Skip to content

perf(producer): the audio mix runs while capture starts its browsers - #6632

Merged
miguel-heygen merged 2 commits into
mainfrom
perf/audio-during-setup
Oct 28, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
perf/audio-during-setup

Conversation

@miguel-heygen

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

Copy link
Copy Markdown
Collaborator

What

A render's audio mix now runs while capture sets up (file server, drawElement gate probe, calibration, worker sizing) instead of before it. Capture starts as soon as both are ready.

Why

The audio stage (decode, mix, AAC encode) ran to completion before capture setup began, but nothing in setup reads its output. Audio is first needed by the disk encoder input, encode observability and the final mux. So every render with audio waited for the mix and then for the browsers, one after the other.

Related work

None.

How

  • runAudioStage starts at the same point and with the same arguments, but is no longer awaited there.
  • The join (await audioStage), with its perf, limiter and warning-policy handling moved unchanged, sits right after the capture plan and encoder preset resolve, before any capture path runs. So hasAudio / audioOutputPath are settled before the disk encoder input is built, exactly as before.
  • If setup fails before the join, the error path waits for the in-flight mix before it reports and cleans up, so no audio process outlives the render.
  • Under --strict, an audio failure still fails the render; it now surfaces after setup instead of before it.

Test plan

  • Unit test added: renderOrchestrator.audioOverlap.test.ts holds the mix open and checks that worker sizing ran while it was pending, and that a setup failure is reported only after the mix settles.
  • Fails without the fix: renderOrchestrator.audioOverlap.test.ts > sets up capture while the audio mixes, and a failure waits for the mix. With only the test applied, worker sizing never runs before the mix is released. With the error-path wait removed, the failure arrives while the mix is still running.
  • renderOrchestrator.masterBus.test.ts stopped the render by throwing from the audio stage, which now surfaces only at the join. It now stops at capture setup's file server and still checks the master chain and video clock reach the audio stage: 1 passed.
  • tsc --noEmit (producer) exit 0; new test 1 passed; renderOrchestrator.stall.test.ts 7 passed; oxfmt and oxlint clean.
  • Manual testing performed: before/after on the real CLI (below).
  • Documentation updated (not applicable)
  • Comments follow CONTRIBUTING.md "Comments"

Before / after

Published [email protected] vs the same bundle with only this change, Apple M4 Pro (14 cores, 24 GB), hyperframes render, repo fixtures with an audio track, interleaved, 5 runs each, medians. wall - compile drops compile, which is network-bound for these fixtures (a remote video).

fixture wall - compile before after output
style-11-prod, 1080x1920, 14 s, audio 9.91 s 9.12 s (-8.0%) byte-identical (same sha256, all 10 runs)
overlay-montage-prod + one mix-blend layer, 42 s, audio 23.43 s 22.10 s (-5.7%) within this fixture's own run-to-run variation

The CLI's stage line still reports audio with its own duration; it now overlaps setup.

@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 · 0 important · 0 nits · head 0fb4477c

  • blocker — required CI › Producer: unit tests fails at this head: renderOrchestrator.masterBus.test.ts > the local renderer gives the shared audio stage its master chain and video clock expects "audio stage reached" but gets No network in unit tests: 127.0.0.1. Its runAudioStage mock throws to stop the render. With the stage no longer awaited at renderOrchestrator.ts:3496, that rejection only surfaces at the join (:4538), so setup runs first and hits the file server. The test needs to stop the render some other way (or stub setup), and still check that masterFxChain and the video clock reach the stage.
Scope

Read the full diff and the setup window between the audio start and the join: no return or capture path runs before the join, hasAudio/audioOutputPath are only read after it, and pendingAudio's .catch keeps an early audio rejection from going unhandled. Other workflows were still running when this was posted.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 120 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 (1)

  • 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: APPROVE — 1 resolved, 0 open, 0 new · 0fb4477c → e47524be (master-bus test stops at createFileServer, still pins master chain + video clock; CI green — one bun install hang in runtime contract passed on rerun)

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 1d97ed2 Oct 28, 2026
167 of 170 checks passed
@miguel-heygen
miguel-heygen deleted the perf/audio-during-setup branch October 28, 2026 08:19
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