Extract and publish the transcript from a YouTube video: $ARGUMENTS
$ARGUMENTS should include:
- A YouTube URL (e.g.
https://www.youtube.com/watch?v=VIDEO_ID,https://youtu.be/VIDEO_ID) - Optionally:
--output DIR— directory for the final.mdfile (default:transcripts/) - Optionally:
--timestamps— include a Timestamped reference section (default: include it when useful for long videos; omit only if user asks for plain prose only) - Optionally:
--language LANG— subtitle language code (default:en)
Non-negotiable: content fidelity
The transcript is source material, not a summary. Every edit must preserve meaning and coverage.
- Do not remove substantive speech — No paraphrasing that drops claims, examples, numbers, names, or definitions. No “condensing” that deletes sentences the speaker said.
- Safe cleanup only — You may remove: VTT artifacts, duplicate consecutive lines from auto-captions, filler stutters only when they are exact repeats with no added meaning (
the the→the), broken cue fragments that are pure duplicates of adjacent text, and obvious non-speech ([Music],[Applause]— optional to keep in italics if they matter for context). - Deduplication rule — Collapse repeats only when the current line is identical (after trim) to the immediately previous line. Do not merge distinct sentences that happen to share a phrase.
- Verify before write — After building the readable transcript, sanity-check against the raw cue list:
- Rough word count of the cleaned body should be ≥ ~85–90% of the raw concatenated cue text (allowance for true duplicates and junk). If it drops far below, you removed too much — restore content.
- If the video is long, spot-check opening, middle, and closing segments against the VTT: no missing paragraphs or skipped timestamp ranges.
- If unsure, keep the text — When cleaning is ambiguous, preserve the longer/original wording.
Before starting
Parse the video ID from the provided URL. Accept:
youtube.com/watch?v=VIDEO_IDyoutu.be/VIDEO_IDyoutube.com/embed/VIDEO_IDyoutube.com/v/VIDEO_ID- Bare video ID (11 characters, alphanumeric +
-/_) - If none match, ask for a valid link.
Check for
yt-dlp:which yt-dlp. If missing:yt-dlp is required. Install: pip install yt-dlpEnsure output directory exists — Create
transcripts/or the user’s--outputdirectory.
Step 1 — Fetch video metadata
yt-dlp --print title --print id --print uploader --print channel_id --print duration_string --print upload_date --no-download "VIDEO_URL"
Capture: title, id, uploader (channel name), duration, upload_date. Use these for the file header and filename.
Step 2 — Download subtitles
Try in order until a .vtt exists:
2a — Manual subtitles
yt-dlp --write-subs --sub-lang LANG --skip-download --sub-format vtt -o "transcripts/%(id)s" "VIDEO_URL"
2b — Auto-generated (fallback)
yt-dlp --write-auto-subs --sub-lang LANG --skip-download --sub-format vtt -o "transcripts/%(id)s" "VIDEO_URL"
If neither produces .vtt:
No subtitles available (language: LANG). Captions may be disabled; try --language with another code.
Use a 60s timeout on these commands; report timeout if it fails.
Step 3 — Parse VTT (preserve content)
Read the .vtt and build an internal cue list before any prose shaping:
- Strip
WEBVTT,Kind:,Language:, cue IDs, positioning (<c>,align:,position:). - Strip HTML tags (
<b>,<i>,<u>,<font>, etc.); keep the inner text. - Parse timestamps
HH:MM:SS.mmm --> HH:MM:SS.mmmand attach text lines to each cue. - Deduplicate only consecutive identical lines (auto-subs).
- Keep the full cue sequence in memory for verification and for the timestamped section.
Paragraph breaks (readable body): Join cues into paragraphs where:
- There is a gap ≥ 3 seconds between cues, or
- A clear topic shift (new section, rhetorical reset) without losing intervening sentences.
Do not drop cues to “improve flow.”
Step 4 — Intuitive filename
Save as kebab-case from the video title, ASCII-only, lowercase, with a short id suffix for stability and deduplication.
Pattern: {slug-from-title}-{video_id}.md
- Slug rules: Lowercase; replace spaces and underscores with
-; strip punctuation except hyphens; collapse multiple hyphens; max ~60 characters from the title portion (trim whole words if needed); keep the full 11-charvideo_idat the end. - Examples:
- Title “AutoResearch with Claude Code” + id
abc123xyz01→autoresearch-with-claude-code-abc123xyz01.md - If the user’s project already uses a folder like
lab/youtube/ai/, place the file there when they specify--output lab/youtube/ai.
- Title “AutoResearch with Claude Code” + id
Never use only the raw video id as the filename unless the user explicitly requests it.
Step 5 — Markdown structure (organization)
Write one .md file with this section order. Adapt headings to the video (e.g. add ## Part 1 — … only when the talk has clear movements), but keep the core blocks:
---
title: "FULL VIDEO TITLE"
video_id: VIDEO_ID
url: https://www.youtube.com/watch?v=VIDEO_ID
channel: "CHANNEL / UPLOADER NAME"
duration: DURATION
uploaded: UPLOAD_DATE
extracted: ISO_DATE
subtitle_type: manual | auto-generated
language: LANG
source: youtube-transcript skill
---
# FULL VIDEO TITLE
Brief one- to three-sentence **overview** of what the video covers (accurate to the transcript; no invented claims).
## Key topics
- Bullet list of 3–8 themes **actually discussed** in the transcript (scan headings/cues; do not hallucinate).
## Transcript
Readable, **paragraph-structured** transcript. Use `###` subheadings only when the speaker clearly changes major topic or after long gaps (optional but improves scanability).
[All substantive spoken content belongs here — this is the canonical body.]
## Timestamped reference
Only if `--timestamps` is on, or by default for videos longer than ~15 minutes, or when the user will need to jump to moments:
Use one block per cue or group adjacent cues in the same minute:
`[MM:SS] Text...`
For videos under ~15 minutes with no timestamp flag, you may omit this section if the user asked for minimal output; otherwise include it.
## Chapters (optional)
If YouTube chapter titles are present in the description **or** obvious in the speech, add a small table: `| Start | Chapter |` with links `https://www.youtube.com/watch?v=VIDEO_ID&t=Xs`.
Formatting habits:
- Escape YAML double quotes in
title/channelif needed. - Use proper markdown lists and
###for intra-transcript sections sparingly. - No wall-of-giant-paragraph: break every ~4–8 sentences for readability without deleting sentences.
Step 6 — Clean up
Delete the intermediate .vtt (and any .part files) after the markdown is written and verified.
Output message to user
After saving:
## Transcript saved
- **Video**: TITLE
- **Channel**: UPLOADER
- **Duration**: DURATION
- **Subtitles**: manual | auto-generated
- **Approx. words** (body): N
- **Fidelity check**: raw cue words ≈ M; retained ratio OK / note if borderline
- **File**: path/to/slug-title-VIDEO_ID.md
Error handling
- Invalid URL — Ask for a valid YouTube link.
- yt-dlp missing — Install instructions; stop.
- No subtitles — Clear message; suggest
--language. - Network / timeout — Report; suggest retry.
- Language mismatch — Try
en,en-US, or list available tracks viayt-dlp --list-subsif needed.