Skip to content

Commit 5e9e755

Browse files
committed
fix: muted functionality
1 parent 06faf49 commit 5e9e755

File tree

3 files changed

+38
-68
lines changed

3 files changed

+38
-68
lines changed

ui/src/components/room.tsx

+18-16
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface MediaStreamPlayerProps {
2020
function MediaStreamPlayer({ stream }: MediaStreamPlayerProps) {
2121
const videoRef = useRef<HTMLVideoElement>(null);
2222
const [needsPlayButton, setNeedsPlayButton] = useState(false);
23+
const hasVideo = stream.getVideoTracks().length > 0;
2324

2425
useEffect(() => {
2526
if (!videoRef.current || !stream) return;
@@ -124,7 +125,6 @@ function Stage({ connected, onStreamReady }: StageProps) {
124125
className="w-full h-full object-cover"
125126
autoPlay
126127
loop
127-
// muted
128128
playsInline
129129
>
130130
<source src="/loading.mp4" type="video/mp4" />
@@ -133,19 +133,23 @@ function Stage({ connected, onStreamReady }: StageProps) {
133133
);
134134
}
135135

136+
const hasVideo = remoteStream.getVideoTracks().length > 0;
137+
136138
return (
137139
<div className="relative w-full h-full">
138140
<MediaStreamPlayer stream={remoteStream} />
139-
<div className="absolute top-2 right-2 bg-black/50 text-white px-2 py-1 rounded text-sm">
140-
<TooltipProvider>
141-
<Tooltip>
142-
<TooltipTrigger>{frameRate} FPS</TooltipTrigger>
143-
<TooltipContent>
144-
<p>This is the FPS of the output stream.</p>
145-
</TooltipContent>
146-
</Tooltip>
147-
</TooltipProvider>
148-
</div>
141+
{hasVideo && (
142+
<div className="absolute top-2 right-2 bg-black/50 text-white px-2 py-1 rounded text-sm">
143+
<TooltipProvider>
144+
<Tooltip>
145+
<TooltipTrigger>{frameRate} FPS</TooltipTrigger>
146+
<TooltipContent>
147+
<p>This is the FPS of the output stream.</p>
148+
</TooltipContent>
149+
</Tooltip>
150+
</TooltipProvider>
151+
</div>
152+
)}
149153
</div>
150154
);
151155
}
@@ -200,18 +204,16 @@ export function Room() {
200204

201205
const handleConnected = useCallback(() => {
202206
setIsConnected(true);
203-
204-
console.debug("Connected!");
205-
206207
connectingRef.current = false;
207208
}, []);
208209

209210
const handleDisconnected = useCallback(() => {
210211
setIsConnected(false);
211-
212-
console.debug("Disconnected!");
213212
}, []);
214213

214+
// Check if we have video tracks in the local stream
215+
const hasLocalVideo = localStream && localStream.getVideoTracks().length > 0;
216+
215217
return (
216218
<main className="fixed inset-0 overflow-hidden overscroll-none">
217219
<meta

ui/src/components/webcam.tsx

+18-30
Original file line numberDiff line numberDiff line change
@@ -162,25 +162,7 @@ export function Webcam({ onStreamReady, deviceId, frameRate, selectedAudioDevice
162162
};
163163

164164
const newStream = await navigator.mediaDevices.getUserMedia(constraints);
165-
166-
// Create a new stream with only the tracks we want
167-
const filteredTracks: MediaStreamTrack[] = [];
168-
if (deviceId !== "none") {
169-
filteredTracks.push(...newStream.getVideoTracks());
170-
}
171-
if (selectedAudioDeviceId !== "none") {
172-
filteredTracks.push(...newStream.getAudioTracks());
173-
}
174-
175-
// Stop any tracks we're not using
176-
newStream.getTracks().forEach(track => {
177-
if (!filteredTracks.includes(track)) {
178-
track.stop();
179-
}
180-
});
181-
182-
const filteredStream = new MediaStream(filteredTracks);
183-
return filteredStream;
165+
return newStream;
184166
} catch (error) {
185167
console.error("Error accessing media devices.", error);
186168
return null;
@@ -192,13 +174,9 @@ export function Webcam({ onStreamReady, deviceId, frameRate, selectedAudioDevice
192174
if (frameRate == 0) return;
193175

194176
startWebcam().then((newStream) => {
195-
replaceStream(newStream);
196177
if (newStream) {
197-
// Only pass to StreamCanvas if we have video
198-
if (deviceId !== "none") {
199-
setStream(newStream);
200-
}
201-
// Only call onStreamReady if we have a valid stream
178+
replaceStream(newStream);
179+
setStream(newStream);
202180
onStreamReady(newStream);
203181
}
204182
});
@@ -208,8 +186,20 @@ export function Webcam({ onStreamReady, deviceId, frameRate, selectedAudioDevice
208186
};
209187
}, [deviceId, frameRate, selectedAudioDeviceId, startWebcam, replaceStream, onStreamReady]);
210188

211-
// Only render StreamCanvas if video is enabled
212-
if (deviceId === "none") {
189+
const hasVideo = stream && stream.getVideoTracks().length > 0;
190+
const hasAudio = stream && stream.getAudioTracks().length > 0;
191+
192+
// Return audio-only placeholder if we have audio but no video
193+
if (!hasVideo && hasAudio) {
194+
return (
195+
<div className="w-full h-full flex items-center justify-center">
196+
<span className="text-white">Audio Only</span>
197+
</div>
198+
);
199+
}
200+
201+
// Return null if we have neither video nor audio
202+
if (!stream || (!hasVideo && !hasAudio)) {
213203
return null;
214204
}
215205

@@ -218,9 +208,7 @@ export function Webcam({ onStreamReady, deviceId, frameRate, selectedAudioDevice
218208
<StreamCanvas
219209
stream={stream}
220210
frameRate={frameRate}
221-
onStreamReady={(processedStream) => {
222-
// Don't call onStreamReady here anymore since we handle it above
223-
}}
211+
onStreamReady={() => {}} // We handle stream ready in the parent component
224212
/>
225213
</div>
226214
);

ui/src/hooks/use-peer.ts

+2-22
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ export function usePeer(props: PeerProps): Peer {
8181
const pc = new RTCPeerConnection(configuration);
8282
setPeerConnection(pc);
8383

84-
// Only add video transceiver if we have video tracks
8584
if (localStream.getVideoTracks().length > 0) {
8685
pc.addTransceiver("video");
8786
}
@@ -90,38 +89,19 @@ export function usePeer(props: PeerProps): Peer {
9089
pc.addTrack(track, localStream);
9190
});
9291

93-
// Create control channel for both negotiation and control
9492
const channel = pc.createDataChannel("control");
9593

9694
channel.onopen = () => {
97-
console.log("[usePeer] Control channel opened, readyState:", channel.readyState);
9895
setControlChannel(channel);
9996
};
10097

10198
channel.onclose = () => {
102-
console.log("[usePeer] Control channel closed");
10399
setControlChannel(null);
104100
};
105101

106-
channel.onerror = (error) => {
107-
console.error("Control channel error:", error);
108-
};
109-
110-
channel.onmessage = (event) => {
111-
console.log("Received message on control channel:", event.data);
112-
};
113-
114102
pc.ontrack = (event) => {
115-
if (event.track.kind === "video") {
103+
if (event.streams && event.streams[0]) {
116104
setRemoteStream(event.streams[0]);
117-
} else if (event.track.kind === "audio") {
118-
// If we already have a remote stream, add the audio track to it
119-
if (remoteStream) {
120-
remoteStream.addTrack(event.track);
121-
} else {
122-
// Otherwise create a new stream with the audio track
123-
setRemoteStream(new MediaStream([event.track]));
124-
}
125105
}
126106
};
127107

@@ -141,7 +121,7 @@ export function usePeer(props: PeerProps): Peer {
141121
await pc.setLocalDescription(offer);
142122
};
143123

144-
createOffer().catch(console.error);
124+
createOffer();
145125
} else {
146126
if (connectionStateTimeoutRef.current) {
147127
clearTimeout(connectionStateTimeoutRef.current);

0 commit comments

Comments
 (0)