Mute media skipped by content-visibility

#40781006 Filed 2021-07-27 Accepted / P4 CL 8420516 CSSWG resolution

What this page checks

The CSSWG resolved that a media element skipped by content-visibility should be muted and should not fire its media events while it stays skipped. This sampler exercises the parts of that behavior that are observable from script, so the same page can be loaded on a stock browser and on a build with the feature enabled and the two results compared directly.

How to run

Stock behavior (feature off) - just load this page and press Run all cases.

Feature on:

chrome --enable-blink-features=ContentVisibilityMediaPlayback \
  https://static.januschka.com/i-40781006/

# or, for everything experimental:
chrome --enable-experimental-web-platform-features

The media is sample-5s.mp4 (5 s, H.264 + AAC), fetched once and reused as a blob URL by every case, so the page needs network access on first load. Cases A-E are automatic. Cases F-H need a click or headphones, because the signal they check (actual audibility, picture-in-picture) is not readable from script.

Detected behavior: not probed yet media: not loaded

Expected results

CaseFeature off (stock)Feature on
A - content-visibility: hidden ancestorimmediatedeferred
B - content-visibility: auto, scrolled outimmediatedeferred
C - flush on revealn/a (never deferred)event arrives on reveal, in order
D - flush on currentTime readn/aevent arrives while still skipped
E - event coalescing3 events1 event (last value wins)
F - audibilityaudible while skippedsilent while skipped
G - autoplay interactionblocked as usualobserve whether reveal produces sound
H - picture-in-pictureaudibleaudible (PiP is exempt)

Automatic cases

Manual cases

Notes for review

Observability

Script cannot read the effective volume, so the mute half of the behavior is only checkable by ear (case F) or via the tab audio indicator. The event half is fully scriptable, which is what cases A-E rely on.

Areas worth poking at

Case E documents that same-type events are collapsed while skipped, so intermediate values are not delivered and the relative order against other deferred event types changes.

Case G covers the interaction with the autoplay policy: while the element is treated as effectively silent, setVolume() and setMuted() take the muted path, so it is worth confirming what happens to audibility at the moment the element is revealed.

Case D exists because the patch flushes deferred events from the currentTime getter, which makes a read of a hot attribute observable as an event-timing change.

Links

↗ Issue 40781006 ↗ CL 8420516 ↗ CSSWG resolution