Storyboard AV Mix
Take a work directory with per-shot video and bilingual VO. For each shot, retime the video to the full VO duration (audio master), drop original video audio, mux, and write language-specific folders.
| Input |
Path |
| Shot video |
<root>/Video/<shot-id>.* |
| Chinese VO |
<root>/Chinese/<shot-id>.* |
| English VO |
<root>/English/<shot-id>.* |
| Output |
Path |
| Chinese mux |
<root>/Video-Chinese/<shot-id>.<video-ext> |
| English mux |
<root>/Video-English/<shot-id>.<video-ext> |
Rules
When this skill applies, read and follow skill-dependency-manager — run scripts as documented, install missing tools into .dependency/.
- VO timing is immutable. Never stretch, shrink, pad, trim, or
atempo the voice-over. Duration of the VO file is the master clock.
- Video serves audio. Only change video duration (FFmpeg
setpts) so it equals that shot’s VO length, then mux.
- Drop all audio from the source video; replace with the VO track. Prefer
-c:a copy; if the container cannot hold the VO codec (e.g. WAV→MP4), encode AAC without changing length.
- Do not downgrade video.
setpts requires a re-encode, but match the source: codec family (H.265 Main10 when source is 10-bit HEVC), pix_fmt, bitrate, color tags, and HDR side data (mastering display / MaxCLL). Copy container + video-stream metadata from the source clip.
- Match shots by filename stem (
01.mp4 ↔ 01.wav).
- Batch only via
.ai/storyboard-av-mix/mix.py — do not hand-write FFmpeg mux/retime commands.
- Never overwrite inputs under
Video/, Chinese/, or English/.
Quick Start
From project root:
.dependency/python/python .ai/storyboard-av-mix/mix.py path/to/<root>
Single language:
.dependency/python/python .ai/storyboard-av-mix/mix.py path/to/<root> --lang chinese
Per shot / language the script:
- Probes VO duration (source of truth) and video duration
- Applies
setpts=PTS*(vo_dur/video_dur) — stretch or compress video only (plus short freeze-tail so video ≥ VO)
- Muxes with
-shortest so container duration == VO duration
- Writes
<root>/Video-Chinese| or Video-English/ / <shot-id>.<same-ext>
Layout
<root>/
Video/
01.mp4
02.mp4
Chinese/
01.wav
02.wav
English/
01.wav
02.wav
Video-Chinese/ # written by this skill
01.mp4
02.mp4
Video-English/
01.mp4
02.mp4
Typical <root> is a storyboard-tts audio dir that also has a sibling or nested Video/ of cut clips — confirm the folder that contains Video/, Chinese/, and English/.
Common Flags
| Flag |
Notes |
root |
Work dir with Video/, Chinese/, English/ |
--lang |
both (default), chinese, english |
Existing outputs are overwritten. Missing VO for a language → skip that job with a warning. Missing video → skip shot.
Agent Notes
- Audio first: if durations disagree, change video, never VO.
- Prefer one
mix.py run for the whole board.
- Re-encode must preserve source quality tags (Main10 / HDR / bitrate) — never force 8-bit H.264.
- Chat summary:
<root>, jobs done / skipped, paths to Video-Chinese/ and Video-English/.
- Upstream VO usually from storyboard-tts; this skill does not synthesize speech.
- Missing Python/FFmpeg → populate
.dependency/ per skill-dependency-manager, retry same command.
Tests
From repo root:
.dependency/python/python .ai/storyboard-av-mix/test_mix.py
Related
Manual CLI examples: cli/storyboard-av-mix.md
1---2name: storyboard-av-mix3description: Muxes per-shot storyboard video with Chinese and English voice-over by retiming video to match VO duration (setpts), writing Video-Chinese/ and Video-English/ (matched by shot id 01, 02, …). Use when the user wants storyboard A/V mix, storyboard A/V mix, VO dubbing mix, video retime to audio, Video-Chinese, Video-English, bilingual VO on cut video, or batch mux Video/ + Chinese/ + English/.4---56# Storyboard AV Mix78Take a work directory with **per-shot** video and bilingual VO. For each shot, **retime the video to the full VO duration** (audio master), drop original video audio, mux, and write language-specific folders.910| Input | Path |11|-------|------|12| Shot video | `<root>/Video/<shot-id>.*` |13| Chinese VO | `<root>/Chinese/<shot-id>.*` |14| English VO | `<root>/English/<shot-id>.*` |1516| Output | Path |17|--------|------|18| Chinese mux | `<root>/Video-Chinese/<shot-id>.<video-ext>` |19| English mux | `<root>/Video-English/<shot-id>.<video-ext>` |2021## Rules2223When this skill applies, read and follow [skill-dependency-manager](../skill-dependency-manager.md) — run scripts as documented, install missing tools into `.dependency/`.24251. **VO timing is immutable.** Never stretch, shrink, pad, trim, or `atempo` the voice-over. Duration of the VO file is the master clock.262. **Video serves audio.** Only change video duration (FFmpeg `setpts`) so it equals that shot’s VO length, then mux.273. Drop all audio from the source video; replace with the VO track. Prefer `-c:a copy`; if the container cannot hold the VO codec (e.g. WAV→MP4), encode AAC **without** changing length.284. **Do not downgrade video.** `setpts` requires a re-encode, but match the source: codec family (H.265 Main10 when source is 10-bit HEVC), `pix_fmt`, bitrate, color tags, and HDR side data (mastering display / MaxCLL). Copy container + video-stream metadata from the source clip.295. Match shots by **filename stem** (`01.mp4` ↔ `01.wav`).306. Batch only via `.ai/storyboard-av-mix/mix.py` — do not hand-write FFmpeg mux/retime commands.317. Never overwrite inputs under `Video/`, `Chinese/`, or `English/`.3233## Quick Start3435From project root:3637```bash38.dependency/python/python .ai/storyboard-av-mix/mix.py path/to/<root>39```4041Single language:4243```bash44.dependency/python/python .ai/storyboard-av-mix/mix.py path/to/<root> --lang chinese45```4647Per shot / language the script:48491. Probes VO duration (source of truth) and video duration502. Applies `setpts=PTS*(vo_dur/video_dur)` — stretch or compress **video only** (plus short freeze-tail so video ≥ VO)513. Muxes with `-shortest` so **container duration == VO duration**524. Writes `<root>/Video-Chinese|` or `Video-English/` / `<shot-id>.<same-ext>`5354## Layout5556```57<root>/58 Video/59 01.mp460 02.mp461 Chinese/62 01.wav63 02.wav64 English/65 01.wav66 02.wav67 Video-Chinese/ # written by this skill68 01.mp469 02.mp470 Video-English/71 01.mp472 02.mp473```7475Typical `<root>` is a [storyboard-tts](../storyboard-tts/SKILL.md) audio dir that also has a sibling or nested `Video/` of cut clips — confirm the folder that contains `Video/`, `Chinese/`, and `English/`.7677## Common Flags7879| Flag | Notes |80|------|--------|81| `root` | Work dir with `Video/`, `Chinese/`, `English/` |82| `--lang` | `both` (default), `chinese`, `english` |8384Existing outputs are overwritten. Missing VO for a language → skip that job with a warning. Missing video → skip shot.8586## Agent Notes87881. Audio first: if durations disagree, change **video**, never VO.892. Prefer one `mix.py` run for the whole board.903. Re-encode must preserve source quality tags (Main10 / HDR / bitrate) — never force 8-bit H.264.914. Chat summary: `<root>`, jobs done / skipped, paths to `Video-Chinese/` and `Video-English/`.925. Upstream VO usually from [storyboard-tts](../storyboard-tts/SKILL.md); this skill does not synthesize speech.936. Missing Python/FFmpeg → populate `.dependency/` per skill-dependency-manager, retry same command.9495## Tests9697From repo root:9899```bash100.dependency/python/python .ai/storyboard-av-mix/test_mix.py101```102103## Related104105- [storyboard-tts](../storyboard-tts/SKILL.md) — bilingual VO under `Chinese/` / `English/`106- [storyboard](../storyboard/SKILL.md) — source markdown107108Manual CLI examples: [cli/storyboard-av-mix.md](../../../cli/storyboard-av-mix.md)