const videoElement = document.getElementById('video'); let peerConnection; // Renamed for clarity let wsConnection; // Removed mediaConstraints and iceCandidates (not needed here) const wsUrl = "ws://localhost:8080/api/v1/preview/5a59a94f-264a-4d24-9e57-8a9be0ecbdbd/KALANI-3.LOCAL%20%28OBS%29"; // Replace with your WebSocket URL if necessary const peerConnectionConfig = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] }; // Initialize WebSocket connection function initWebSocket() { wsConnection = new WebSocket(wsUrl); wsConnection.onopen = () => { console.log('Connected to WebSocket'); createOffer(); }; wsConnection.onmessage = async (message) => { const signal = JSON.parse(message.data); console.log("Received signal:", signal); // Add logging // The browser initiates with an offer, so it expects an answer or ICE candidates. // It should not receive an 'offer'. if (signal.type === 'answer') { handleAnswer(signal); } else if (signal.type === 'ice') { handleIceCandidate(signal); } else { console.warn("Received unexpected signal type:", signal.type); } }; wsConnection.onerror = (error) => { console.error('WebSocket Error:', error); }; wsConnection.onclose = (event) => { console.log('WebSocket closed:', event.code, event.reason); }; } // Create an SDP offer to receive media async function createOffer() { peerConnection = new RTCPeerConnection(peerConnectionConfig); // Set up event handlers peerConnection.onicecandidate = handleIceCandidateEvent; peerConnection.ontrack = (event) => { console.log("Track received:", event.track, "Stream:", event.streams[0]); if (videoElement.srcObject !== event.streams[0]) { videoElement.srcObject = event.streams[0]; console.log("Assigned stream to video element"); } }; peerConnection.oniceconnectionstatechange = () => { console.log("ICE connection state:", peerConnection.iceConnectionState); }; peerConnection.onconnectionstatechange = () => { console.log("Peer connection state:", peerConnection.connectionState); }; // Configure to receive video and audio peerConnection.addTransceiver('video', { direction: 'recvonly' }); peerConnection.addTransceiver('audio', { direction: 'recvonly' }); try { console.log("Creating offer..."); const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); console.log("Offer created and set as local description:", offer); const signalMessage = { type: 'offer', sdp: offer.sdp }; console.log("Sending offer via WebSocket:", signalMessage); wsConnection.send(JSON.stringify(signalMessage)); } catch (error) { console.error("Error creating offer:", error); } } // Handle SDP answer from the server async function handleAnswer(signal) { console.log("Handling answer:", signal); const remoteDescription = new RTCSessionDescription({ type: 'answer', sdp: signal.sdp }); try { await peerConnection.setRemoteDescription(remoteDescription); console.log("Remote description (answer) set successfully."); } catch (error) { console.error("Error setting remote description (answer):", error); } } // Handle ICE candidates generated locally (send to server) function handleIceCandidateEvent(event) { console.log("Local ICE candidate event:", event); if (event.candidate) { console.log("Sending ICE candidate:", event.candidate); const iceMessage = { type: 'ice', ice: { candidate: event.candidate.candidate, sdpMid: event.candidate.sdpMid, sdpMLineIndex: event.candidate.sdpMLineIndex } }; wsConnection.send(JSON.stringify(iceMessage)); } else { console.log("All local ICE candidates have been sent."); } } // Handle ICE candidate received from the server async function handleIceCandidate(signal) { console.log("Handling received ICE candidate:", signal); if (!signal.ice || !signal.ice.candidate) { console.warn("Received incomplete ICE candidate signal:", signal); return; } try { const candidate = new RTCIceCandidate({ candidate: signal.ice.candidate, sdpMid: signal.ice.sdpMid, sdpMLineIndex: signal.ice.sdpMLineIndex }); await peerConnection.addIceCandidate(candidate); console.log("Added received ICE candidate successfully."); } catch (error) { console.error("Error adding received ICE candidate:", error); } } // Initialize the connection when the page loads window.onload = initWebSocket;