fix: enable audio playback via manual start stream button

Browser autoplay policy blocks audio without user interaction.
Store audio elements in ref and trigger playback when user clicks
the existing 'Manually start stream' button.
This commit is contained in:
Alex P 2025-10-28 14:01:08 +02:00
parent b2a57a64e9
commit ef86af8afc
1 changed files with 9 additions and 4 deletions

View File

@ -26,6 +26,7 @@ import { m } from "@localizations/messages.js";
export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssues: boolean }) { export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssues: boolean }) {
// Video and stream related refs and states // Video and stream related refs and states
const videoElm = useRef<HTMLVideoElement>(null); const videoElm = useRef<HTMLVideoElement>(null);
const audioElementsRef = useRef<HTMLAudioElement[]>([]);
const { mediaStream, peerConnectionState } = useRTCStore(); const { mediaStream, peerConnectionState } = useRTCStore();
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const [isPointerLockActive, setIsPointerLockActive] = useState(false); const [isPointerLockActive, setIsPointerLockActive] = useState(false);
@ -330,7 +331,6 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu
if (!peerConnection) return; if (!peerConnection) return;
const abortController = new AbortController(); const abortController = new AbortController();
const signal = abortController.signal; const signal = abortController.signal;
const audioElements: HTMLAudioElement[] = [];
peerConnection.addEventListener( peerConnection.addEventListener(
"track", "track",
@ -339,11 +339,14 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu
addStreamToVideoElm(e.streams[0]); addStreamToVideoElm(e.streams[0]);
} else if (e.track.kind === "audio") { } else if (e.track.kind === "audio") {
const audioElm = document.createElement("audio"); const audioElm = document.createElement("audio");
audioElm.autoplay = true;
audioElm.srcObject = e.streams[0]; audioElm.srcObject = e.streams[0];
audioElm.style.display = "none"; audioElm.style.display = "none";
document.body.appendChild(audioElm); document.body.appendChild(audioElm);
audioElements.push(audioElm); audioElementsRef.current.push(audioElm);
audioElm.play().catch(() => {
console.debug("[Audio] Autoplay blocked, will be started by user interaction");
});
} }
}, },
{ signal }, { signal },
@ -351,10 +354,11 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu
return () => { return () => {
abortController.abort(); abortController.abort();
audioElements.forEach((audioElm) => { audioElementsRef.current.forEach((audioElm) => {
audioElm.srcObject = null; audioElm.srcObject = null;
audioElm.remove(); audioElm.remove();
}); });
audioElementsRef.current = [];
}; };
}, },
[addStreamToVideoElm, peerConnection], [addStreamToVideoElm, peerConnection],
@ -564,6 +568,7 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu
show={hasNoAutoPlayPermissions} show={hasNoAutoPlayPermissions}
onPlayClick={() => { onPlayClick={() => {
videoElm.current?.play(); videoElm.current?.play();
audioElementsRef.current.forEach(audioElm => audioElm.play().catch(() => undefined));
}} }}
/> />
</div> </div>