You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Skills: document per-shot score ducking under voice-over (gain_audio regions) for H3 scored pieces #340
repro: A scored cuts piece whose H3 shots mix narration with action sound. Assemble with templates/assemble-and-score. Try world_gain 1.8 (default), 4.5 and 7.2.
expected: Some way to put dialogue on top of the score while leaving the action or melee sound where it was.
actual:
H3 renders narration ~24 dB above its own ambience, stable across one batch: shots with no voice-over were -54.46/-48.90/-46.15 dBFS mean, the two voice-over shots -33.83/-33.13.
Music3's score lands 6-15 dB above the narration.
The world arrives as one stream, so raising it lifts both:
No duck/sidechain task exists (grep "sidechain" in dw/tasks: nothing).
proposed fix (design options, needs a decision):
(1) A duck_audio task, or a sidechain argument on mix_audio. It takes a key track (the world, which contains the speech) plus threshold, depth_db, attack_ms and release_ms, and pulls the target (score) down while the key's short-window envelope is above threshold.
(2) A cheaper variant: a task that emits gain_audio regions from a key track's envelope.
(3) Model-side: an H3 option to return dialogue as its own stem. Probably not available.
Wire (1) into assemble-and-score as an optional duck_score_db (default 0 = off).
Filed from Don's dw findings ledger (dw-findings-ledger.html, DW-03). First-pass triage for applicability and value against open/closed issues and develop @ f11ac2a by claude-opus-5-5 via anthropic (interactive session with Don; code-checking subagents inherited that model).
changed the title [-]Proposal: voice-driven ducking (sidechain) for mix_audio, since H3's single world track can't lift dialogue without lifting action sound[/-][+]Skills: document per-shot score ducking under voice-over (gain_audio regions) for H3 scored pieces[/+]on Sep 22, 2026
Disposition (Don, 2026-09-22): narrowed to a skill/doc change. Do not build the engine proposal above.
Why the proposal as written is rejected: a sidechain keyed on the world track can't separate dialogue from action, because the world track carries both. It would duck the score under the melee too, which is exactly where the score peaks. Speech-keyed ducking would need new speech-detection surface (transcribe_audio returns text only, no timestamps). That can come back as its own proposal if manual ducking proves painful.
Scope for this issue:
In the dw plugin skills that cover scored H3 pieces (dw:minimax-h3, dw:series-episodes, and wherever templates/assemble-and-score / dissolve-between-shots are taught), add a short recipe. When some shots carry voice-over and the score buries them, duck the score under just those shots with gain_audio (No per-region gain task; ducking requires a five-step slice/gain/rejoin chain #187): one region per voice-over shot, with start_frame = the running sum of the preceding shots' num_frames, num_frames = that shot's length, and fps the cut's rate. Apply it to the score before the mix step. That means a local variant of the template, or a pre-processed score passed as score.
Name the measured symptom so agents recognise it: narration ~24 dB over its own ambience, with a Music 3 score 6–15 dB over the narration. Raising world_gain lifts the action sound with the voice (4.5 → voice +5 dB, melee −0.5 dB; 7.2 → voice +5…+8 dB, and the score's peaks drop after normalize).
Say what not to do: don't reach for world_gain to fix intelligibility.
Plugin change only: merge to develop, no server restart. (Recorded by claude-opus-5-5 via anthropic in the triage session with Don.)
triage: batch with #354 — both are Don-narrowed doc-only changes to plugins/dw/skills (H3/speech skills) and tool docstrings; one session, one deploy. Work per Don's disposition comment, not the original engine proposal. (claude-opus-5-5 via anthropic, triage session)
Fixed and deployed. Worked as claude-sonnet-5 (Anthropic).
Added a ducking recipe to the three skills that teach a scored H3 piece:
plugins/dw/skills/minimax-h3/SKILL.md - the primary recipe, under the "A piece with cuts" bullet: a score burying voice-over is not a world_gain fix (the world track carries narration and action together - narration ~24 dB over its own ambience, score 6-15 dB over that - so raising it lifts both). Duck the score instead, before passing it as score: one gain_audio (No per-region gain task; ducking requires a five-step slice/gain/rejoin chain #187) step per voice-over shot, chained, start_frame = running sum of preceding shots' num_frames, num_frames that shot's length, fps the cut's rate, negative gain_db (-6 to -10). Notes dissolve-between-shots eats a dissolve_frames per seam, so its sum isn't plain addition.
plugins/dw/skills/series-episodes/SKILL.md - same recipe referenced from the match_levels step of the five-beat procedure, since that's the other place assemble-and-score's mixing is taught.
plugins/dw/skills/minimax-music3/SKILL.md - pointer added to the "A score under a film or a cuts piece" bullet, pointing back at minimax-h3's recipe.
minimax-h3/SKILL.md was trimmed elsewhere (wording only, no content dropped) to stay under the 12KB skill size cap after the addition - final size 12278 bytes.
Shipped: commit 96e2ea2 on develop (merged from fix/340-354-score-ducking-and-transcription-route), plugin-only change - no server restart required for this part, but the same commit also carries #354's fix, which does need one; both are now live on lem (deployed at 2026-09-23 12:34 UTC, healthy at 96e2ea2).
tests/test_plugin_skills.py (52 tests, all pinned substrings/size caps) passes.
Batched with #354 per the triage comment on #340 - see that issue for its own summary.
start_frame = running sum of the preceding shots' num_frames, num_frames = that shot's length, fps = the cut's rate, negative gain_db
the dissolve-between-shots caveat
dw:series-episodes: the match_levels beat says voice-over burial isn't fixed by match_levels or world_gain, and points to the minimax-h3 recipe.
dw:minimax-music3: the "A score under a film or a cuts piece" bullet points to the same recipe.
Adjacent checks (does the recipe work as written?):
get_task("gain_audio"): the task takes gain_db, start_frame, num_frames and fps. These are the parameter names the recipe uses.
validate_workflow on an inline two-step chain following the recipe: gain_audio on asset:qa-cast/ep20-score.wav (start_frame 124, num_frames 141, fps 24, gain_db -8), then gain_audio on previous_result:duck1 (start_frame 265, num_frames 124). Result: valid: true, no warnings.
Not covered: Don's scope asked for "don't reach for world_gain" and the measured-symptom wording. Both are present. Whether a -6 to -10 dB duck is enough in practice is a listening judgement. Nothing was generated this session, so I didn't test it.
No regression case added: this is a doc-only change, and a skill-text pin belongs in tests/test_plugin_skills.py, not in an MCP suite.
Activity
[-]Proposal: voice-driven ducking (sidechain) for mix_audio, since H3's single world track can't lift dialogue without lifting action sound[/-][+]Skills: document per-shot score ducking under voice-over (gain_audio regions) for H3 scored pieces[/+]dkackman commentedon Sep 22, 2026
Disposition (Don, 2026-09-22): narrowed to a skill/doc change. Do not build the engine proposal above.
Why the proposal as written is rejected: a sidechain keyed on the world track can't separate dialogue from action, because the world track carries both. It would duck the score under the melee too, which is exactly where the score peaks. Speech-keyed ducking would need new speech-detection surface (
transcribe_audioreturns text only, no timestamps). That can come back as its own proposal if manual ducking proves painful.Scope for this issue:
dw:minimax-h3,dw:series-episodes, and wherevertemplates/assemble-and-score/dissolve-between-shotsare taught), add a short recipe. When some shots carry voice-over and the score buries them, duck the score under just those shots withgain_audio(No per-region gain task; ducking requires a five-step slice/gain/rejoin chain #187): one region per voice-over shot, withstart_frame= the running sum of the preceding shots'num_frames,num_frames= that shot's length, andfpsthe cut's rate. Apply it to the score before the mix step. That means a local variant of the template, or a pre-processed score passed asscore.world_gainlifts the action sound with the voice (4.5 → voice +5 dB, melee −0.5 dB; 7.2 → voice +5…+8 dB, and the score's peaks drop after normalize).world_gainto fix intelligibility.Plugin change only: merge to
develop, no server restart. (Recorded by claude-opus-5-5 via anthropic in the triage session with Don.)dkackman commentedon Sep 23, 2026
triage: batch with #354 — both are Don-narrowed doc-only changes to plugins/dw/skills (H3/speech skills) and tool docstrings; one session, one deploy. Work per Don's disposition comment, not the original engine proposal. (claude-opus-5-5 via anthropic, triage session)
fix(plugin): #340, #354 - score ducking recipe + transcription route …
dkackman commentedon Sep 23, 2026
Fixed and deployed. Worked as claude-sonnet-5 (Anthropic).
Added a ducking recipe to the three skills that teach a scored H3 piece:
plugins/dw/skills/minimax-h3/SKILL.md- the primary recipe, under the "A piece with cuts" bullet: a score burying voice-over is not aworld_gainfix (the world track carries narration and action together - narration ~24 dB over its own ambience, score 6-15 dB over that - so raising it lifts both). Duck the score instead, before passing it asscore: onegain_audio(No per-region gain task; ducking requires a five-step slice/gain/rejoin chain #187) step per voice-over shot, chained,start_frame= running sum of preceding shots'num_frames,num_framesthat shot's length,fpsthe cut's rate, negativegain_db(-6 to -10). Notesdissolve-between-shotseats adissolve_framesper seam, so its sum isn't plain addition.plugins/dw/skills/series-episodes/SKILL.md- same recipe referenced from thematch_levelsstep of the five-beat procedure, since that's the other placeassemble-and-score's mixing is taught.plugins/dw/skills/minimax-music3/SKILL.md- pointer added to the "A score under a film or a cuts piece" bullet, pointing back at minimax-h3's recipe.minimax-h3/SKILL.mdwas trimmed elsewhere (wording only, no content dropped) to stay under the 12KB skill size cap after the addition - final size 12278 bytes.Shipped: commit
96e2ea2ondevelop(merged fromfix/340-354-score-ducking-and-transcription-route), plugin-only change - no server restart required for this part, but the same commit also carries #354's fix, which does need one; both are now live onlem(deployed at 2026-09-23 12:34 UTC, healthy at96e2ea2).tests/test_plugin_skills.py(52 tests, all pinned substrings/size caps) passes.Batched with #354 per the triage comment on #340 - see that issue for its own summary.
dkackman commentedon Sep 23, 2026
Verified by claude-opus-5-5 via anthropic (tester, verify session), against lem develop @ 4aaeef7 and plugin tree at origin/develop.
What I ran:
dw:minimax-h3through the Skill tool. The ducking recipe sits under "A piece with cuts" and covers every point in Don's scope:world_gainfix"world_gainlifts both)scoregain_audio(No per-region gain task; ducking requires a five-step slice/gain/rejoin chain #187) step per voice-over shot, chainedstart_frame= running sum of the preceding shots'num_frames,num_frames= that shot's length,fps= the cut's rate, negativegain_dbdissolve-between-shotscaveatdw:series-episodes: thematch_levelsbeat says voice-over burial isn't fixed bymatch_levelsorworld_gain, and points to the minimax-h3 recipe.dw:minimax-music3: the "A score under a film or a cuts piece" bullet points to the same recipe.Adjacent checks (does the recipe work as written?):
get_task("gain_audio"): the task takesgain_db,start_frame,num_framesandfps. These are the parameter names the recipe uses.validate_workflowon an inline two-step chain following the recipe:gain_audioonasset:qa-cast/ep20-score.wav(start_frame 124, num_frames 141, fps 24, gain_db -8), thengain_audioonprevious_result:duck1(start_frame 265, num_frames 124). Result:valid: true, no warnings.Not covered: Don's scope asked for "don't reach for
world_gain" and the measured-symptom wording. Both are present. Whether a -6 to -10 dB duck is enough in practice is a listening judgement. Nothing was generated this session, so I didn't test it.No regression case added: this is a doc-only change, and a skill-text pin belongs in
tests/test_plugin_skills.py, not in an MCP suite.