YouTube Transcript (via yt-dlp)
SkillMediaUse whenever the user needs the transcript of a YouTube video — fetching, extracting, downloading, or pulling captions/subtitles/transcript text from a YouTube URL. Triggers on "get the transcript", "transcript of this video", "pull the captions", "download subtitles", "what does this YouTube video say".
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the YouTube Transcript (via yt-dlp) skill
What this skill tells your AI
The instructions your AI receives, as published by matyasstoch/david-skills in skills/youtube-transcript/SKILL.md and read by ahel’s review.
Fetch a YouTube video's captions (no video download) and save a clean raw .txt transcript.
Save location
- If the user is in a real project/working dir → save there.
- Otherwise (no dir given, or cwd makes no sense) → save to
~/Downloads.
Fastest path
OUT="$(pwd)" # or ~/Downloads if cwd makes no sense
META=$(yt-dlp --print "%(channel)s|%(title)s" --skip-download "URL")
NAME=$(echo "$META" | tr '| ' '__' | tr -cd '[:alnum:]_.-') # "Channel_Title", spaces -> _, strip unsafe chars
yt-dlp --skip-download --write-subs --write-auto-subs \
--sub-langs "en.*" --sub-format json3 \
-o "$OUT/$NAME.%(ext)s" "URL"
Always name the file Channel_Title with spaces replaced by _ (e.g. David_Ondrej_title_of_video.txt). Fall back channel → uploader → uploader_id if channel is null.
--skip-download= captions only.--write-subs+--write-auto-subs= manual first, auto as fallback (yt-dlp prefers manual automatically).- Always use
json3, never VTT/SRT — auto VTT repeats every line twice (rolling captions). json3 is clean structured JSON.
Flatten json3 → raw text
python3 - "$OUT" <<'PY'
import json, html, re, glob, sys, pathlib
f = glob.glob(sys.argv[1] + "/*.json3")
if not f: sys.exit("no json3 file")
data = json.load(open(f[0], encoding="utf-8"))
parts = ["".join(s.get("utf8","") for s in e.get("segs") or []) for e in data.get("events", [])]
txt = re.sub(r"\s+", " ", html.unescape(" ".join(p.strip() for p in parts if p.strip()))).strip()
out = pathlib.Path(f[0]).with_suffix(".txt")
out.write_text(txt, encoding="utf-8"); print(out)
PY
Output: <video_id>.txt in the chosen dir. Report the path; print the text if short.
Notes
- Non-English / unknown language: run
yt-dlp --list-subs "URL"first, then set--sub-langs. - Newer yt-dlp may need
denoon PATH for YouTube extraction.
Failure handling
- On first failure: run
yt-dlp -Uonce, retry once, then stop. - 429 / "Sign in to confirm you're not a bot" = IP flagged. STOP — do NOT retry in a loop (makes it worse).
- Empty / "no subtitles" = video has no captions. Report it; don't retry, don't switch tools.
- Never fall back to downloading audio for Whisper unless the user explicitly asks.
Signals
- GitHub stars
- 59
- Forks
- 11
- Last commit
- Jun 2026
Advanced
- Catalog kind
- skill
- Gateway key
youtube-transcript-matyasstoch- Source
- github.com/matyasstoch/david-skills