Extract specific highlight themes from previously-ingested YouTube videos as vertical (9:16) short clips.
User picks highlights by number (as listed from the highlights page's Key Themes section). The agent lists available highlights first, user picks, agent clips.
yt-dlp (installed via uv tool install yt-dlp into ~/.local/bin/)ffmpeg (system package, usually pre-installed)/opt/data/wiki/ with highlights in consume/highlights/Ensure yt-dlp is on PATH:
export PATH="$HOME/.local/bin:$PATH"
All clips go under /opt/data/clips/<highlight-slug>/:
/opt/data/clips/
├── william-hockey-bet-on-yourself/
│ ├── 01-vc-as-heroin.mp4
│ ├── 03-boring-edge.mp4
│ └── ...
├── alex-sacerdote-investing/
│ └── 02-s-curve-framework.mp4
└── ...
Naming: NN-theme-slug.mp4 where NN is the highlight number (zero-padded, 2 digits).
/opt/data/wiki/consume/highlights/index.md
This page is the canonical browseable index of all highlights with themes, timestamps, and YouTube URLs. Present it to the user in the same outline format it's already in (NOT markdown tables — Slack renders tables poorly).
The index page is maintained alongside highlights and updated when new videos are ingested. Always check it first before falling back to reading individual highlight files.
Only fall back to reading individual highlight pages if the index is stale (missing recent ingestions) or the user asks for more detail on a specific highlight.
User specifies highlights to clip. Formats supported:
For each selected theme number, find its timestamp in the highlight page:
1. Read the highlight markdown file
2. Find the theme section matching the number (e.g., ### 3. The Boring Edge)
3. Extract all timestamps from quotes in that section (e.g., ~40:34, ~37:53)
4. Use the earliest timestamp in the theme section as the clip start point
5. If no timestamp found in the theme section, scan nearby sections for one
For each highlight, use yt-dlp to download a segment:
export PATH="$HOME/.local/bin:$PATH"
OUTDIR="/opt/data/clips/$SLUG"
mkdir -p "$OUTDIR"
Compute start (5s before timestamp) and end (85s after = 90s total)
START=$(python3 -c "
ts='$TIMESTAMP' # e.g., '40:34' or '1:07:08'
parts = ts.strip('~').split(':')
if len(parts) == 2:
total = int(parts[0]) * 60 + int(parts[1])
elif len(parts) == 3:
total = int(parts[0]) 3600 + int(parts[1]) 60 + int(parts[2])
else:
total = 0
start = max(0, total - 5)
print(start)
")
END=$(python3 -c "
ts='$TIMESTAMP'
parts = ts.strip('~').split(':')
if len(parts) == 2:
total = int(parts[0]) * 60 + int(parts[1])
elif len(parts) == 3:
total = int(parts[0]) 3600 + int(parts[1]) 60 + int(parts[2])
else:
total = 0
print(total + 85)
")
Download with yt-dlp
yt-dlp \
--download-sections "*${START}-${END}" \
-f "bestvideo[height<=1080]+bestaudio/best[height<=1080]" \
--merge-output-format mp4 \
-o "${OUTDIR}/raw_${NN}.mp4" \
--force-keyframes-at-cuts \
"$YOUTUBE_URL"
After download, use ffmpeg to crop/reframe to vertical:
ffmpeg -i "${OUTDIR}/raw_${NN}.mp4" \
-vf "crop=ih*9/16:ih,scale=1080:1920:flags=lanczos" \
-c:v libx264 -preset fast -crf 23 \
-c:a aac -b:a 128k \
-movflags +faststart \
"${OUTDIR}/${NN}-${THEME_SLUG}.mp4"
If the source is already vertical, skip the crop and just scale.
rm "${OUTDIR}/raw_${NN}.mp4"
After clipping, report:
Clipped 3 highlights from William Hockey → /opt/data/clips/william-hockey-bet-on-yourself/
01-vc-as-heroin.mp4 (90s, ~20:36–22:06)
03-boring-edge.mp4 (90s, ~40:29–41:59)
05-dollar-as-weapon.mp4 (90s, ~57:56–59:26)
Ready to download.
When the user says "delete clips from William Hockey" or "delete /opt/data/clips/...":
rm -rf /opt/data/clips/$SLUG/
Confirm: "Deleted /opt/data/clips/william-hockey-bet-on-yourself/ (3 clips)."
When the user says "what clips do I have?":
find /opt/data/clips/ -name "*.mp4" -exec ls -lh {} \; 2>/dev/null || echo "No clips found."
The user may reference highlights by topic, not speaker name ("get me s-curve highlight from ..."). Use:
grep -rl "s-curve" /opt/data/wiki/consume/highlights/ --include="*.md" -l
To find the relevant highlight file, then proceed with the normal workflow.
--sleep-interval 5 between clips.~MM:SS pattern, skip it and tell the user which themes were skipped.~ (tilde) timestamps — they're directionally correct but may be ±10s off. The 5s pre-buffer helps.crop=ih9/16:ih:(iw-ih9/16)/2:0 to center-crop.After clipping, verify each file:
ffprobe -v error -show_entries format=duration,size -of csv=p=0 "${OUTDIR}/${NN}-${THEME_SLUG}.mp4"
Confirm duration is 55-95s and file size is reasonable (5-20 MB for 90s at 1080p).