Reputation: 1
The problem is the user already in the room can access the other user's vid, but not vice versa. I guess this is signalling issue, and im not able to track it down. Please do help me here. Thanks in advance.
Signalling server:
const express = require("express");
const { createServer } = require("node:http");
const crypto = require("crypto");
const app = express();
const server = createServer(app);
const io = require("socket.io")(server, {
cors: {
origin: "*",
},
});
let rooms = {};
io.on("connection", (socket) => {
socket.emit("getId", { id: socket.id });
socket.on("getMeetLink", (data) => {
const roomId = crypto.randomUUID();
rooms[roomId] = [];
console.log(rooms);
io.to(data.id).emit("meetLink", { roomId });
});
socket.on("joinRoom", (data) => {
socket.join(data.roomId);
io.to(data.id).emit("onJoinRoom", {
message: "success",
});
socket.to(data.roomId).emit("someone-joining-room", {
signalData: data.signalData,
id: data.id,
});
});
socket.on("accept-peer", (data) => {
io.to(data.id).emit("acceptConnection", { signalData: data.signalData });
});
socket.on("sendMessage", (data) => {
socket.to(data.roomId).emit("incomingMessage", { message: data.message });
});
socket.on("disconnect", () => {
console.log("user disconnected");
});
});
server.listen(8000, () => {
console.log("Server running on port", 8000);
});
Client side code:
import React, { useRef, useEffect, useState } from "react";
import {
Box,
Button,
Card,
CardContent,
IconButton,
Input,
TextField,
} from "@mui/material";
import { MicOff, Mic, Videocam, VideocamOff } from "@mui/icons-material";
import io from "socket.io-client";
import Peer from "simple-peer";
// import {} from "@mui/";
const socket = io.connect("http://localhost:8000");
const HomePage = () => {
const [videoEnabled, setVideoEnabled] = useState(false);
const [audioEnabled, setAudioEnabled] = useState(false);
const [id, setId] = useState(null);
const [roomId, setRoomId] = useState("");
const [inRoom, setInRoom] = useState(false);
const [message, setMessage] = useState("");
const [myStream, setMyStream] = useState();
const videoRef = useRef(null);
const mediaStreams = useRef([]); // Store media streams for cleanup
const secondVideo = useRef(null);
const userVideo = useRef();
const connectionRef = useRef();
const incomingVids = [];
useEffect(() => {
socket.on("getId", (data) => {
setId(data.id);
console.log(data.id);
});
socket.on("incomingMessage", (data) => {
console.log(data);
});
socket.on("someone-joining-room", (data) => {
console.log("someOneJoing the room", data);
const peer = new Peer({
initiator: false,
trickle: false,
stream: myStream,
});
peer.on("signal", (signalData) => {
console.log("sending the signal data back.");
socket.emit("accept-peer", { signalData: signalData, id: data.id });
});
peer.on("stream", (stream) => {
console.log("someone stream", stream);
userVideo.current.srcObject = stream;
incomingVids.push({ stream, id: data.id });
console.log(incomingVids);
});
peer.signal(data.signalData);
connectionRef.current = peer;
});
}, []);
const getMeetLink = () => {
console.log("getting meet link");
socket.emit("getMeetLink", { id });
socket.on("meetLink", (data) => {
console.log(data);
setRoomId(data.roomId);
});
};
const handleInputChange = (event) => {
setRoomId(event.target.value);
};
const handleSetMessageChange = (event) => {
setMessage(event.target.value);
};
const hanndleJoinRoom = () => {
console.log({ roomId, id });
const peer = new Peer({
initiator: true,
trickle: true,
stream: myStream,
});
peer.on("signal", (data) => {
console.log("joining room", { roomId, id, signalData: data });
socket.emit("joinRoom", { roomId, id, signalData: data });
socket.on("onJoinRoom", (data) => {
// console.log(data);
if (data.message == "success") {
setInRoom(true);
}
});
});
socket.on("acceptConnection", (vals) => {
console.log("connection got accepted");
console.log("Data ", vals);
peer.signal(vals.signalData);
peer.on("stream", (stream) => {
console.log("i joined stream ", stream);
userVideo.current.srcObject = stream;
});
});
connectionRef.current = peer;
};
useEffect(() => {
// Cleanup function to stop media streams when the component unmounts
return () => {
mediaStreams.current.forEach((stream) => {
stream.getTracks().forEach((track) => track.stop());
});
};
}, [mediaStreams]);
const handleSendMessage = () => {
socket.emit("sendMessage", { roomId, message });
};
const handleVideoToggle = async () => {
if (!videoEnabled) {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
});
setVideoEnabled(true);
setMyStream(stream);
mediaStreams.current.push(stream);
videoRef.current.srcObject = stream;
videoRef.current.play();
} catch (error) {
console.error("Error accessing video:", error);
setVideoEnabled(false);
}
} else {
const videoStream = mediaStreams.current.find(
(stream) => stream.getVideoTracks().length > 0
);
if (videoStream) {
videoStream.getTracks().forEach((track) => track.stop());
videoRef.current.pause();
videoRef.current.srcObject = null;
mediaStreams.current = mediaStreams.current.filter(
(stream) => stream !== videoStream
);
setVideoEnabled(false);
}
}
};
const handleAudioToggle = async () => {
if (!audioEnabled) {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
setAudioEnabled(true);
mediaStreams.current.push(stream);
} catch (error) {
console.error("Error accessing audio:", error);
setAudioEnabled(false);
}
} else {
const audioStream = mediaStreams.current.find(
(stream) => stream.getAudioTracks().length > 0
);
if (audioStream) {
audioStream.getTracks().forEach((track) => track.stop());
mediaStreams.current = mediaStreams.current.filter(
(stream) => stream !== audioStream
);
setAudioEnabled(false);
}
}
};
// useEffect(() => {
// handleAudioToggle();
// handleAudioToggle();
// }, []);
return (
<div
style={{
display: "flex",
// flexDirection: "column",
alignItems: "center",
justifyContent: "center",
height: "100vh",
}}
>
<Card
style={{
display: "flex",
height: "70vh",
width: "90%",
// justifySelf: "center",
}}
elevation={10}
>
<div style={{ flexGrow: 2, margin: "20px" }}>
<div
style={{
display: "flex",
flexDirection: "column",
width: "100%",
height: "100%",
}}
>
<div style={{ display: "flex" }}>
<video
style={{
// zIndex: 0,
width: "calc(50% + 2px)",
transform: "scaleX(-1)",
height: "80%",
}}
playsInline
muted
ref={videoRef}
autoPlay
></video>
<video
style={{
// zIndex: 0,
width: "calc(50% + 2px)",
transform: "scaleX(-1)",
height: "80%",
}}
playsInline
muted
ref={userVideo}
autoPlay
></video>
</div>
<div
style={{
height: "20%",
// backgroundColor: "green",
display: "flex",
justifyContent: "center",
alignItems: "center",
justifyContent: "space-evenly",
}}
>
<div>
<IconButton onClick={handleVideoToggle}>
{videoEnabled ? <Videocam /> : <VideocamOff />}
</IconButton>
</div>
<div>
<IconButton onClick={handleAudioToggle}>
{audioEnabled ? <Mic /> : <MicOff />}
</IconButton>
</div>
</div>
</div>
</div>
<div style={{ margin: "20px" }}>
<Card
style={{ height: "100%", width: "100%", padding: "5px" }}
elevation={5}
>
<CardContent
style={{
display: "flex",
flexDirection: "column",
justifyContent: "space-evenly",
alignItems: "center",
margin: 0,
padding: 0,
height: "100%",
}}
>
{!inRoom && (
<>
<div style={{ display: "flex", flexDirection: "column" }}>
<TextField
id="filled-basic"
label="Email"
margin="0"
variant="filled"
/>
<TextField
id="filled-basic"
label="Room code"
margin="0"
variant="filled"
value={roomId}
onChange={handleInputChange}
/>
</div>
<Button
variant="contained"
style={{ width: "90%" }}
onClick={hanndleJoinRoom}
>
Join
</Button>
<Button
variant="contained"
style={{ width: "90%" }}
onClick={getMeetLink}
>
Create Room
</Button>
</>
)}
{inRoom && (
<>
<div>{roomId}</div>
<Input
value={message}
onChange={handleSetMessageChange}
></Input>
<Button
variant="contained"
style={{ width: "90%" }}
onClick={handleSendMessage}
>
Send Message
</Button>
</>
)}
</CardContent>
</Card>
</div>
</Card>
</div>
);
};
export default HomePage;
I tried to debug the signalling data exchange by logging the signal data.
console.log("connection got accepted");
console.log("Data ", vals);
this does log, but the next peer.on("stream") has no logs.
Upvotes: 0
Views: 98