Pardon me for the beginner's question. I want to create a website for group video calls using webRTC, Peer, and Next.js. I use a signaling server using Node.js to be able to connect the peer. But for some reason, when I run it, I always get the error cannot signal after the peer is destroyed.
Any tip? Thanks
This is the file handle for my room where users can join.
'use client'
import React, { useEffect, useRef, useState } from "react";
import { useRouter } from 'next/navigation'; // Fix typo in import statement
import io from "socket.io-client";
import Peer from "simple-peer";
import styled from "styled-components";
const Container = styled.div`
padding: 20px;
display: flex;
height: 100vh;
width: 90%;
margin: auto;
flex-wrap: wrap;
`;
const StyledVideo = styled.video`
height: 40%;
width: 50%;
`;
const Video = (props) => {
const ref = useRef();
useEffect(() => {
props.peer.on("stream", stream => {
ref.current.srcObject = stream;
});
}, [props.peer]);
return (
<StyledVideo playsInline autoPlay ref={ref} />
);
}
const Room = () => {
const router = useRouter();
const [peers, setPeers] = useState([]);
const socketRef = useRef();
const userVideo = useRef();
const peersRef = useRef([]);
const id = router.query; // Use router.query to get the room ID
const roomID = 123
useEffect(() => {
console.log(id)
const videoConstraints = {
height: window.innerHeight / 4,
width: window.innerWidth / 4
};
socketRef.current = io.connect("http://localhost:8000");
navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: true }).then(stream => {
userVideo.current.srcObject = stream;
socketRef.current.emit("join room", roomID);
socketRef.current.on("all users", users => {
const peers = [];
users.forEach(userID => {
if (userID !== socketRef.current.id) {
const peer = createPeer(userID, socketRef.current.id, stream);
peersRef.current.push({
peerID: userID,
peer,
});
peers.push(peer);
}
});
setPeers(peers);
});
socketRef.current.on("user joined", payload => {
const peer = addPeer(payload.signal, payload.callerID, stream);
peersRef.current.push({
peerID: payload.callerID,
peer,
});
setPeers(users => [...users, peer]);
});
socketRef.current.on("receiving returned signal", payload => {
const item = peersRef.current.find(p => p.peerID === payload.id);
if (item) {
item.peer.signal(payload.signal);
}
});
});
}, [roomID]);
function createPeer(userToSignal, callerID, stream) {
const peer = new Peer({
initiator: true,
trickle: false,
stream,
});
peer.on("signal", signal => {
socketRef.current.emit("sending signal", { userToSignal, callerID, signal });
});
return peer;
}
function addPeer(incomingSignal, callerID, stream) {
const peer = new Peer({
initiator: false,
trickle: false,
stream,
});
peer.on("signal", signal => {
socketRef.current.emit("returning signal", { signal, callerID });
});
peer.signal(incomingSignal);
return peer;
}
return (
<div className="bg-gray-100 min-h-screen flex flex-col">
<h1 className="text-2xl font-semibold p-4">Video Chat Room</h1>
<div className="video-container p-4 flex-1">
{userVideo && <StyledVideo muted ref={userVideo} autoPlay playsInline />}
{peers.map((peer, index) => (
<Video key={index} peer={peer} />
))}
</div>
{/* Chat bar */}
<div className="bg-white p-4 border-t border-gray-300">
<div className="chat-messages"></div>
<div className="flex mt-2">
<input
type="text"
placeholder="Type a message..."
className="p-2 border border-gray-300 rounded-lg flex-1"
/>
<button
className="ml-2 bg-blue-500 text-white px-4 py-2 rounded-lg"
>
Send
</button>
</div>
</div>
<div className="p-4">
<button
className="bg-blue-500 text-white px-4 py-2 rounded-lg"
>
</button>
<button
className="ml-2 bg-blue-500 text-white px-4 py-2 rounded-lg"
>
</button>
</div>
</div>
);
};
export default Room;
Here is my signaling server
require('dotenv').config();
const express = require("express");
const http = require("http");
const app = express();
const cors = require("cors");
app.use(cors)
const server = http.createServer(app);
const socket = require("socket.io");
const io = socket(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
const users = {};
const socketToRoom = {};
io.on('connection', socket => {
socket.on("join room", roomID => {
if (users[roomID]) {
const length = users[roomID].length;
if (length === 4) {
socket.emit("room full");
return;
}
users[roomID].push(socket.id);
} else {
users[roomID] = [socket.id];
}
socketToRoom[socket.id] = roomID;
const usersInThisRoom = users[roomID].filter(id => id !== socket.id);
socket.emit("all users", usersInThisRoom);
});
socket.on("sending signal", payload => {
io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID });
});
socket.on("returning signal", payload => {
io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });
});
socket.on('disconnect', () => {
const roomID = socketToRoom[socket.id];
let room = users[roomID];
if (room) {
room = room.filter(id => id !== socket.id);
users[roomID] = room;
}
});
});
server.listen(process.env.PORT || 8000, () => console.log('server is running on port 8000'));
I hope you can identify what my problem is in the code. I would appreciate your assistance in identifying and resolving the issue. Thank you.
I think you should check PeerJS documentation as well. in that, they have mentioned under the destroy like this
for more information check this PeerJS