Mix master
Skill gooseworks-ai/goose-skills/skills/ads/packs/video-ad-formats/mix-master
Canonical short-form-ad audio mix in one FFmpeg pass. VO loudnorm + 3.0× per-clip + 2.0× mix, music 0.13 base + apad+afade, sidechain compress 20:1 @ 0.01, climax line +20%, optional video-to-music duration sync. Replaces the reactive multi-round tuning that cost v03 6+ passes.From its SKILL.md
npx -y skills add gooseworks-ai/goose-skills --skill mix-masterAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
5.4 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
mix-master
Purpose
The v03 Ironman LEARNINGS describe 6+ tuning rounds because no default mix protocol existed: round 1 music too loud, round 2 VO too quiet, round 3 Whisper mis-transcribed, round 4 sidechain ratio finally right, round 5 music ended too early, round 6 climax sat at the same loudness as the rest.
This atom encodes the protocol that landed and ships it as the default. Operators tune by flag; they don't redesign the chain.
Inputs
--video <path>— video file with no audio (or whose audio gets dropped) (required)--vo <path,path,...>— comma-separated list of per-scene VO mp3s in scene order (required)--vo-starts <ms,ms,...>— start time in milliseconds for each VO clip on the timeline (required, same length as--vo)--music <path>— music bed file (required)--sfx <path,path,...>— optional comma-separated SFX list--sfx-starts <ms,ms,...>— optional SFX start times--output <path>— output mp4 (required)--total-duration <s>— target total duration in seconds (required — video AND music are sync-fit to this)--vo-boost-line <N>— 1-indexed VO clip that is the climax; gets +20% additional volume (default unset)--vo-volume <float>— per-clip VO volume multiplier (default3.0)--vo-mix-volume <float>— extra mix-bus volume on VO (default2.0)--music-volume <float>— base music volume (default0.13)--music-swell-volume <float>— peak music volume during apad/swell (default0.21)--sidechain-ratio <float>— sidechain ratio, capped at 20 by FFmpeg (default20)--sidechain-threshold <float>— sidechain threshold (default0.01)--target-i <lufs>— VO loudnorm integrated target (default-16)--target-tp <dbtp>— VO loudnorm true-peak (default-1.5)--target-lra <lu>— VO loudnorm LRA (default11)
Workflow
- Validate inputs —
--voand--vo-startsmust be same length;--sfxand--sfx-startsmust be same length; ffmpeg + ffprobe must be on PATH. - Probe music duration (
ffprobe). If music shorter than--total-duration, appendapad=pad_dur=2.0then trim back to target. If music longer, trim withafade=outover last 1.5s. - Build a
filter_complex_scriptfile (long chains exceed shell arg limits):- Per-VO:
[N:a]loudnorm=I=...:TP=...:LRA=...,adelay=<start>|<start>,volume=<vo_volume>[voN]; - Climax VO (if
--vo-boost-line N): volume becomesvo_volume * 1.2. - Mix all VO:
amix=inputs=K:duration=longest,volume=<vo_mix_volume>[vo_pre]; - Split VO for sidechain key:
[vo_pre]asplit=2[vo_final][vo_sc]; - Music base:
apad=pad_dur=2.0,atrim=0:<TOTAL>,afade=t=out:st=<TOTAL-1.5>:d=1.5,volume=<music_volume>[music_base]; - Sidechain:
[music_base][vo_sc]sidechaincompress=threshold=<thresh>:ratio=<ratio>:attack=20:release=600[music_ducked]; - SFX (optional): per-SFX
adelay+volumethen mix into[sfx_bus]. - Final:
amix=inputs=<2 or 3>:duration=longest[a_out].
- Per-VO:
- Run a single ffmpeg invocation that consumes video, all VO, music, all SFX, applies the filter chain, and outputs the mixed mp4 (video re-encoded only if duration trim needed; otherwise
-c:v copy). - Run a verification probe: ffprobe loudness summary on
[a_out], writemanifest.jsonandverification.md.
Output
<output>— mixed mp4 with VO + music + SFX.manifest.json— chain parameters, vo timing, climax line, integrated LUFS after.verification.md— pass/fail report (integrated LUFS within ±0.5 of expected target, no clipping).
Quality Checks
- Output integrated LUFS within ±0.5 of
<target-i>(post-protocol; should be approximately -14 social-ready after the boosts). - True-peak strictly below
<target-tp>(no clipping). - Output duration equals
<total-duration>± 100ms. - Music tail has
afade=out— last 100ms RMS < -30 dB. - If
--vo-boost-linewas set, the corresponding clip'svolume=value isvo_volume * 1.2.
Failure Modes
- Sidechain ratio > 20 — FFmpeg errors "Result too large." Cap at 20 (the protocol default).
- VO and starts arrays mismatched — fail fast at validation.
- Music too short and
apadinsufficient — emit a warning; video may end before music. Operator should re-source music or shorten--total-duration. - VO clip > 5KB but actually error JSON — out of scope here;
create-clipsPhase 4 catches it. - Re-encoding video unnecessarily — if total duration matches input video duration, use
-c:v copyto preserve quality.
Example
scripts/mix.sh \
--video peloton/ads/video-04-new-job/edits/master-no-audio.mp4 \
--vo "peloton/ads/video-04-new-job/audio/vo-scene-01.mp3,...,peloton/ads/video-04-new-job/audio/vo-scene-14.mp3" \
--vo-starts "0,2000,3500,...,28000" \
--music peloton/ads/video-04-new-job/audio/music-cue-01.wav \
--output peloton/ads/video-04-new-job/edits/master-final.mp4 \
--total-duration 30.0 \
--vo-boost-line 14
Consumed by: video-orchestrator/edit-video Phase 3–5, auto-fix-from-review-notes dispatcher (when vo-intelligibility or music-vo-balance polish-notes items reference mix-master).
What ships with it: 2 files
8.3 KB alongside SKILL.md, 1 of them executable
scripts/
- mix.shruns8.1 KB
- skill.meta.json252 B