How the Download Module Uses yt-dlp to Fetch Captions and Extract Audio/Video in claude-video
The download module in claude-video wraps yt-dlp in Python subprocess calls, using --skip-download for caption-only retrieval and format selectors with -N 8 parallelism for audio/video extraction.
The download module (skills/watch/scripts/download.py) is the core media handler in the bradautomates/claude-video repository. It provides a clean Python interface to yt-dlp for downloading YouTube and other platform videos, extracting English captions in VTT format, and resolving local file paths. This article breaks down exactly how the module orchestrates yt-dlp subprocess calls, constructs format selectors, and processes the resulting metadata.
Core Functions and Their yt-dlp Invocation Patterns
The module exposes three primary entry points, two of which invoke yt-dlp directly.
fetch_captions() — Caption Retrieval Without Video Download
When you only need subtitles and metadata, fetch_captions(url, out_dir) (lines 67-95) invokes yt-dlp with --skip-download to avoid transferring video bytes.
The command array built at lines 73-86 includes these critical options:
--skip-download— Prohibit video download entirely--write-info-json— Save metadata tovideo.info.json--write-subsand--write-auto-subs— Request both manual and auto-generated subtitles--sub-langs en.*— Filter for English language tracks only--sub-format vttand--convert-subs vtt— Force VTT output for downstream parsing--no-playlistand--ignore-errors— Single video focus with fault tolerance-o video.%(ext)s— Predictable output naming
The function returns a dict with video_path: None and downloaded: False (lines 91-95), signaling that no media file was produced.
download_url() — Full Video or Audio-Only Download
For actual media retrieval, download_url(url, out_dir, audio_only=False) (lines 26-62) constructs a format-aware yt-dlp command.
Format selector logic (line 26):
fmt = "bestaudio/best" if audio_only else "best[height<=720]/best[height<=720]"
This caps video resolution at 720p—sufficient for frame extraction while minimizing bandwidth and storage.
The full command assembled at lines 28-43 adds:
-N 8— Download 8 fragments in parallel for speed-f <fmt>— Inject the format selector above--merge-output-format mp4— Uniform container format- All caption options from
fetch_captions()for simultaneous subtitle retrieval
Post-execution, _pick_video() (lines 55-62) locates the downloaded file, _pick_subtitle() (lines 44-52) selects the best VTT, and _read_info() (lines 98-112) parses the JSON metadata.
resolve_local() — Local File Path Handling
For non-URL inputs, resolve_local(path) validates the file exists and returns a corresponding dict without any yt-dlp invocation. This ensures the download() dispatcher (lines 20-25) handles both remote and local sources uniformly.
URL Detection and Dispatch Flow
The module's entry point download() follows this decision tree:
is_url()(lines 20-25) tests if the source string matches^https?://- If URL: forward to
download_url()orfetch_captions()depending on caller intent - If local path: delegate to
resolve_local()
from pathlib import Path
from skills.watch.scripts.download import download, fetch_captions
# Download video + captions
result = download(
"https://www.youtube.com/watch?v=abc123XYZ",
Path("/tmp/watch-output"),
audio_only=False # Set True for audio-only extraction
)
# Or fetch captions without downloading video
captions_only = fetch_captions(
"https://vimeo.com/987654321",
Path("/tmp/captions")
)
Post-Processing: File Selection and Metadata Extraction
After yt-dlp completes, three helper functions standardize the output:
| Function | Purpose | Lines |
|---|---|---|
_pick_video() |
Scan output directory for video file (prefers .mp4, falls back to any video extension) |
55-62 |
_pick_subtitle() |
Select best VTT subtitle, preferring en over en-* variants |
44-52 |
_read_info() |
Parse video.info.json for title, uploader, duration, and canonical URL |
98-112 |
The final returned dict contains:
{
"video_path": "/tmp/watch-output/video.mp4", # or None if --skip-download
"subtitle_path": "/tmp/watch-output/video.en.vtt",
"info": {
"title": "Video Title",
"uploader": "Channel Name",
"duration": 123,
"url": "https://www.youtube.com/watch?v=abc123XYZ"
},
"downloaded": True # or False for caption-only mode
}
Why yt-dlp Over Other Tools
The claude-video project selected yt-dlp based on source code implementation priorities evident in download.py:
Reliability across platforms — yt-dlp handles YouTube, Vimeo, and hundreds of other extractors without API keys or rate-limit complications.
Native subtitle pipeline — The --sub-langs en.* → --convert-subs vtt chain produces immediately usable captions for transcribe.py, bypassing Whisper when manual subtitles exist.
Performance tuning — The -N 8 parallelism and 720p format ceiling balance speed against downstream processing needs (frame extraction at 720p yields sufficient detail for most computer vision tasks).
Predictable output structure — The -o video.%(ext)s template ensures download.py can locate files without parsing yt-dlp's verbose stdout.
Integration with the Watch Pipeline
The download module serves as the first stage in the /watch slash-command pipeline:
watch.pyreceives user URL or path inputdownload.pyproduces video file, VTT captions, and metadata dictframes.pyextracts representative frames from the videotranscribe.pyconsumes VTT captions directly, or falls back to Whisper audio transcription
This architecture makes yt-dlp's output contracts (VTT format, JSON info schema) critical integration points across the codebase.
Summary
fetch_captions()uses--skip-downloadfor metadata + subtitle retrieval without video transferdownload_url()builds format selectors (best[height<=720]orbestaudio) with-N 8parallelism- Both functions enforce VTT subtitle output via
--convert-subs vttfor downstream compatibility - Post-processing helpers (
_pick_video,_pick_subtitle,_read_info) standardize yt-dlp's variable output into predictable Python dicts - The 720p ceiling optimizes the storage/quality trade-off for frame-extraction workflows
Frequently Asked Questions
What video quality does claude-video download by default?
The download_url() function caps video at 720p using the format selector best[height<=720]/best[height<=720]. This resolution provides adequate detail for frame extraction while minimizing download time and storage. For audio-only extraction, set audio_only=True to select bestaudio/best instead.
Can I use the download module for platforms other than YouTube?
Yes. The module invokes yt-dlp generically without platform-specific logic, so any site supported by yt-dlp (Vimeo, Twitter, Reddit, etc.) works automatically. The --no-playlist flag ensures single-video handling regardless of source.
How does the module handle videos without English captions?
If yt-dlp finds no English subtitles matching --sub-langs en.*, the _pick_subtitle() helper returns None in the result dict. Downstream transcribe.py detects this absence and falls back to Whisper audio transcription. The video still downloads successfully.
Is parallel downloading configurable?
The -N 8 fragment parallelism is hardcoded in download_url() at lines 28-43. Modifying this requires editing the source. The value balances speed against connection overhead for typical residential and cloud bandwidth profiles.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →