Play

Phones and Safari

How the player behaves on iPhone, Safari and Android, why Apple devices use the LL-HLS fallback, and what to expect from sound and background tabs.

The same <nearglass-player> tag runs on phones. What differs is which path plays: some phones play over MoQ, and every Apple device plays the LL-HLS fallback today.

What plays where

BrowserPlays withNotes
Chrome, Edge on a computerMoQ
Firefox on a computerMoQ
Chrome for AndroidMoQthe phone's H.264 decoder has to take the stream; if no frame comes, the player falls back after 3 s
Samsung InternetMoQ
Firefox for AndroidLL-HLSit has no WebCodecs; give the player hls.js (Browsers without native HLS)
Safari on iPhone, iPad and MacLL-HLSthe browser's own HLS
Chrome, Firefox, Edge on iPhone and iPadLL-HLSon iOS every browser is built on Safari's engine, so they behave as Safari does
any browser on a network that blocks UDPLL-HLSMoQ needs QUIC, which runs over UDP

The bar under the picture says which: "Low latency" or "Compatibility mode".

Why Apple devices use the fallback

Safari has had WebTransport since version 26.4, but it has a bug (WebKit bug 319818): it never gives back the flow-control credit for a WebTransport connection, so each connection stops receiving after a limited amount of data or number of streams, in minutes at a video stream's rate. Chrome and Firefox on the same servers are not affected. It cannot be detected by asking the browser; the player recognises WebKit's WebTransport by what only it has, on a browser made by Apple, and treats it as unusable. The result: on Safari and every iPhone browser the player goes straight to LL-HLS, with reason: 'webkit-flow-control'.

The status was open when it was last checked, on 2026-10-21. The player's engine can also keep MoQ going on WebKit by moving to a fresh connection before the limit is reached; that is off by default, is a test option of createPlayer() (webkit: 'on') and not of the element, and has been shown to work only against a model of the bug and in desktop Chrome pretending to be WebKit. When WebKit fixes the bug, the default will change; the page's code does not need to.

Two consequences:

  • A stream a device publishes with the SDK has no LL-HLS, so on an Apple device it shows the "cannot play" message with advice to use Chrome on a computer or Android. That sentence says Chrome on Android for a reason: no browser on an iPhone is an alternative.
  • Driving is not supported on Apple devices today. A driver's page needs MoQ for its commands, and its picture would be the fallback, which a driver must not rely on (Controller seats). Watching works.

Sound on a phone

  • Video starts muted and plays inline (the element sets playsinline and muted), so a stream starts by itself. Sound needs one tap on the Sound button, which is the user gesture iOS requires. The same holds for every browser's autoplay rules.
  • The silent switch. On an iPhone the ring/silent switch normally mutes Web Audio. On the Sound tap the player asks iOS for the playback audio session (navigator.audioSession, or where that does not exist a silent audio element), so sound plays with the switch on, as a video would.
  • A hidden page turns the sound off. Another app in front, the screen locked, a different tab: by default the sound is turned off as if the viewer had pressed Sound, nothing is downloaded or decoded for it, and it stays off when the page returns until the viewer taps Sound. Set background-audio for a page people listen to with the screen off (Sound). The fallback follows the same rule.
  • Listen for audiochange to keep your own Sound control honest.

Background and returning

  • A hidden page keeps its seat: the player tells the API the page is hidden, and the seat then lives 60 s without a heartbeat instead of 20 s, because browsers slow a hidden page's timers. A phone locked longer than that loses its seat; the page shows "Your seat was given up. Reload to watch again." when the viewer comes back.
  • Over MoQ, a hidden page stops downloading video after 30 s and closes its session after 5 minutes (unless sound is playing in the background), and starts again from the live edge when the page is shown.
  • Closing a tab, or leaving the page, gives the seat up at once.

Testing without a phone

You can see the Apple path in desktop Chrome by making the page look like WebKit before the player loads. This only checks the player's decision, not Apple's player:

<script>
  Object.defineProperty(navigator, 'vendor', { get: () => 'Apple Computer, Inc.' });
  window.WebTransport = class { get anticipatedConcurrentIncomingUnidirectionalStreams() { return 1; } };
</script>

The player then reports fallback with reason: 'webkit-flow-control'. Proving the behaviour on a device needs a real iPhone or Mac.

On this page