Two passes: chapter the video from its transcript, then cut. Two modes decide who picks the chapters:
- Strip fluff (default): pick the chapters yourself — keep
teaching,demoand plausibly-demono speechchapters, cutpromo/adandfluff— and run both passes without stopping. Report the chapter table and what was kept and cut alongside the finished clip. - Manual selection (when the user asks to choose, or the keep/cut call is genuinely unclear): present the chapter table with a recommended selection, stop, and cut only what they pick. Never download the full video before their selection.
Pass 1: chapter
-
Fetch metadata and captions into the scratchpad, no video download:
yt-dlp --skip-download --write-auto-subs --sub-lang en --convert-subs srt -o "<VIDEO_ID>.%(ext)s" "<URL>" yt-dlp --dump-json "<URL>" | jq '{title, channel, duration_string, upload_date, chapters}'Prefer creator chapters from metadata as a starting skeleton when present. If no captions exist, download audio only and transcribe with the transcribe-audio skill (Parakeet), as in youtube-transcribe.
-
Read the whole SRT and segment it into chapters at topic shifts. Auto-caption quirks: cues overlap and repeat as rolling lines (trust start times, not text boundaries), and timestamps can drift a second or two from the actual speech.
-
Label any stretch longer than roughly 20 seconds with no speech as
no speech— in instructional dance videos that is usually music over a demonstration, which may be exactly the material the user wants, so lean towards keeping it (strip fluff) or flag it for their decision (manual selection). -
Build a numbered chapter table: number, start–end, duration, one-line description, and a tag —
teaching,demo,no speech,promo/ad, orfluff. Every second of the video must fall in exactly one chapter. In strip-fluff mode, select the keepers and continue straight to pass 2. In manual mode, present the table with a recommendation and end with one question: which chapters to include. Stop there.
Pass 2: cut
-
Download the video once:
yt-dlp -f "bv*[height<=1080][ext=mp4]+ba[ext=m4a]/b[height<=1080]" -o "<VIDEO_ID>.%(ext)s" "<URL>" -
Pad each selected chapter by 1 second on each side, then merge selections that touch or overlap. Cut each merged range with a re-encode for frame accuracy, using identical parameters across segments:
ffmpeg -ss <start> -to <end> -i <src>.mp4 -c:v libx264 -crf 19 -preset medium \ -c:a aac -b:a 128k -movflags +faststart seg-01.mp4For a study app, match the library instead: 1080p H.264 around 3 Mbit/s (
-b:v 3M -maxrate 4M -bufsize 8Min place of-crf 19). -
Join with the concat demuxer and stream copy (safe because the segments share encode parameters):
printf "file 'seg-01.mp4'\nfile 'seg-02.mp4'\n" > list.txt ffmpeg -f concat -safe 0 -i list.txt -c copy <output>.mp4 -
Verify with ffprobe that the output duration matches the sum of the merged ranges within a couple of seconds, name the file after the video slug plus chapter numbers, and hand it to the user. Offer to nudge boundaries — caption drift means a cut can clip a sentence or a demonstration's first beat.