Skip to content
Agentmart
Submit a tool

youtube-dlp-python

Download YouTube video transcripts (subtitles/captions) using yt-dlp, with faster-whisper as fallback for local transcription.

Skill by Jansen611

IndexedMIT★ 2
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/jansen611-youtube-dlp-python

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Download YouTube video transcripts (subtitles/captions) using yt-dlp, with faster-whisper as fallback for local transcription. Supports manual subtitles, auto-generated captions, and Whisper transcription when the subtitle API is blocked. Optionally fetches YouTube comments (top/most-recent sorted) via yt-dlp. Triggers when user mentions: - Provides a YouTube URL and wants the transcript - "download transcript" or "get captions/subtitles" from a YouTube video

Use cases: backend

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Python package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/youtube-dlp-python

Tools it pre-approves 1

From allowed-tools in SKILL.md: the agent may use these without asking you each time.

  • Bash,Read,Write

What's inside

Skill name
youtube-dlp-python
Description
Download YouTube video transcripts (subtitles/captions) using yt-dlp, with faster-whisper as fallback for local transcription. Supports manual subtitles, auto-generated captions, and Whisper transcription when the subtitle API is blocked. Optionally fetches YouTube comments (top/most-recent sorted) via yt-dlp. Triggers when user mentions: - Provides a YouTube URL and wants the transcript - "download transcript" or "get captions/subtitles" from a YouTube video
License
MIT
Allowed tools
Bash,Read,Write
Instructions
113 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts
  • Pre-approves some shell commands

Files (4)

  • SKILL.md
  • fetch_comments.py · scripts/
  • vtt_to_transcript.py · scripts/
  • whisper_fallback.py · scripts/

SKILL.md (first lines)

# YouTube Transcript Downloader

Download transcripts from YouTube. Primary: yt-dlp subtitles (instant, free). Fallback: faster-whisper local transcription when the subtitle API is blocked or no subtitles exist.

All Python scripts live in `$SKILL_DIR/scripts/`.

## Decision

1. Check subtitles first: `yt-dlp --list-subs "URL"`. If any exist → **Path A (yt-dlp subtitles)**.
2. If no subtitles exist, or Path A cannot download a usable subtitle after trying its track-selection order → **Path B (Whisper fallback)**. Do NOT retry the same failed track; audio downloads use a different CDN and are normally unaffected.

## Environment Check

```bash
# yt-dlp: try PATH, then macOS ~/.zshrc, then ~/.venv; install only if all fail.
# (macOS: VS Code's terminal may not load ~/.zshrc, so source it manually.)
source ~/.zshrc 2>/dev/null
export PATH="$HOME/.venv/bin:$PATH"
command -v yt-dlp >/dev/null || ~/.venv/bin/pip install -U "yt-dlp[default]"

# faster-whisper (installs PyAV automatically) -- only needed for Path B
~/.venv/bin/python3 -c "from faster_whisper import WhisperModel; import av" 2>/dev/null \
  || ~/.venv/bin/pip install faster-whisper
```

## Output Location

Let the caller decide: user-specified path > AGENTS.md convention > current working directory. Do NOT hardcode a machine-specific path.

Filename is always `Youtube-<Channel>-<Snake_Case_Title>.md`, and **the first line must be** `Source: [Title](URL)`.

## Path A: yt-dlp Subtitles (Preferred)

Within Path A, select the language in this order:

1. Determine the video's source language from its title (unless the user explicitly requests a different language; for example, English/Latin → `en`, Simplified Chinese → `zh-Hans`, Traditional Chinese → `zh-Hant`).
2. If `Available subtitles` contains a manual track in that language, use it.
3. Otherwise, use the matching original-language automatic track whose exact code ends in `-orig` (for example, `en-orig`).
4. If no matching `-orig` track exists, use the non-`-orig` automatic track for the video's source language (for example, `en`, `zh-Hans`, or `zh-Hant`).

Use `--write-sub` for manual subtitles and `--write-auto-sub` for automatic captions. If a track returns 429/403, do not retry that track; continue with the next candidate in this order, then use Path B if all candidates fail.

```bash
VIDEO_URL="YOUTUBE_URL"

# 1. Check subtitles -- read full output, don't grep. Keep the two sections separate.
yt-dlp --list-subs "$VIDEO_URL"

# 2. Get title/channel and derive snake_case filename
TITLE=$(yt-dlp --get-title "$VIDEO_URL" | sed 's/[/:*?"<>|]/-/g')
CHANNEL=$(yt-dlp --print channel "$VIDEO_URL" | sed 's/^NA$//')
snake_case() { echo "$1" | sed 's/[^[:alnum:]]/_/g' | sed 's/__*/_/g' | sed 's/^_//;s/_$//'; }
CHANNEL_SNAKE=$(snake_case "$CHANNEL")
SNAKE_TITLE=$(snake_case "$TITLE")
OUTPUT_MD="Youtube-${CHANNEL_SNAKE:+$CHANNEL_SNAKE-}$SNAKE_TITLE.md"

# 3. Determine the video's source language from TITLE, then select one track in this
#    order: manual source-language subtitle, source-language automatic -orig track,
#    and finally the regular source-language automatic track.
#    Copy the exact language code from --list-subs; manual and automatic codes can
#    differ (for example, zh-Hans vs zh-Hans-zh-Hans). Run only one command below.
#    Manual subtitle:
yt-dlp --write-sub --sub-langs <manual-lang> --skip-download --output "$TITLE" "$VIDEO_URL"
#    Automatic subtitle (-orig or regular source language):
yt-dlp --write-auto-sub --sub-langs <orig-or-title-lang> --skip-download --output "$TITLE" "$VIDEO_URL"

# 4. Verify the .vtt was actually written before converting. If missing, the
#    flag/lang-code combo was wrong (see step 3) or the subtitle API is blocked.
ls "$TITLE.<lang>.vtt"

# 5. Convert VTT to timestamped transcript
echo "Source: [$TITLE]($VIDEO_URL)" > "$OUTPUT_MD"
echo >> "$OUTPUT_MD"
python3 "$SKILL_DIR/scripts/vtt_to_transcript.py" "$TITLE.<lang>.vtt" >> "$OUTPUT_MD"
```

Note: the bash `snake_case` strips non-ASCII. For CJK/non-ASCII titles, prefer Path B's naming (Python `\w+` keeps Unicode), or sanitize the title in Python.

## Path B: Whisper Fallback (HTTP 429/403 or No Subtitles)

```bash
python3 "$SKILL_DIR/scripts/whisper_fallback.py" "YOUTUBE_URL" [--lang zh] [--model large-v3-turbo] [--outdir .]
```

- `--lang`: source language (e.g. `zh`, `en`). Default: **auto-detect** from audio — do not force English; pick per video (CJK videos → `zh`).
- `--model`: `large-v3-turbo` (default, ~1.62GB, recommended quality/speed balance) → `medium` (~1.53GB) → `small` (~484MB, faster) → `large-v3` (~3.09GB, maximum quality but slower). `tiny` and `base` are also available for low-resource use.
- The script downloads audio → transcribes on CPU → writes the `.md` → deletes the audio.

## Optional: Fetch Comments (Read-Only)

```bash
python3 "$SKILL_DIR/scripts/fetch_comments.py" "YOUTUBE_URL" [--sort top|newest] [--max 80]
```

No files written. Gotchas are documented in the script's docstring.

## Output Formats

- `.vtt`: raw subtitle file with timing markup (Path A only)
- `.md`: `Youtube-<Channel>-<Snake_Case_Title>.md` with line-level timestamps `[00:01:23.456] text here` (both paths)

## Common Issues

| Error | Solution |
|-------|----------|
| `command not found: yt-dlp` | `source ~/.zshrc`, then check `~/.venv/bin` |
| `No subtitles for requested languages` | flag/lang-code mismatch: manual subs (`--write-sub`) are under "Available subtitles", auto (`--write-auto-sub`) under "Available automatic captions" with different codes (`zh-Hans` vs `zh-Hans-zh-Hans`). Copy the exact code from `--list-subs`. |
| `HTTP Error 429/403` on subtitle | Do NOT retry the same track; try the next distinct candidate in the manual → `-orig` → title-language order, then use Path B. |
| Exit code is 0 even on failure | yt-dlp returns 0 for both "no subtitles" and 429. Do NOT trust exit codes — verify the `.vtt` file exists (step 4) and read the error text. |
| `ModuleNotFoundError: faster_whisper` / `av` | `~/.venv/bin/pip install faster-whisper` (installs `av`) |
| `Cannot write video metadata to JSON file` | Restricted dir → `--dump-single-json` to stdout |

From Jansen611/Agent-Skills, MIT.

Signals

Stars
2
Forks
0
Open issues
0
Last commit (this folder)
Sep 12, 2026 (1 month ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from Jansen611

Cite this page

youtube-dlp-python skill. Agent Mart. https://agentmart.dev/skills/jansen611-youtube-dlp-python (last updated 2026-10-24)