Reputation: 1
The code is attached below. Audio working absolutely fine on screen sharing and when the video is on. But as I turn off the video, my audio stops going to my peers though I can hear them well. I dont know what's causing the issue. I have really tried a lot. Any help from senior developer will be much appreciated.
import { useEffect, useState } from "react";
import { cloneDeep } from "lodash";
import "./VideoCallComp.css";
import { useSocketContext } from "../../Context/SocketContext";
import usePlayer from "../../Hooks/usePlayer";
import VideoPlayerComp from "../../Components/VideoCall/VideoPlayerComp/VideoPlayerComp";
import CopySection from "../../Components/VideoCall/CopySection/CopySection";
import Bottom from "../../Components/VideoCall/Bottom/BottomVideoCall";
import usePeer from "../../Hooks/usePeer";
import useMediaStream from "../../Hooks/useMediaStream";
import { useLocation, useNavigate } from "react-router-dom";
import { Row, Col } from "antd";
import { Pin, PinOff, ScreenShare, ScreenShareOff } from "lucide-react";
import { CallTimer } from "../../Components/VideoCall/CallTimer/CallTimer";
import ScreenRecording from "../../Components/VideoCall/ScreenRecorder/ScreenRecorder";
import { isAuthenticated } from "../../Components/Auth/auth";
const VideoCallComp = () => {
const router = useNavigate();
const location = useLocation();
const socket = useSocketContext();
const [screenShare, setScreenShare] = useState(false);
const [pinnedUser, setPinnedUser] = useState("");
const [refreshPeer, setRefreshPeer] = useState(false);
const roomId = new URLSearchParams(location.search).get("roomID");
const { peer, myId } = usePeer(refreshPeer);
const { stream } = useMediaStream(screenShare);
const {
players,
setPlayers,
nonHighlightedPlayers,
toggleAudio,
toggleVideo,
leaveRoom
} = usePlayer(myId, roomId, peer);
const [users, setUsers] = useState([]);
console.log("video off stream", stream?.getTracks());
// Function to update all streams with the new stream
const updateAllStreams = (newStream) => {
if (!newStream || !peer || !myId) return;
Object.keys(users).forEach(userId => {
const call = users[userId];
if (call) {
call?.peerConnection?.getSenders()?.forEach(sender => {
if (sender.track.kind === 'video') {
sender.replaceTrack(newStream.getVideoTracks()[0]);
} else if (sender.track.kind === 'audio') {
sender.replaceTrack(newStream.getAudioTracks()[0]);
}
}); }
});
};
useEffect(() => {
if (!socket || !peer || !stream) return;
const handleUserConnected = (newUser) => {
console.log(`user connected in room with userId ${newUser}`);
callUser(newUser?.userId, stream, newUser?.loggedInUser);
};
const callUser = (userId, stream, loggedInUser) => {
const call = peer.call(userId, stream, loggedInUser);
call.on("stream", (incomingStream) => {
console.log("incomingStream", incomingStream)
setPlayers((prev) => ({
...prev,
[userId]: {
url: incomingStream,
loggedInUser,
muted: false,
playing: true,
},
}));
console.log("callObject", call);
setUsers((prev) => ({
...prev,
[userId]: call,
}));
});
};
socket.on("user-connected", handleUserConnected);
return () => {
socket.off("user-connected", handleUserConnected);
};
}, [peer, setPlayers, socket, stream, users]);
useEffect(() => {
if (!socket) return;
const handleToggleAudio = (userId) => {
console.log(`user with id ${userId} toggled audio`);
setPlayers((prev) => {
const copy = cloneDeep(prev);
copy[userId].muted = !copy[userId].muted;
return { ...copy };
});
};
const handleToggleVideo = (userId) => {
console.log(`user with id ${userId} toggled video`);
setPlayers((prev) => {
const copy = cloneDeep(prev);
copy[userId].playing = !copy[userId].playing;
// copy[userId].muted = false;
return { ...copy };
});
};
const handleUserLeave = (userId) => {
console.log(`user ${userId} is leaving the room`);
users[userId]?.close();
const playersCopy = cloneDeep(players);
delete playersCopy[userId];
setPlayers(playersCopy);
};
socket.on("user-toggle-audio", handleToggleAudio);
socket.on("user-toggle-video", handleToggleVideo);
socket.on("user-leave", handleUserLeave);
return () => {
socket.off("user-toggle-audio", handleToggleAudio);
socket.off("user-toggle-video", handleToggleVideo);
socket.off("user-leave", handleUserLeave);
};
}, [players, setPlayers, socket, users]);
// console.log("coming stream", stream);
useEffect(() => {
if (!peer || !stream) return;
peer.on("call", (call) => {
const { peer: callerId } = call;
call.answer(stream);
call.on("stream", (incomingStream) => {
console.log("incomingStream", incomingStream)
console.log(`incoming stream from ${callerId}`);
setPlayers((prev) => ({
...prev,
[callerId]: {
url: incomingStream,
muted: false,
playing: true,
},
}));
setUsers((prev) => ({
...prev,
[callerId]: call,
}));
});
});
}, [peer, setPlayers, stream]);
useEffect(() => {
if (!stream || !myId) return;
console.log(`setting my stream ${myId}`);
let loggedInUser = {
email: isAuthenticated()?.email,
fullName: isAuthenticated()?.fullName
}
setPlayers((prev) => ({
...prev,
[myId]: {
url: stream,
loggedInUser,
muted: false,
playing: true,
},
}));
updateAllStreams(stream); // Update streams for all peers in real-time
}, [myId, setPlayers, stream, screenShare]);
// Set the default pinned user
useEffect(() => {
if (!pinnedUser && Object.keys(nonHighlightedPlayers).length > 0) {
const firstNonHighlightedPlayerId = Object.keys(nonHighlightedPlayers)[0];
const firstNonHighlightedPlayer = {
playerId: firstNonHighlightedPlayerId,
...nonHighlightedPlayers[firstNonHighlightedPlayerId]
};
setPinnedUser(firstNonHighlightedPlayer);
}
}, [nonHighlightedPlayers, pinnedUser]);
const handleBeforeUnload = (event) => {
event.preventDefault();
// Included for legacy support, e.g. Chrome/Edge < 119
event.returnValue = true;
leaveRoom();
socket.disconnect();
};
const handleUnload = () => {
if (socket && roomId && myId) {
leaveRoom();
socket.disconnect();
document.location.reload();
}
};
useEffect(() => {
window.addEventListener("beforeunload", handleBeforeUnload);
window.addEventListener("unload", handleUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
window.removeEventListener("unload", handleUnload);
};
}, [socket, roomId, myId, players]);
const handleLeaveRoom = () => {
leaveRoom();
router("/");
setTimeout(() => {
document.location.reload();
}, 1200);
}
const handleToggleVideOnScreenShare = (val) => {
setScreenShare(val);
setTimeout(() => {
toggleVideo();
toggleVideo();
}, 1500);
}
return (
<div className="videoCallPage">
<CallTimer />
{
isAuthenticated()?.role === 1 &&
<ScreenRecording roomId={roomId} />
}
<Row className="videos mt-3">
<Col xs={24} md={24} className="inActivePlayerContainer">
{Object.keys(nonHighlightedPlayers).map((playerId, index) => {
const { url, muted, playing, loggedInUser } = nonHighlightedPlayers[playerId];
let makePinnedUser = nonHighlightedPlayers[playerId];
makePinnedUser.playerId = playerId;
return (
url?.active &&
<div key={index} className={pinnedUser?.playerId === playerId ? "VideoPlayerSection pinnedVideo" : "VideoPlayerSection otherVideos"}>
<div>
{pinnedUser?.playerId === playerId ? (
<PinOff className="text-white pinIcon" onClick={() => setPinnedUser("")} />
) : (
<Pin className="text-white pinIcon" onClick={() => setPinnedUser(makePinnedUser)} />
)}
<VideoPlayerComp
key={playerId}
url={url}
muted={playerId === myId || muted}
playing={playing}
toggleAudio={toggleAudio}
isActive={false}
/>
{
// myId === playerId &&
(
<Bottom
myId={myId}
playerId={playerId}
loggedInUser={loggedInUser}
muted={muted}
playing={playing}
toggleAudio={toggleAudio}
toggleVideo={toggleVideo}
leaveRoom={handleLeaveRoom}
/>
)}
</div>
</div>
);
})}
</Col>
</Row>
{
// isAuthenticated()?.role === 1 &&
<button className="screensharebtn btn">
{
screenShare ?
<ScreenShareOff onClick={() => { handleToggleVideOnScreenShare(false) }} />
:
<ScreenShare onClick={() => { handleToggleVideOnScreenShare(true) }} />
}
</button>
}
<CopySection roomId={roomId} />
</div>
);
};
export default VideoCallComp;
import { useState } from 'react'
import { cloneDeep } from 'lodash'
import { useSocketContext } from '../Context/SocketContext'
const usePlayer = (myId, roomId, peer, stream) => {
const socket = useSocketContext()
const [players, setPlayers] = useState({})
const playersCopy = cloneDeep(players);
const nonHighlightedPlayers = playersCopy
const leaveRoom = () => {
socket.emit('user-leave', myId, roomId)
console.log("leaving room", roomId)
peer?.disconnect();
}
const toggleAudio = () => {
console.log("I toggled my audio")
setPlayers((prev) => {
const copy = cloneDeep(prev)
copy[myId].muted = !copy[myId].muted
return { ...copy }
})
socket.emit('user-toggle-audio', myId, roomId);
}
const toggleVideo = () => {
console.log("I toggled my video")
setPlayers((prev) => {
const copy = cloneDeep(prev);
copy[myId].playing = !copy[myId].playing;
return { ...copy }
})
socket.emit('user-toggle-video', myId, roomId)
}
return { players, setPlayers, nonHighlightedPlayers, toggleAudio, toggleVideo, leaveRoom }
}
export default usePlayer;
import { useState, useEffect } from "react";
const useMediaStream = (screenShare) => {
const [stream, setStream] = useState(null);
useEffect(() => {
let mediaStream = null;
let audioStream = null;
const startStream = async () => {
try {
// Stop any active tracks if there's an existing stream
if (mediaStream) {
mediaStream.getTracks().forEach(track => track.stop());
}
if (audioStream) {
audioStream.getTracks().forEach(track => track.stop());
}
if (screenShare) {
mediaStream = await navigator.mediaDevices.getDisplayMedia({ video: true });
// Get the audio separately with additional constraints
audioStream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
}
});
// Combine the video and audio tracks
mediaStream.addTrack(audioStream.getAudioTracks()[0]);
} else {
mediaStream = await navigator.mediaDevices.getUserMedia({ video: true });
audioStream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
}
});
// Combine the video and audio tracks
mediaStream.addTrack(audioStream.getAudioTracks()[0]);
}
setStream(mediaStream);
} catch (error) {
console.error("Error accessing media devices.", error);
}
};
startStream();
return () => {
if (mediaStream) {
mediaStream.getTracks().forEach(track => track.stop());
}
if (audioStream) {
audioStream.getTracks().forEach(track => track.stop());
}
};
}, [screenShare]);
return { stream };
};
export default useMediaStream;
I have tried a lot of problems but did'nt find any solution
Upvotes: 0
Views: 43