Fox saw repeated "stream stalled" and "autoplay blocked: aborted at
user's request" log lines on both auto-enrolled mobile listeners and
host self-monitor clicks. Three coupled causes:
1. applySinkTo() was called sync-fire-and-forget right before setting
.src and calling .play(). setSinkId() can re-init the media
pipeline; when it landed during the in-flight load it aborted the
request — Firefox surfaces that as
"The fetching process for the media resource was aborted by the
user agent at the user's request." on the play() promise. We
wrongly logged that as autoplay-blocked. Fix: await applySinkTo()
BEFORE assigning .src.
2. The 'stalled' event handler called unmuteWebRtcOnFail every time
it fired. 'stalled' fires constantly during normal mobile-cellular
buffering and isn't a terminal failure. Each fire ping-ponged the
audio path between WebRTC (unmuted) and the still-loading HTTP
stream. Drop the handler — only 'error' and a rejected play()
promise indicate real failure.
3. A second toggle-on for the same pubHex (auto-enroll race when
peer-joined fires during initial enrol) reassigned .src on the
same <audio> element, aborting the prior load with the same abort
error. Make startStream idempotent: if the element already has
our wantUrl and no .error, return immediately.
Plus two cheap mobile-friendly attrs on the dynamic <audio>:
- preload="auto" so buffering starts before play() (gives the
user-gesture window time to last past the initial fill)
- playsInline so iOS/Safari doesn't escalate to a fullscreen player
startStream is now async — callers (toggleStreamFor,
autoEnableDjModeForListener) fire-and-forget the returned promise,
which is fine since all error paths are already caught inside.
Tests green (83 fsm + 16 zebra-spaces).
|
||
|---|---|---|
| .. | ||
| blog | ||
| fonts | ||
| chat.html | ||
| host-your-own.html | ||
| how-it-works.html | ||
| index.html | ||
| kernel.html | ||
| stamp.js | ||
| zebra-audio.html | ||
| zebra-spaces.html | ||