# Make Lyric Recap Video

> Create lyric-synchronized single-event or multi-day course recap videos from a song, subtitles, photos, and short videos. Use when Codex must produce a subtitle timing video, revise synchronization, inventory and map event media, build or optimize an emotionally paced montage, make fast proxy or chapter previews, reuse incremental render caches, burn in lyric subtitles, or deliver a final MP4.

- Skill: `haodao-culture/make-lyric-recap-video` (Agent Skill, multi-file: 20 files)
- Install (CLI): `npx skillmds@latest add haodao-culture/make-lyric-recap-video`
- Raw SKILL.md: https://api.skillmd.com/api/skills/haodao-culture/make-lyric-recap-video/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: haodao-culture (https://skillmd.com/u/haodao-culture)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/haodao-culture/make-lyric-recap-video

---


# 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-event` for one activity whose story is mainly a sequence of stages.
- Use `multi-day-course` for a course spanning multiple dates. Keep day order visible while preserving one overall emotional arc. Read [references/multi-day-course.md](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

1. Probe the exact audio duration with `ffprobe`.
2. Obtain or create SRT cues. Treat a lyric text file as content, not timing evidence.
3. Validate cue order, overlaps, and end time with `scripts/srt_tools.py validate`.
4. Render the transparent subtitle frames with `scripts/render_graphics.py subtitles`, using the Pillow Python reported by `scripts/find_pillow_python.zsh`.
5. Build a black-background review video with `scripts/render_subtitle_check.zsh`.
6. Review cue boundaries around phrase onsets and endings. Adjust the SRT, rerender, and repeat until the user approves it.
7. Preserve the approved SRT under a clearly versioned name. Never silently regenerate or retime it during Phase B.

Read [references/subtitle-sync.md](references/subtitle-sync.md) when creating or correcting timings.

## Phase B: select media and edit the recap

1. For a new project, run `scripts/prepare_media_incremental.mjs` with `--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 legacy `prepare_media.zsh` only for an existing project that already depends on its generated indexes.
2. Review `media_flow_mapping.tsv` and 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](references/media-flow-mapping.md).
3. Run `scripts/make_contact_sheets.zsh` to create review sheets labeled with display ID and filename. Inspect every sheet before authoring the timeline.
4. 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.
5. Create a TSV manifest using [references/timeline-manifest.md](references/timeline-manifest.md). Ensure display durations sum to the exact audio duration.
6. Render the title card with `scripts/render_graphics.py title`, using the Pillow Python reported by `scripts/find_pillow_python.zsh`. Use `--heading-size` or `--subtitle-size` when review feedback calls for different title prominence.
7. During revision, render with `scripts/render_montage_cached.mjs --mode draft`; use `--range START:END` or the optional manifest chapter column for local review. Reuse unchanged segment and chunk caches.
8. 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.
9. 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.
10. 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](references/editing-guidelines.md) before selecting shots or revising an existing cut.
Read [references/fast-iteration.md](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:

- `ffprobe` confirms 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 `fadeblack` at 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.

