diff --git a/native-app/src/hooks/useHeliumStreamer.ts b/native-app/src/hooks/useHeliumStreamer.ts index 2aecc05..3c25f83 100644 --- a/native-app/src/hooks/useHeliumStreamer.ts +++ b/native-app/src/hooks/useHeliumStreamer.ts @@ -11,6 +11,7 @@ import { getSignalingUrl } from "../lib/signaling"; import type { IncomingSignalingMessage, NativeIceServer, + NativeIceCandidateInit, NativeSessionDescriptionInit, } from "../types/signaling"; @@ -31,6 +32,25 @@ interface UseHeliumStreamerResult { stopSharing: () => void; } +function serializeIceCandidate(candidate: RTCIceCandidate): NativeIceCandidateInit { + const raw = candidate as unknown as { + candidate?: string; + sdpMid?: string | null; + sdpMLineIndex?: number | null; + toJSON?: () => NativeIceCandidateInit; + }; + + if (typeof raw.toJSON === "function") { + return raw.toJSON(); + } + + return { + candidate: raw.candidate ?? "", + sdpMid: raw.sdpMid ?? null, + sdpMLineIndex: raw.sdpMLineIndex ?? null, + }; +} + export function useHeliumStreamer( iceServers: NativeIceServer[], ): UseHeliumStreamerResult { @@ -113,10 +133,15 @@ export function useHeliumStreamer( return; } + const candidate = serializeIceCandidate(event.candidate); + if (!candidate.candidate) { + return; + } + sendMessage({ event: "ice-candidate", targetId: viewerId, - candidate: event.candidate, + candidate, }); }; @@ -199,11 +224,23 @@ export function useHeliumStreamer( } setStatus("requesting screen capture"); - const stream = await mediaDevices.getDisplayMedia(); + const stream = await (mediaDevices as unknown as { + getDisplayMedia: (constraints?: { + video?: boolean; + audio?: boolean; + }) => Promise; + }).getDisplayMedia({ + video: true, + audio: true, + }); streamRef.current = stream; setStreamUrl(stream.toURL()); setIsSharing(true); + const videoTrackCount = stream.getVideoTracks().length; + const audioTrackCount = stream.getAudioTracks().length; + setStatus(`capturing ${videoTrackCount} video / ${audioTrackCount} audio tracks`); + stream.getTracks().forEach((track) => { const streamTrack = track as unknown as MediaStreamTrack & { onended: (() => void) | null;