Skip to content

fix(cli): normalize-audio --reference stops short of the peak ceiling instead of refusing - #7254

Merged
miguel-heygen merged 2 commits into
mainfrom
fix/normalize-reference-limit
Nov 5, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
fix/normalize-reference-limit

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

What

hyperframes normalize-audio --reference <a> --target <b> --write no longer refuses when a full match would push the target past Studio's ceilings. It applies the most gain that fits under -1.5 dBTP and the +12 dB authoring ceiling, writes it, and says how far under the reference that leaves the target:

#speaker-opening -15.0 LUFS → #speaker-closing -18.0 LUFS
Reaches -16.5 LUFS, 1.5 dB under the reference (stopped short of -1.5 dBTP).

Why

A report: matching a closing speaker to the opening one refused the write with "Matching #speaker-closing would clip at +1.5 dBFS; limit or preprocess the source first". The absolute mode of the same command (--target with a LUFS goal) already handles this case another way: it never refuses, stops at the same ceilings, and names the limit. One command had two rules for one constraint, and the stricter one left the person with an error and nothing written.

How

  • One rule, one owner: fittedGain in loudness.ts picks the most of the wanted gain under both ceilings and names the limit that stopped it. absoluteLoudnessPlan and audioNormalizationPlan both call it. A limit still never cuts gain already authored when the wish is a boost.
  • audioNormalizationPlan returns limitedBy like the absolute plan, so --json carries it too.
  • The CLI prints how far under the reference the target lands, and leaves the file alone when a limit leaves no gain to change ("Cannot get closer", as the absolute mode does).
  • docs/packages/cli.mdx and the CLI README say what the command does now instead of "refuses".
  • A match whose peak lands between -1.5 and 0 dBTP used to be written in full; it now stops at -1.5 dBTP, the ceiling the absolute mode already keeps.

Test plan

  • Unit tests added/updated

  • Manual testing performed

  • Documentation updated (if applicable)

  • Comments follow CONTRIBUTING.md "Comments": they say why, not what, and a bug fix says what the code must do and how to reproduce the bug

  • fails without the fix: with main's loudness.ts and normalize-audio.ts, the 4 new tests fail: "writes the most gain that stays under -1.5 dBTP and says how far under the reference that leaves it" (the command, with --write: the printed line and the written data-volume="1.188502"), "stops a boost at Studio's +12 dB ceiling and names it", "stops a boost that would pass -1.5 dBTP there, as the absolute target does", "names no limit when the match fits". All pass here.

  • 3 runs in a row: normalize-audio.test.ts and normalize-audio.command.test.ts (35 tests), and studio-server's loudness.test.ts (47), whose absolute-plan tests now run through the shared fittedGain. oxfmt --check, the comment ratchet and tsc for studio-server clean. The CLI's tsc reports only 5 errors in checkFindingInspect and checkTypes, which import @hyperframes/inspector (not built in that tree); this PR doesn't touch them.

  • Not covered: a run on a real recording; the measurement step is mocked in the command test, as the existing command tests do.

@mintlify

mintlify Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Nov 5, 2026, 6:10 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@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 · 0 blocker · 0 important · 1 nit · head d40aa021

  • nit: packages/cli/README.md:70-71 still says the command "refuses unsafe boosts that exceed Studio's +12 dB ceiling or would clip". docs/packages/cli.mdx got the new wording, but the README didn't, so it now describes the old behavior.
Scope

Read the whole diff, plus normalizeAudio, plannedNormalization and absoluteOutcome. fittedGain gives the same result as the absolute-mode reduce it replaces. With previousGainDb = -Infinity (volume 0), the boost guard is a no-op, so applied = limited. The "under the reference" figure can't go negative, because applied ≤ wanted on both the boost and cut branches. The reference-mode heldAtLimit matches absoluteOutcome === "held" under the !withinTolerance gate. No other callers of audioNormalizationPlan exist outside the CLI. Intended behavior change: matches that land between -1.5 and 0 dBTP used to be written in full and now stop at -1.5 dBTP; the docs cover this.

Fails-without-fix check: with main's loudness.ts and normalize-audio.ts, the 4 named tests fail and the other 31 pass. At head, all 35 CLI tests and 47 studio-server loudness.test.ts tests pass. CI was still running at review time (CI, Docs, CodeQL, Windows render); nothing had failed.

— Genesis V2 reviewer

@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 — 1 resolved, 0 open, 0 new · d40aa021 → d2b6f0cb (README-only change, rewording to match cli.mdx; same base). Nothing has failed in CI so far.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 107 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 (8)

Unstable (2)

  • seqplainkeys-none-px-r0-root-z100: 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 / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true
  • seqab-none-center-r0-root-z100: tracking 0.03, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit 2f21955 Nov 5, 2026
90 of 91 checks passed
@miguel-heygen
miguel-heygen deleted the fix/normalize-reference-limit branch November 5, 2026 19:12
SanHsien added a commit to SanHsien/hyperframes that referenced this pull request Nov 6, 2026
…view

Adopts heygen-com#7240 (deferred frame extraction leaves the distributed code),
heygen-com#7241 (a capture segment extracts and deletes its own frames), heygen-com#7255
(segmented and sequential capture check drawElement samples), heygen-com#7254
(normalize-audio --reference stops short of the peak ceiling), heygen-com#7256
(engine names a failed script's origin first), heygen-com#7258 (SVG gradient text
judged by its stops) and heygen-com#7242 (windowed source frames, off unless
HF_VIDEO_FRAME_WINDOW=true). Release v0.9.17 is not synced wholesale;
the producer packed budget takes upstream's +12000 from this range.
Watermark advances to 32eb4c3.

Co-authored-by: Vance Ingalls <vance@heygen.com>
Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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