Web media interoperability

The same video, seconds out of sync, depending on your browser

Inside a video file there can be a tiny instruction that says “hold the picture back a moment so it lines up with the sound.” Some browsers follow it. Some ignore it. And the surprising part: the same browser can do both, depending on how the video is loaded.

TL;DR. Two tiny demos run right on this page, one at a time, so you can watch the problem yourself; the timeline under the player shows it even with sound off. Below them: why it happens, and where each browser and the spec now stand.

What’s actually going on

A video file can carry an edit list: a small note to the player. Ours says “delay the picture by 3 seconds”, so the picture and a separately-timed soundtrack end up aligned. (Three seconds is deliberately exaggerated to make the effect unmissable; the real stream that started this was off by about two.) Nothing exotic; it’s a standard part of the MP4 format that editing tools emit all the time.

To make the effect impossible to miss, the test file has a white flash in the picture and a beep in the sound, positioned so they coincide only if the 3-second delay is applied:

Delay applied
(correct)
⚡🔊
video
in sync
Delay dropped
(the bug)
🔊
video
3 s early
−3−2 −10 +1+2 +3

Seconds relative to the beep. The beep (audio) is fixed at 0; only the video flash moves, landing 3 s early when the delay is dropped.

Everything else is identical: the same bytes in every browser. The only thing that changes the outcome is the browser, and how it loads the video.

Try it: one demo at a time

Pick a demo. Only one plays at a time; two beeps together would make it impossible to judge whether a flash and a beep line up, which is the whole reason. Sound is optional: the timeline under the player shows the offset as a visible gap, so it reads fine muted (handy on a phone). Then reopen this page in a different browser and watch it flip.

Pick a demo above to start.
Beep = the only sound in the clip (a 1 kHz blip at 4 s). Flash = the white video frame. Their gap on the timeline is the desync.

Prefer the bare, single-purpose versions? The originals (linked from the browser bug reports) are still here: streaming (MSE) · plain file.

The twist: no browser agreed with itself

Put the two demos side by side and a pattern appears; read across each row:

Streaming
(MSE)
Plain file
(<video src>)
Chrome drops3 s early followsin sync
Firefox followsin sync drops3 s early
Safari drops*shipping; trunk-fixed, unshipped followsin sync

*Every shipping Safari still drops the offset under streaming: Safari 26.5.2 and 26.6 (releases) and 27.0 beta 1, as of 6 Aug 2026. WebKit’s fix landed in trunk on 7 Jul 2026 (my report bug 319998, resolved as a duplicate of bug 316870 where the fix landed, 316626@main) but is not in any shipping release or beta yet; confirmed applying correctly in Safari Technology Preview Release 249 (WebKit 21626.1.1), tested 3 Aug 2026. Chrome also still drops it today; a fix is intended, not shipped (see below). So on today’s browsers the streaming demo is wrong in both Chrome and Safari.

Chrome and Firefox are mirror images, and today no shipping engine handles the same file the same way in both modes. There was no single “broken browser” to point at, because there was no agreed, written-down answer for what should happen. That’s what turned a bug report into an interoperability question: not “who’s wrong,” but “what’s the correct behaviour, and can everyone converge on it.”

Why it matters

This is one concrete way a live or on-demand video stream can sit out of lip-sync in the browser: not a drift but a fixed offset, constant for the whole stream. The error itself is obvious; its cause is invisible in ordinary content, and only pin-pointable with a file engineered to expose it. The real stream sat about 1.6 to 2.0 seconds out, the exact figure re-minted on every encoder restart, which is part of what made it confusing. Reducing that to a ~12 KB reproduction is what made it possible to file precisely, in the same terms, against every engine and the spec at once.

Where it stands

Filed as an interoperability clarification (observation, evidence, question), against every engine and the spec at once, rather than as an accusation. Status as of 23 July 2026: