feat: Make the TURN realm configurable via environment variable and ensure the viewer only reacts to the broadcaster's disconnection.

This commit is contained in:
2026-02-23 06:03:45 +01:00
parent 5ee1d39f62
commit 49e757a155
2 changed files with 11 additions and 4 deletions

View File

@@ -10,6 +10,7 @@ services:
- BROADCASTER_PASSWORD=${BROADCASTER_PASSWORD}
- TURN_USER=${TURN_USER}
- TURN_PASSWORD=${TURN_PASSWORD}
- TURN_REALM=${TURN_REALM}
coturn:
image: coturn/coturn:latest
@@ -20,6 +21,6 @@ services:
--log-file=stdout
--min-port=49152
--max-port=49252
--realm=yourdomain.com
--realm=${TURN_REALM}
--user=${TURN_USER}:${TURN_PASSWORD}
--stale-nonce

View File

@@ -3,6 +3,7 @@ const remoteVideo = document.getElementById('remoteVideo');
const overlay = document.getElementById('overlay');
let peerConnection;
let broadcasterPeerId = null; // Track who the broadcaster is
// Fetch TURN credentials dynamically from the server
const turnHost = window.location.hostname;
@@ -28,6 +29,9 @@ fetch('/turn-config')
.catch(e => console.error('Failed to load TURN config:', e));
socket.on('offer', (id, description) => {
// Track the broadcaster's socket ID so we only react to THEIR disconnect
broadcasterPeerId = id;
// Close any existing connection before creating a new one
if (peerConnection) {
peerConnection.close();
@@ -51,11 +55,9 @@ socket.on('offer', (id, description) => {
peerConnection.oniceconnectionstatechange = () => {
console.log('ICE state:', peerConnection.iceConnectionState);
if (peerConnection.iceConnectionState === 'failed') {
// Try ICE restart before giving up
console.log('ICE failed, attempting restart...');
peerConnection.restartIce();
} else if (peerConnection.iceConnectionState === 'disconnected') {
// Wait briefly then check if it recovered
setTimeout(() => {
if (peerConnection && peerConnection.iceConnectionState === 'disconnected') {
console.log('ICE still disconnected, attempting restart...');
@@ -114,11 +116,15 @@ socket.on('broadcaster', () => {
socket.emit('viewer');
});
socket.on('disconnectPeer', () => {
// CRITICAL: Only react to the BROADCASTER's disconnect, not other viewers
socket.on('disconnectPeer', (id) => {
if (id !== broadcasterPeerId) return; // Ignore other viewers disconnecting
if (peerConnection) {
peerConnection.close();
peerConnection = null;
}
broadcasterPeerId = null;
remoteVideo.classList.remove('active');
remoteVideo.srcObject = null;