Repository navigation
fix(core): Safari stops chopping audio by seeking it over and over during playback - #6854
miguel-heygen wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 1 important · 0 nits · head c33989f8
The fix itself looks right. I ran it locally: clock.safariAudio.test.ts sees 62 seeks with main's media.ts/mediaSteer.ts and passes with this PR, and the core runtime suite passes (110 files, 2656 tests). The fails without the fix: line is satisfied.
- blocker: Preflight (lint + format) fails on every workflow:
oxfmt --checkflagspackages/core/src/runtime/clock.safariAudio.test.ts:72. The body says oxfmt is clean. Runningoxfmton that file wraps theattachAudioSourceline, and that's the whole fix. - important: see the inline comment on
mediaSteer.ts:35.
Scope
Read end to end: mediaSteer.ts, the syncRuntimeMedia drift/seek/play block in media.ts, clock.ts now() and _elementTimeNeverBehind, and the new test. I did not review webkit-stops.ts (playbench only) and did not re-run the WebKit numbers. No prior reviews.
Edit accuracy: accurate 271 (base branch 271), smooth 129 of thoseThe gate passes. Quarantined, measured but not gated (0) Unstable (1)
|
c33989f to
5071aa3
Compare
What
In Safari and every WebKit, sounding audio is no longer seeked over and over while it plays. Since #6768, a played edit's audio was seeked about twice a second and stood still for most of the play, which is heard as chopped audio. Chrome is unchanged.
Why
WebKit reports a just-played or just-seeked
<audio>'s start time for 150 to 400 ms before its output begins. #6768 made the playhead stop waiting for it, so every start leaves the audio that far behind the playhead.steerMediaseeks sounding audio whose lag holds above 100 ms, and in WebKit that seek starts the same delay again: the audio lands behind by the same amount, is seeked again, and so on for the whole play.Before #6768 the playhead waited for the audio, which hid the loop most of the time but stopped the picture at cuts (and the loop still took hold in some plays, see below).
How
mediaSteer.tskeeps one more per-element fact: the runtime has just started or seeked this element and it has not yet moved in tolerance (within 40 ms of the playhead, with a settled offset). While that holds, its lag is its own output delay, so it is steered by rate (audio stays within 10%) instead of seeked, unless the lag passesMEDIA_HARD_SYNC_SECONDS(0.5 s): a second audio that stalls far behind is still seeked once.media.tsmarks an element when the sync callsplay()on it or seeks it;steerMediamarks it when it orders a seek. Audio that was in sync and then drifts past 100 ms is still seeked once. The clock is untouched, so #6768's moving playhead at cuts stays.The WebKit playbench (
webkit-stops.ts) now also reports audioseekingevents per play and the share of playing-audio time an element's clock stood still for over 50 ms, and can drive Chromium (--browser chromium) for the comparison.Compared with Remotion
How each handles a playing
<audio>that is behind the playhead. Remotion read at v4.0.539,packages/core/src.use-media-playback.ts:34, "In Safari, amplified media can lag behind by around 0.4 seconds")get-media-sync-action.ts:105)buffer-until-first-frame.ts:33)use-media-playback.ts:174-192)Remotion's choice of tolerating the lag over steering it is relevant to the "Not proven" note below: in WebKit the residual standing-still share comes partly from steering audio at 1.10x.
Test plan
mediaSteer.test.tssteers the lag a start left in audio, but still seeks one past hard sync(0.3 s steered, 0.8 s seeked).clock.safariAudio.test.tsplays one audio clip through the realTransportClockandsyncRuntimeMediafor 10 s, with an element whose time stays at its start or seek target for 150 ms before it moves, as WebKit's does. It expects no seeks and the audio within 0.1 s of the playhead at the end.clock.safariAudio.test.tssees 62 seeks in 10 s; with fix(core): the playhead keeps moving at a cut while the incoming take has not started #6768's clock change reverted it sees 0.tsc,fallow auditand the comment ratchet clean.make-media.sh) in Playwright WebKit 27.2 on macOS, 3 plays per side, playhead and audio sampled every frame:10-take edit (53.08 s):
3-take edit (24.8 s):
Chrome 152 (headless shell, Linux), 10-take edit, 6 plays per side: 9 seeks (one per cut) and 0% audio standing still on both; playhead stops 0 in all 6 plays here, 0 to 19 on main in the same interleaved runs on a loaded machine.
Not proven
This is Playwright's WebKit, not Safari itself, and not an iPhone. A real Safari run needs "Allow remote automation" turned on.
What stays of the "standing still" share in WebKit is each take's own start delay plus 300 ms stretches while the audio is steered at 1.10x: WebKit's audio clock stands still at intervals at that rate. Whether those are heard is not measured. Starting audio early by its learned start delay, as video already is, would remove both and is a separate change.
Documentation updated (not applicable)
Comments follow CONTRIBUTING.md "Comments"