import { useEffect, useRef } from 'react' // Signaling host for the GStreamer WebRTC server (hostname only, e.g. rapsbot-v2.local). // Set VITE_WEBRTC_HOST in .env.local or as an env var; defaults to the current page host. const signalingHost = import.meta.env.VITE_WEBRTC_HOST || window.location.hostname const SIGNALING_WS_URL = `ws://${signalingHost}:8443` export function VideoStream() { const videoRef = useRef(null) const pcRef = useRef(null) const wsRef = useRef(null) useEffect(() => { console.log('[WebRTC] Connecting to', SIGNALING_WS_URL) const pc = new RTCPeerConnection({}) const ws = new WebSocket(SIGNALING_WS_URL) pcRef.current = pc wsRef.current = ws pc.onconnectionstatechange = () => console.log('[WebRTC] PC state:', pc.connectionState) pc.oniceconnectionstatechange = () => console.log('[WebRTC] ICE state:', pc.iceConnectionState) pc.ontrack = ({ streams }) => { console.log('[WebRTC] Track received, streams:', streams.length) if (videoRef.current) videoRef.current.srcObject = streams[0] } pc.onicecandidate = ({ candidate }) => { if (candidate && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'ice', mlineindex: candidate.sdpMLineIndex, candidate: candidate.candidate, })) } } ws.onopen = () => console.log('[WebRTC] Signaling connected') ws.onclose = () => console.log('[WebRTC] Signaling closed') ws.onmessage = async (event) => { const msg = JSON.parse(event.data) console.log('[WebRTC] Signal:', msg.type, msg) if (msg.type === 'offer') { await pc.setRemoteDescription({ type: 'offer', sdp: msg.sdp }) const answer = await pc.createAnswer() await pc.setLocalDescription(answer) ws.send(JSON.stringify({ type: 'answer', sdp: answer.sdp })) console.log('[WebRTC] Answer sent') } else if (msg.type === 'ice') { await pc.addIceCandidate({ sdpMLineIndex: msg.mlineindex, candidate: msg.candidate }) } } let cleanedUp = false ws.onerror = (e) => { if (!cleanedUp) console.error('[WebRTC] Signaling error', e) } return () => { cleanedUp = true pc.close() ws.close() } }, []) return (