Skip to content

fix(cli): normalize-audio never cuts a clip that is quieter than the target - #6767

Merged
miguel-heygen merged 4 commits into
mainfrom
fix/normalize-audio-peak-cap
Oct 30, 2026
Merged

miguel-heygen merged 4 commits into
mainfrom
fix/normalize-audio-peak-cap

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

What

normalize-audio --lufs no longer cuts a clip that is quieter than the target. When the true-peak ceiling stops a boost, the clip keeps its current gain and limitedBy says why.

Why

A clip measuring -17.1 LUFS with a peak past the -1.5 dBTP ceiling, asked for -17, was written with data-volume 0.81. That projects to -18.9 LUFS: further from the target than before, reported as ok: true. The limit math took the lowest of the wanted gain and the ceilings, and the peak room is negative for such a clip, so a boost request became a cut.

Related work

Trim windows are measured correctly on main (-ss/-t as input options); this is not a window bug. Earlier work: the playback-start fix and the in-scene targeting fix, both merged.

How

absoluteLoudnessPlan clamps the limited gain so that a request to go up never lands below the clip's current gain. Cuts are unchanged. A held clip has changeDb 0 and is not reported as matched: absoluteOutcome says matched, held or change, the command prints that it cannot get closer, and nothing is written. This also explains a clip reported withinTolerance: true while far from the target.

Test plan

  • Unit tests added/updated
  • Manual testing performed
  • Documentation updated (if applicable)
  • Comments follow CONTRIBUTING.md "Comments"

fails without the fix: with the clamp removed, never cuts a clip that is below the target because its peak is already past the ceiling fails with expected -1 to be close to +0.

What I measured

loudness.test.ts: 47 passed on three runs on the devbox; the cli normalize tests pass (33). Without the fix, 1 failed; with absoluteOutcome forced to matched, calls a clip a limit cannot move held, not matched fails with expected 'matched' to be 'held'. Real ffmpeg on a built CLI: a pulsed tone at -17.1 LUFS with a near full-scale peak, --lufs=-17 --write --json, wrote 0.81 and projected -18.9 LUFS before the fix. A trimmed clip with the same tone measures its played window correctly (-21.9 LUFS).

What I did NOT execute

The fixed CLI on the pulsed fixture after the change, and the reported "-19.7 LUFS, within tolerance, wrote nothing" case, which I could not tie to a cause (an earlier gain already on the clip would produce it).

Size

Under 100 lines on purpose: normalize-audio cuts clips it should boost today, and no open change touches it to carry this.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES · 1 blocker · 1 important · 0 nits · head 431a9e9c

The fix itself is right. The fails without the fix: line holds: with the clamp removed, the new test fails (expected -1 to be close to +0), and 44/44 pass at the head. cli normalize-audio tests pass 33/33.

  • blocker: Comments is red. The run reports RAISED comment share: packages/studio-server/src/helpers/loudness.ts is 5.0% (28/563), at the base 4.8% (27/560). That comes from the one new comment at line 547. Cut it, or move the explanation into a name (for example const boostOnlyGainDb = …). ↓ inline
  • important ↓ inline: a held clip reports withinTolerance: true and prints "Already matched" however far it is from the target.
Scope

Read all of absoluteLoudnessPlan and both callers (CLI normalize-audio.ts and the Studio /loudness/normalize route). CI and Windows were still running when this was posted.

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 141 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (3)

  • seqplainkeys-none-center-r0-nested-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true
  • seqresize-none-px-r0-nested-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true
  • seqplainkeys-none-pct-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES — 1 resolved, 1 open, 2 new · 431a9e9 → e3b0605

New blockers, both from CI on this head: Comments is red again (loudness.ts 28/572, base 27/560), and oxfmt --check fails on normalize-audio.ts, which turns the required Format and Windows preflight checks red. Running oxfmt on that file fixes the second. Locally: loudness 47/47, cli normalize-audio 33/33.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE — 4 resolved, 0 open, 0 new · e3b0605 → fbea11d. Loudness tests pass 47/47 and cli normalize-audio 33/33 locally; oxfmt is clean; CI, Windows, Comments and CodeQL are green.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 9c01e2e Oct 30, 2026
117 checks passed
@miguel-heygen
miguel-heygen deleted the fix/normalize-audio-peak-cap branch October 30, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant