Skip to content

@remotion/renderer: Don't deadlock when concurrent renders merge 32+ audio tracks - #12539

Merged
JonnyBurger merged 1 commit into
remotion-dev:mainfrom
parbhatkapila4:fix/merge-audio-deadlock
Oct 22, 2026
Merged

JonnyBurger merged 1 commit into
remotion-dev:mainfrom
parbhatkapila4:fix/merge-audio-deadlock

Conversation

@parbhatkapila4

Copy link
Copy Markdown
Contributor

mergeAudioTrack() runs under a module-wide pLimit(3). With 32 or more tracks, it splits them into chunks, merges each chunk with a nested mergeAudioTrack() call, and then merges the results, all while holding its own slot. When three such merges overlap in one process, for example, three renders with many audio tracks at once, the three outer calls hold all three slots and wait for chunk merges that can never start. The renders hang with no error, and cancelling doesn't help because nothing is running.

Now only the FFmpeg calls take a slot. A merge that waits for its chunks holds none, so it can't block them, at any nesting depth or number of renders. There are still at most 3 FFmpeg merges at once.

Added a test that starts three 32-track merges at the same time with callFf() mocked. It gets stuck on main and passes with the fix, and it checks that no more than 3 FFmpeg calls run at once. I also ran it with real FFmpeg on 3 renders of 40 tracks each: stuck after 60 seconds on main, done in under half a second with the fix.

@vercel

vercel Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
bugs Ready Ready Preview Oct 22, 2026 7:06pm UTC
remotion Ready Ready Preview Oct 22, 2026 7:06pm UTC

Request Review

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

  • packages/renderer/src/merge-audio-track.ts — Moves the module-wide pLimit(3) guard off the whole mergeAudioTrack call and onto the individual FFmpeg invocations (callFf for the merge, plus createSilentAudio). A merge that awaits its recursively-invoked chunk merges now holds no slot, so three concurrent 32+-track merges can no longer occupy all three slots while waiting on queued chunk merges. Concurrency stays capped at 3 FFmpeg processes per module.
  • packages/renderer/src/test/merge-audio-track.test.ts — New regression test that fires three concurrent 32-track merges with callFf mocked, races them against a 2s timeout, and asserts maxRunning <= 3.

I confirmed the test genuinely detects the bug: it fails against the pre-fix merge-audio-track.ts (resolves as stuck after the full 2s) and passes with the fix. I also checked that external callers (create-audio.ts, merge-inline-audio-tracks.ts) are unaffected since only FFmpeg concurrency — not mergeAudioTrack call concurrency — was the intent, and that oxfmt/eslint pass on both changed files.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash | 𝕏

@JonnyBurger
JonnyBurger merged commit 3ab3466 into remotion-dev:main Oct 22, 2026
20 checks passed
@JonnyBurger

Copy link
Copy Markdown
Member

Thanks!

This branch was successfully deployed

2 active deployments
Preview – remotion — eb4ccee1 Deployed Oct 22, 2026 by vercel[bot]
Preview – bugs — eb4ccee1 Deployed Oct 22, 2026 by vercel[bot]
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.

2 participants