Make Lyric Recap Video
Build one project in two independently callable phases: approve subtitle timing first, then edit the visual montage against that approved timing. Keep both phases in one skill because they share the audio duration, subtitle file, frame geometry, typography, and QA rules.
Choose the project profile
- Use
single-eventfor one activity whose story is mainly a sequence of stages. - Use
multi-day-coursefor a course spanning multiple dates. Keep day order visible while preserving one overall emotional arc. Read references/multi-day-course.md. - Use the same scripts and timeline schema for both profiles. The profile changes media mapping, chapter names, review checkpoints, and story structure—not the rendering engine.
Choose the phase
- If the user asks to check or fix synchronization, run Phase A only. Do not select media yet.
- If the user provides media after approving synchronization, preserve the approved SRT and run Phase B.
- If the user asks for the complete result immediately, still create a subtitle-check video first unless they explicitly waive approval.
- If the user asks to optimize an existing cut, keep the approved SRT and start with the Phase B review loop.
Phase A: make and approve subtitle timing
- Probe the exact audio duration with
ffprobe. - Obtain or create SRT cues. Treat a lyric text file as content, not timing evidence.
- Validate cue order, overlaps, and end time with
scripts/srt_tools.py validate. - Render the transparent subtitle frames with
scripts/render_graphics.py subtitles, using the Pillow Python reported byscripts/find_pillow_python.zsh. - Build a black-background review video with
scripts/render_subtitle_check.zsh. - Review cue boundaries around phrase onsets and endings. Adjust the SRT, rerender, and repeat until the user approves it.
- Preserve the approved SRT under a clearly versioned name. Never silently regenerate or retime it during Phase B.
Read references/subtitle-sync.md when creating or correcting timings.
Phase B: select media and edit the recap
- For a new project, run
scripts/prepare_media_incremental.mjswith--proxies. It creates stable photo/video IDs, normalized previews, full-resolution render-safe JPEGs for HEIC sources, sampled frames, reusable 720p proxies, media indexes, and a cache report. Use the legacyprepare_media.zshonly for an existing project that already depends on its generated indexes. - Review
media_flow_mapping.tsvand fill in day, stage, priority, status, and notes when the source folders or capture times do not establish the activity order. Read references/media-flow-mapping.md. - Run
scripts/make_contact_sheets.zshto create review sheets labeled with display ID and filename. Inspect every sheet before authoring the timeline. - Group the story into an emotional arc such as arrival, connection, challenge, reflection, release, and closing. Match literal lyric ideas only when it feels natural.
- Create a TSV manifest using references/timeline-manifest.md. Ensure display durations sum to the exact audio duration.
- Render the title card with
scripts/render_graphics.py title, using the Pillow Python reported byscripts/find_pillow_python.zsh. Use--heading-sizeor--subtitle-sizewhen review feedback calls for different title prominence. - During revision, render with
scripts/render_montage_cached.mjs --mode draft; use--range START:ENDor the optional manifest chapter column for local review. Reuse unchanged segment and chunk caches. - Build review MP4s with
scripts/assemble_review_cached.mjs --mode draft. It clips audio and SRT for a selected range and reuses unchanged subtitle/output caches. - After picture lock, rerun the cached montage and assembly scripts with
--mode final,photos_final.tsv, original videos, full-range audio, and the approved SRT. - Probe and fully decode the final file, then visually inspect the opening, each story transition, all dark footage, subtitle-heavy shots, and the last lyric.
Read references/editing-guidelines.md before selecting shots or revising an existing cut. Read references/fast-iteration.md before creating proxies, rendering a partial range, or invalidating caches.
Output requirements
- Default to 1920x1080, 30 fps, H.264 video, AAC audio,
yuv420p, and limited-range Rec.709 unless the user requests another delivery format. - Mute source-video audio unless the user explicitly wants ambient sound mixed in.
- Keep the montage duration within one frame of the song duration.
- Preserve the subtitle-check video, approved SRT, timeline TSV, base montage, and final MP4 as separate files.
- Preserve proxy, segment, chunk, subtitle, and output caches between review versions. Delete a cache only when its report or validation proves it stale.
- Use versioned output names; never overwrite an approved deliverable.
- Report what changed, cache hits/misses, render mode, selected range, elapsed time, and clickable links to the output and timeline.
Quality gate
Do not call the result complete until all checks pass:
ffprobeconfirms expected duration, codecs, dimensions, frame rate,yuv420p,color_range=tv, and BT.709 color metadata.- A full null-output decode completes without errors.
- No black gaps, frozen frames caused by short trims, missing assets, or stretched aspect ratios appear.
- Subtitle text is legible on both bright and dark shots and does not cover important faces.
- Crossfades do not create distracting double faces; prefer
fadeblackat crowded or emotionally decisive cuts. - Night footage remains believable after brightening and does not become noisy or washed out.
- The final image has enough hold time for emotional closure and fades cleanly with the music.