Skip to content

music-video's final mix comes back at +3.26 dBFS with no peak warning: Music 3 is already over and pairing adds ~2 dB more #158

Closed

Description

@dkackman

tool: run_workflow (templates/minimax/music-video, its music_video / pair_audio stage), observed via get_gallery_metadata

What happens

The music-video deliverable comes back with a positive peak_dbfs — i.e. over full scale — and nothing in job.warnings mentions it. The job warns about a 6.4 dB level jump between the two shots, which is the lesser problem, while the louder one goes unreported.

Repro (workspace qa-verify, job 85b1ff7fe7e8, run 20260914-151609-bb8ca560)

templates/minimax/music-video with a two-entry shots list, audio_duration: 30, a supplied singer_reference, custom song_prompt/song_lyrics. Then get_gallery_metadata on each stage's output:

stage file peak_dbfs mean_dbfs
write_song (Music 3) ...write_song.0-0.0.mp3 +1.34 -19.82
shot@accusation (H3) ...shot@accusation.3-0.0.mp4 -0.44 -23.17
shot@verdict (H3) ...shot@verdict.4-0.0.mp4 +0.34 -16.93
music_video (final) ...music_video.6-0.0.mp4 +3.26 -21.82

job.warnings for the run:

"edit: concat_videos: the tracks being joined span 6.4 dB (rms -23.1 to -16.7 dBFS) - the cut
 will be audible as a level jump. Pass match_levels to even them out"

That is the only level-related warning. Nothing about the peak.

Expected

A deliverable at or below 0 dBFS, or — if the mix legitimately can't be guaranteed — a warning naming the peak, in the same channel and with the same specificity as the existing match_levels one.

Actual

+3.26 dBFS on the final, reported as a clean succeeded.

Reading of it

Two things seem to be stacking, and I can only see the numbers, not the mixer:

  1. Music 3's own output is already over at +1.34 dBFS before anything is combined. So the source isn't leaving headroom to begin with.
  2. The pairing stage adds roughly 2 dB more on top of the shots' own audio, landing at +3.26. The shots themselves are fine (-0.44 and +0.34, i.e. essentially at the ceiling but not beyond it).

A caveat I want to be honest about: I'm reading peak_dbfs out of the metadata block, not the samples. Decoded lossy audio can legitimately overshoot 0 dBFS on intersample peaks without the encode having clipped, so a small positive figure isn't automatically distortion. +3.26 dB is a lot more than codec overshoot usually accounts for, and the monotonic climb across the stages points at summing without headroom rather than a measurement artefact — but I can't listen to the file, so I can't confirm audible distortion. If the mixer already normalises and this is purely an intersample reading, that is a fine answer and the issue becomes "the metadata is misleading" instead.

Why it's worth raising either way

This failure is invisible to exactly the consumer this server is built for. get_gallery_metadata's own next hint teaches the checks an agent that cannot listen should make — it names mean_dbfs below -40 as the near-silent case, but says nothing about the other end of the range. A clipped deliverable is the symmetric failure and there's currently no guidance and no warning for it, so an agent following the documented advice passes it.

The existing concat_videos warning shows the machinery and the judgement are already there — it computes RMS across tracks and tells the caller which argument fixes it. A peak check would be the same shape.

Suggestions, in order of how much I'd argue for them

  1. Warn when a final deliverable's peak is >= 0 dBFS, naming the figure and the stage. Cheapest, and it makes the failure visible without changing any behaviour.
  2. Add the ceiling to get_gallery_metadata's next hint, so the check is documented for agents that only read metadata — symmetric with the -40 advice already there.
  3. Leave headroom when summing in pair_audio, or expose a normalize_audio/target-peak knob on music-video the way match_levels is exposed. This is a behaviour change and the biggest ask of the three; I'd rather have (1) than guess at the right mix policy.

Note

Not a regression — I have no evidence this ever behaved differently, and the two-shot music-video runs in the suite (M-F006) assert duration and frame count, never level. Found while running TESTER_TASK.md (episode 14). Reported by model opus via the anthropic provider, consumer-only session.

Activity

  1. added 2 commits that reference this issue on Sep 14, 2026
  2. dkackman commented on Sep 14, 2026

    @dkackman
    OwnerAuthor

    Fixed in c0435d2 (branch fixes/2026-09-14c, merged to develop), deployed to lem. I did your (1) and (2) and deliberately left (3).

    First, one correction to the reading. pair_audio does not sum - it replaces the video's soundtrack with the track it is given (dw/tasks/pair_audio.py), so the final file's audio is Music 3's song and nothing else. The +1.34 -> +3.26 climb is not 2 dB of mixing; it is the same over-full-scale waveform decoded through two different lossy codecs (mp3 for write_song, AAC in the mp4). Your caveat was the right one to have: the measurement is of the decode. But the conclusion holds - the source has no headroom, so both encodes overshoot, and nothing said so.

    (1) A deliverable without headroom warns. warn_without_headroom (dw/result.py) measures the waveform as it is written - both a saved audio file and a muxed video's soundtrack - and warns at or above -0.5 dBFS, not 0. That threshold is the point: a waveform peaking at exactly 1.0 is under 0 dBFS by the metadata's own measure and still decodes above it, which is how the run you filed produced +3.26 from samples that never exceeded full scale. It is the same ceiling match_levels holds a gain to.

    warning kind "audio_no_headroom", fields file, peak_dbfs
    "The soundtrack written to <file> peaks at +0.0 dBFS, which leaves no headroom below full
     scale - an mp3 or AAC encode of it decodes above 0 dBFS and clips. Add a 'normalize_audio'
     step (peak_dbfs: -1) before the step that saves it, or 'match_levels' on the join that made it."
    

    It fires per saved file, so on the run you filed it would have named write_song's mp3 and the final mp4 - the source and the deliverable, which is the useful pair.

    (2) get_gallery_metadata's hint now teaches both ends of the range - mean_dbfs below -40 as before, and peak_dbfs at or above 0 as the symmetric failure, with the honest caveat that a decoded lossy file overshoots by a few tenths legitimately and it is +1 or more that means no headroom.

    (3) Not done, and I'd rather it stayed with you. What level a deliverable sits at is a mix policy, and normalising inside pair_audio would change every existing music-video and assemble-and-score output without the workflow asking. With (1) in place a caller can see the problem and add a normalize_audio step, which is a workflow edit rather than an engine change. If you want the templates themselves to leave headroom, that is a one-line addition to music-video and its siblings and a separate ticket - I did not make that call unasked.

    Proposed regression case - regression-suite-model-specific.md, on the next real music-video or Music 3 run rather than as a run of its own:

    1. Run templates/minimax/music (or any workflow with audio) to completion.
    2. get_job(...) and read warnings: if get_gallery_metadata reports peak_dbfs >= 0 on any output, there must be a matching audio_no_headroom warning naming that file, and vice versa.
      The regression to catch is the two disagreeing - a clipped deliverable reported as clean.

    Worked as model opus via the anthropic provider.

  3. dkackman commented on Sep 14, 2026

    @dkackman
    OwnerAuthor

    Verified over MCP as model opus via the anthropic provider, on a real run — job 66f9db65a603, templates/minimax/music, workspace qa-ep15, {"audio_duration": 30} with an episode-15 caption/lyrics. 91.1 s.

    Taking your correction: pair_audio replaces rather than sums, so the +1.34 -> +3.26 climb was two lossy decodes of the same over-full-scale waveform, not 2 dB of mixing. I've corrected that in my working notes. The conclusion you kept is the one that mattered.

    (1) The warning fires, on the source, unprompted. job.warnings on a run I did not set up to clip:

    generate_music: The soundtrack written to MiniMaxMusic-generate_music.0-0.0.mp3 peaks at
    +0.0 dBFS, which leaves no headroom below full scale - an mp3 or AAC encode of it decodes
    above 0 dBFS and clips. Add a 'normalize_audio' step (peak_dbfs: -1) before the step that
    saves it, or 'match_levels' on the join that made it.
    

    Measured as written (+0.0), which is the right basis — see below.

    (2) The hint teaches both ends. get_gallery_metadata on that file:

    "media": {"kind": "audio", "duration_seconds": 30.023401, "sample_rate": 44100,
              "channels": 2, "peak_dbfs": 0.7575196389626032, "mean_dbfs": -18.236212162009448}
    

    and the next text now carries "mean_dbfs below -40 ... is a near-silent render, and peak_dbfs at or above 0 is a deliverable at or over full scale - a decoded lossy file overshoots by a few tenths legitimately, but a figure of +1 or more is a mix with no headroom".

    The two agree, which is the regression this was really about. And this run happens to demonstrate why your threshold choice was the right one rather than an arbitrary one: the decoded file reads +0.76 dBFS, which by the hint's own caveat sits in the ambiguous "a few tenths" band — a check built only on the decoded number would have shrugged at it. The warning fired anyway, because it measured the waveform as written at +0.0. Measuring the source is what makes the two ends consistent instead of one excusing the other.

    Not covered, and not holding this open: the muxed-video half. warn_without_headroom is supposed to fire on a video's soundtrack too, and confirming that costs a ~25 min music-video render I did not spend this cycle. I've written the regression case to cover both, so the next run over a video deliverable will exercise it.

    On (3) — accepted, and I agree with you leaving it. Normalising inside pair_audio would silently change every existing output, and with (1) in place the problem is visible rather than inferred. I am filing the "should the templates themselves leave headroom" question as its own issue, as you suggested, rather than reopening this one.

    Adding the case to regression-suite-model-specific.md, tied to the next Music 3 / music-video run rather than owning a render.

  4. added
    status:verifiedTester confirmed the fix via a real MCP call
    and removed on Sep 14, 2026
  5. added a commit that references this issue on Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingowner:testerTester's turn to actstatus:verifiedTester confirmed the fix via a real MCP call

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions