Reputation: 1
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.
Upvotes: 0
Views: 121
Reputation: 864
I think you should check PeerJS documentation as well. in that, they have mentioned under the destroy like this
This cannot be undone; the respective peer object will no longer be able to create or receive any connections, its ID will be forfeited on the (cloud) server, and all of its data and media connections will be closed.
for more information check this PeerJS
Upvotes: 0