Repository navigation
@remotion/media: Bound paused audio decoding with a keep-alive context - #12609
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Paused decode lookahead bound (
audio-iterator-manager.ts): the scheduling priority now subtracts the liveAudioContextclock only while the player is playing, and the iterator-creationcurrentTimesnapshot while paused. While paused the frozen reference cancels out ofgetScheduledTime, leaving priority equal to the media lookahead relative to the iterator start, so a keep-alive clock can no longer admit chunks past the two-second horizon. - Playback state plumbing (
media-player.ts):getIsPlaying: () => this.playingis passed into the manager. This isfalseduring pause and buffering — both of which hold the composition frame still — so the frozen reference is the correct one in each case. - Regression test (
audio-anchor-reschedule.test.tsx): a mountedPlayerwith_experimentalKeepAudioContextAlive, a real ChromiumAudioContext, and a browser click to unlock audio. After three seconds of paused clock advancement, queued decoded audio is asserted to stay inside the two-second lookahead and playback still advances afterwards. - Fixture updates:
audio-iterator.test.ts,audio-seek-tolerance.test.ts, andvideo-with-no-frames-in-beginning.test.tssupplygetIsPlaying: () => true, preserving their existing playing-clock scheduling behavior.
The resume/seek paths remain safe because a pause→play (and buffering-end) transition forces an exact re-anchor (setGlobalTimeAnchor(..., force) → audioSyncAnchorChanged → destroyIterator + seekTo), which builds a fresh iterator with a current currentTime, so the stale creation snapshot cannot produce a burst or underrun on resume.
deepseek-v4.1-flash | 𝕏
@remotion/media: Bound paused audio decoding with a keep-alive context

With
<Player _experimentalKeepAudioContextAlive>and@remotion/mediaaudio, leaving the Player paused lets the native AudioContext keep advancing. The scheduler continues decoding beyond its lookahead, retaining unstarted nodes and their decoded PCM. This also affects hidden mounted Players.Bound paused preparation by the amount of media decoded from the current iterator's start, adjusted for playback rate. Always allow the existing minimum100ms source prebuffer; once it is ready, the existing two-second scheduling horizon bounds further paused decoding. Playing continues to use the native clock. Reuse the current queue, readiness threshold and iterator cleanup.
The earlier revision froze priority against iterator-creation wall time. That stranded audio mounted before its timeline start: the future scheduled start used the entire horizon before its initial prebuffer completed, and buffering kept playback paused. The revised calculation removes that circular wait. The100ms minimum also prevents starvation at very slow authored rates such as0.01×.
This is separate from #12409's cleanup of completed audio nodes: these nodes have never started. The corrected policy is also validated in Kino's follow-up kino-ai/kino#4780.
Validation
Refreshed against upstream main
1c5244bde0on October 26; merge commitc9d6a6af16. Re-ran all 186 media Chromium tests across 53 files, core/player/media builds, media TypeScript and changed-file lint/formatting. All pass (two existing max-params lint warnings).Full media Chromium suite: 186 tests passed across53 files. Core/player/media builds, media TypeScript, changed-file ESLint/formatting and
git diff --checkpass.Existing mounted-Player browser regression now covers current audio, three-second premounted audio, and premounted0.01× audio. It uses the existing real AAC fixture, Chromium AudioContext and a browser gesture to unlock audio. It checks bounded decoded duration after three seconds of paused clock advancement, then verifies playback advances beyond the future clip boundary.
The premount cases fail against the prior frozen-wall-clock revision; the original paused-retention check remains covered.
Kino separately verifies the affected real-asset clip boundary, rate/trim readiness regressions, hidden-player retention, pause/buffering silence, replay and full node release. These isolated runtime measurements do not establish total process/GPU memory savings or universal performance.
Why each file changes
All paths are under
packages/media/src/.audio-iterator-manager.tsmedia-player.tstest/audio-anchor-reschedule.test.tsxtest/audio-iterator.test.tstest/audio-seek-tolerance.test.tstest/video-with-no-frames-in-beginning.test.ts