# How yt-dlp Integration Works in Claude-Video for Automated Video Downloads

> Discover how Claude-Video integrates yt-dlp to automate video downloads. Learn about deterministic command lines, URL detection, and standardized MP4/VTT output.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: how-to-guide
- Published: 2026-08-07

---

**Claude-Video uses a Python wrapper in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py) that constructs deterministic yt-dlp command lines to either fetch metadata and subtitles only or perform full video downloads, automatically detecting URLs versus local file paths and post-processing outputs into standardized MP4 and VTT formats.**

The bradautomates/claude-video repository implements a robust video ingestion pipeline by wrapping **yt-dlp** in a thin abstraction layer. This integration handles everything from bandwidth-efficient subtitle retrieval to high-performance parallel video downloads, ensuring reliable media processing for AI-powered video analysis.

## Source Detection and URL Validation

Before initiating any download operation, the system determines whether the user input is a remote URL or a local file path. In [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py), the `is_url()` function (lines 20-25) performs this validation, branching the execution flow accordingly.

- **Local paths** bypass yt-dlp entirely and proceed directly to file validation.
- **Remote URLs** trigger the yt-dlp wrapper logic, beginning with either metadata retrieval or full download depending on the caller's requirements.

This early branching prevents unnecessary network operations when users provide locally stored media files.

## Metadata-Only Retrieval for Bandwidth Efficiency

When the system only needs to verify subtitle availability or extract video metadata without downloading the full media stream, the `fetch_captions()` function (lines 66-86) constructs a lightweight yt-dlp command. This approach conserves bandwidth by skipping the actual media download while still retrieving structured data and caption files.

The function passes the following flags to yt-dlp:

- `--skip-download` – Prevents media file retrieval
- `--write-info-json` – Outputs structured metadata to a JSON file
- `--write-subs` and `--write-auto-subs` – Retrieves both manual and auto-generated captions
- `--sub-langs en.*` – Filters for English language subtitles
- `--sub-format vtt` and `--convert-subs vtt` – Standardizes output to WebVTT format

This metadata-first strategy allows the `/watch` skill to check for existing transcripts before committing to a full video download.

## Full Video Download with Parallel Processing

For complete media ingestion, the `download_url()` function (lines 26-44 and 126-152) assembles a comprehensive yt-dlp command optimized for speed and compatibility. The wrapper automatically configures format selection, parallel downloads, and post-processing.

Key implementation details include:

- **Format selectors** – Uses `bv*[height<=720]+ba` for video+audio up to 720p, or `ba/bestaudio` for audio-only mode when processing transcripts without visual analysis
- **Parallelism** – The `-N 8` flag enables 8 concurrent fragment downloads to maximize throughput
- **Output standardization** – `--merge-output-format mp4` ensures consistent container formats across different source platforms
- **Error resilience** – `--ignore-errors` and `--no-playlist` prevent single-video failures from cascading and restrict downloads to the specific URL provided

After the subprocess completes, helper functions `_pick_video()` and `_pick_subtitle()` (lines 44-63 and 98-111) locate the generated files within the output directory. If no video file is detected, the wrapper raises an explicit error (lines 49-52) to halt downstream processing.

## Orchestration Logic in the Watch Skill

The high-level entry point in [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) (lines 97-123) implements intelligent fallback logic to minimize unnecessary data transfer. First, it calls `fetch_captions()` to check for existing subtitles without downloading the video file. Only if captions are missing **or** if the user explicitly requests frame extraction does the system invoke the full `download()` function.

This tiered approach ensures that transcript-only queries complete in seconds rather than minutes, while still supporting full video analysis when visual content is required.

## Binary Validation and Dependency Management

The integration relies on three external binaries: **yt-dlp**, **ffmpeg**, and **ffprobe**. The [`setup.py`](https://github.com/bradautomates/claude-video/blob/main/setup.py) file defines these requirements in the `REQUIRED_BINARIES` list (line 35), while [`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py) (lines 66-68) verifies their presence before executing any commands.

If yt-dlp is not found in the system PATH, the script aborts with installation instructions for Homebrew, pip, or Winget package managers. This pre-flight check prevents cryptic subprocess errors and ensures users receive actionable remediation guidance.

## Practical Implementation Examples

### Downloading a Full Video with Subtitles

```python
from pathlib import Path
from skills.watch.scripts.download import download

# Download a YouTube video into a temporary directory

out = download(
    source="https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    out_dir=Path("/tmp/watch-demo"),
    audio_only=False,
)

print("Video saved at:", out["video_path"])
print("Subtitle (VTT) path:", out["subtitle_path"])
print("Metadata:", out["info"])

```

### Retrieving Only Subtitles Without Media

```python
from skills.watch.scripts.download import fetch_captions
from pathlib import Path

info = fetch_captions(
    url="https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    out_dir=Path("/tmp/watch-captions")
)

print("Subtitle path (if any):", info["subtitle_path"])
print("Video title from info‑json:", info["info"].get("title"))

```

### Using the Watch Command Line Interface

```bash
python -m skills.watch.scripts.watch \
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ" \
    --detail balanced \
    --resolution 720

```

The CLI automatically selects between metadata-only and full download modes based on the requested detail level and existing caption availability.

## Summary

- **URL Detection** – The `is_url()` function in [`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py) (lines 20-25) distinguishes between local files and remote URLs before invoking yt-dlp.
- **Two-Path Architecture** – `fetch_captions()` retrieves only metadata and VTT files, while `download_url()` performs full media extraction with parallel downloading enabled by the `-N 8` flag.
- **Format Optimization** – Dynamic format selectors ensure videos do not exceed 720p unless specified, with automatic fallback to audio-only for transcript-focused workflows.
- **Post-Processing** – Helper functions `_pick_video()` and `_pick_subtitle()` standardize output handling, ensuring downstream components receive predictable file paths.
- **Dependency Safety** – [`setup.py`](https://github.com/bradautomates/claude-video/blob/main/setup.py) (line 35) and [`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py) (lines 66-68) enforce binary prerequisites before execution, preventing runtime failures.

## Frequently Asked Questions

### How does Claude-Video handle missing yt-dlp installations?

The system validates the presence of yt-dlp, ffmpeg, and ffprobe before executing any download commands. In [`skills/watch/scripts/setup.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/setup.py) (line 35), the `REQUIRED_BINARIES` list defines these dependencies, and [`download.py`](https://github.com/bradautomates/claude-video/blob/main/download.py) (lines 66-68) checks for their availability. If yt-dlp is missing, the script exits immediately with platform-specific installation instructions for Homebrew, pip, or Winget.

### Can the integration download videos without subtitles?

Yes. While the default configuration retrieves both media and subtitles, you can modify the `download_url()` behavior by adjusting the command construction in [`skills/watch/scripts/download.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/download.py). The current implementation always includes subtitle flags for comprehensive AI analysis, but the `--write-subs` and related flags can be removed from the argument list if only the video file is required.

### What happens if a video download fails or returns no file?

The wrapper implements explicit error handling in `download_url()` (lines 49-52). If the `_pick_video()` helper cannot locate a media file after the yt-dlp subprocess completes, the function raises a `FileNotFoundError` with a descriptive message. This prevents the pipeline from attempting to process non-existent files and provides clear feedback for debugging URL or format selector issues.

### How does the system decide between metadata-only and full downloads?

The decision logic resides in [`skills/watch/scripts/watch.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/watch.py) (lines 97-123). The code first attempts `fetch_captions()` to check for existing VTT subtitles without downloading the video. Only if no captions are found, or if the user explicitly requests frame extraction (visual analysis), does the system proceed to the full `download()` path. This tiered approach minimizes bandwidth usage for transcript-only queries.