web: prefer video tag with gesture audio unlock

This commit is contained in:
every.channel 2026-02-24 23:21:19 -08:00
parent c545b2381d
commit ad81b9791a
No known key found for this signature in database
2 changed files with 63 additions and 7 deletions

View file

@ -169,10 +169,16 @@ function mountPlayer(relayUrl, name) {
watch.connection.websocket = { enabled: false };
}
const canvas = document.createElement("canvas");
canvas.className = "canvas";
watch.appendChild(canvas);
// Prefer a video element for native controls/audio routing.
// Start muted to satisfy autoplay policy, then unlock audio on user gesture.
const video = document.createElement("video");
video.className = "archiveVideo";
video.controls = true;
video.autoplay = true;
video.muted = true;
video.volume = 1;
video.playsInline = true;
watch.appendChild(video);
mount.appendChild(watch);
const forceAudioOn = () => {
try {
@ -182,9 +188,33 @@ function mountPlayer(relayUrl, name) {
// Best effort only.
}
};
forceAudioOn();
window.setTimeout(forceAudioOn, 1000);
window.setTimeout(forceAudioOn, 4000);
const unlockAudio = () => {
forceAudioOn();
watch.backend?.paused?.set?.(true);
watch.backend?.paused?.set?.(false);
video.muted = false;
video.volume = 1;
void video.play().catch(() => {});
setHint(`Live: subscribed to ${name} (audio unlocked)`, "ok");
};
document.addEventListener("pointerdown", unlockAudio, { once: true });
video.addEventListener("pointerdown", unlockAudio, { once: true });
void video.play().catch(() => {});
// If video-element rendering stalls, fall back to canvas rendering.
window.setTimeout(() => {
const stalled = video.readyState < 2 || (video.currentTime === 0 && !video.paused);
if (!stalled) return;
const canvas = document.createElement("canvas");
canvas.className = "canvas";
try {
video.remove();
watch.appendChild(canvas);
setHint(`Live: subscribed to ${name} (canvas fallback)`, "warn");
} catch (_) {
// Ignore fallback errors.
}
}, 9000);
bindPlayerSignals(watch, name);
}