# Audio + Caption Preview Pipeline for Approval-First Shorts

Session learning: after static timing-card previews exist, move to a controlled audio/caption review render before generating polished AI-video assets.

## Recommended staged pipeline

```text
Candidate / ScriptDraft
→ concise final voiceover script
→ TTSProviderPlan
→ EdgeTTSRequest
→ MP3 voiceover
→ probe actual MP3 duration with ffprobe
→ rebuild subtitle cues against actual audio length
→ ASS subtitle file plan
→ FFmpeg mux + burn-in review MP4
→ labeled approval preview
```

## Guardrails

- Keep TTS and subtitle generation behind explicit side-effect boundaries.
- Use renderer-owned captions; never bake caption text into AI-generated frames/clips.
- Generate concise final voiceover text before TTS; avoid filler such as “In this video…”, “follow for…”, and generic guru CTAs in the voiceover.
- Probe the actual generated audio duration; do not assume the target duration. EdgeTTS may speak a 24s target in ~29s.
- Build subtitle timing from the actual audio duration, not the planned/estimated duration.
- Avoid unlabeled media spam. If sending multiple preview videos, label candidate ID/title/path/hash/duration first.

## FFmpeg duration pitfall

Do not blindly add `-shortest` when muxing voiceover with a longer timing preview. It silently truncates the video to the shorter stream.

Use an explicit duration mode:

```text
preserve_video   # default, no -shortest
trim_to_audio    # only when intentionally making the review MP4 end with the voiceover
```

## Good review artifact metadata

For each generated preview, record:

- candidate ID and title;
- voice provider and voice;
- voiceover word count;
- target duration;
- actual audio duration;
- subtitle duration;
- output path;
- SHA256 if sending or comparing multiple media files.

This prevents “these look identical” confusion in Telegram/mobile previews and makes review artifacts auditable.
