'PeerJs and Socket IO signal not recived by the existing user
I am making and group call platform for my final year project. I used this code from GitHub and modified a little bit. Back end code is almost same.
I am facing an issue while joining. Whenever a new user join the room it's video is not visible to the existing user's but the new user is able to see the video of the existing user.
[Front-end]
layout.jsx
import React, { useEffect, useRef, useState } from 'react';
import { io } from "socket.io-client";
import ChatSection from '../components/ChatSection';
import { EndCall, FullVolumeIcon, MessageIcon, MicrophoneOffIcon, MicrophoneOnIcon, UsersIcon, VideoOffIcon, VideoOnIcon } from '../components/Icon';
import queryString from 'query-string';
import Peer from 'simple-peer';
import { SnackBar } from '../components/SnackBar';
import useSound from "use-sound";
const Video = (props) => {
const videoRef = useRef(null);
useEffect(() => {
props.peer.on("stream", stream => {
videoRef.current.srcObject = stream;
})
}, [])
return (
<video className="meeting_video_video" ref={videoRef} autoPlay playsInline />
)
}
export default function CenturyLayout() {
const [showUserLeftSnackbar, setShowUserLeftSnackbar] = useState({
open: false,
message: 'test message'
});
const [showSnackBar, setShowSnackBar] = useState({
open: false,
message: 'test message'
});
const [roomName, setRoomName] = useState('');
const [roomID, setRoomID] = useState('');
const [userName, setUserName] = useState('');
const [userSocketID, setUserSocketID] = useState('');
const [time, setTime] = useState(0);
const [isAudio, setIsAudio] = useState(true);
const [isVideo, setIsVideo] = useState(true);
const [showChat, setShowChat] = React.useState(false);
// variables for different functionalities of video call
const [peers, setPeers] = useState([]);
const socketRef = useRef();
const userVideo = useRef();
const peersRef = useRef([]);
const userStream = useRef();
const [message, setMessage] = useState([]);
const updateMessages = (message) => {
setMessage((prev) => [...prev, { ...message }]);
}
useEffect(() => {
const roomID = queryString.parse(window.location.search).room;
const userName = queryString.parse(window.location.search).user;
setRoomID(roomID);
setUserName(userName);
function formatAMPM(date) {
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0' + minutes : minutes;
var strTime = hours + ':' + minutes + ' ' + ampm;
return strTime;
}
setTime(formatAMPM(new Date()));
// const socket = io.connect("https://centaur-meet.herokuapp.com/");
const socket = io.connect("http://localhost:5000");
setUserSocketID(socket.id);
socketRef.current = socket;
socket.on("chat-message", data => {
alert(data.message);
updateMessages(data);
})
// asking for audio and video access
navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(stream => {
// streaming the audio and video
userVideo.current.srcObject = stream;
userStream.current = stream;
socket.emit("join room group", { roomID, userName });
// getting all user for the new user joining in
socket.on("all users", users => {
console.log("User currently in the room >>>", users);
const tempPeers = [];
// adding the new user to the group
users.forEach(user => {
console.log("🙂User ID >>>", user);
const peer = createPeer(user.id, socket.id, stream, socket, user.userName);
peersRef.current.push({
peerID: user.id,
peer,
})
tempPeers.push({
peerID: user.id,
peer,
});
})
setPeers(tempPeers);
})
// sending signal to existing user's after new user joined
socket.on("user joined", payload => {
console.log(">>>A new user joined ", { payload });
displaySnackBar(payload.userName + " joined the room");
const peer = addPeer(payload.signal, payload.callerID, stream, socket);
peersRef.current.push({
peerID: payload.callerID,
peer,
})
const peerObj = {
peer,
peerID: payload.callerID
}
setPeers((prev) => [...prev, peerObj]);
});
// existing users receiving the signal
socket.on("receiving returned signal", payload => {
console.log("Receiving returned signal ", payload.id);
const item = peersRef.current.find(p => p.peerID === payload.id);
console.log("item >>>", item);
item.peer.signal(payload.signal);
});
// handling user disconnecting
socket.on("user left", id => {
// finding the id of the peer who just left
const peerObj = peersRef.current.find(p => p.peerID === id);
if (peerObj) {
peerObj.peer.destroy();
displaySnackBar(`${id} left the room`);
}
// removing the peer from the arrays and storing remaining peers in new array
const peers = peersRef.current.filter(p => p.peerID !== id);
peersRef.current = peers;
setPeers(peers);
})
})
return () => {
socket.disconnect();
}
}, []);
const displaySnackBar = (message) => {
setShowSnackBar((prev) => {
return {
...prev,
open: true,
message: message
}
})
setTimeout(() => {
setShowSnackBar((prev) => {
return {
...prev,
open: false,
}
})
}, 3000);
}
// creating a peer object for newly joined user
function createPeer(userToSignal, callerID, stream, socket, userName) {
const peer = new Peer({
initiator: true,
trickle: false,
stream,
config: {
'iceServers': [{ 'urls': 'stun:stun.l.google.com:19302' }]
}
});
peer.on("signal", signal => {
console.log("🙂Sending signal to callerID >>>", callerID);
socket.emit("sending signal", { userToSignal, callerID, signal, userName })
})
return peer;
}
// adding the newly joined peer to the room
function addPeer(incomingSignal, callerID, stream, socket) {
const peer = new Peer({
initiator: false,
trickle: false,
stream: stream,
})
peer.on("signal", signal => {
console.log("Socket ID: ", socket.id);
console.log("🙂Sending signal to callerID >>>", callerID);
socket.emit("returning signal", { signal, callerID })
})
peer.signal(incomingSignal);
return peer;
}
// Toggle Video
function toggleVideo() {
setIsVideo(!isVideo);
userStream.current.getVideoTracks()[0].enabled = isVideo;
}
// Toggle Audio
function toggleAudio() {
setIsAudio(!isAudio);
userStream.current.getAudioTracks()[0].enabled = isAudio;
}
// Hanging up the call
function hangUp() {
userStream.current.getVideoTracks()[0].enabled = false;
// callEndSound();
window.location.replace("/");
}
// Chat functionality
function sendChat(message) {
const messageData = {
message,
userID: socketRef.current.id,
roomID
}
updateMessages(messageData);
socketRef.current.emit("message", messageData);
}
return (
<div className='meeting_lyt_wrapper'>
<ChatSection
sendMessage={sendChat}
userID={userSocketID}
messages={message}
showChat={showChat}
setShowChat={setShowChat} />
{
showSnackBar.open && <SnackBar msg={showSnackBar.message} />}
<div className='meeting_header_lyt'>
<img src='./svg/centaurLogo.svg' className='meeting_header_logo' width={50} alt='logo' />
<p className='meeting_header_time'>{time}</p>
<hr />
<p className='meeting_header_name'>{roomID}</p>
</div>
<div className='meeting_video_lyt'>
<ul className='meeting_video_lists'>
<li className='meeting_video_item'>
<video ref={userVideo} className="meeting_video_video" autoPlay playsInline muted />
</li>
{peers && peers.map((peer, index) => (
<li key={index} className='meeting_video_item'>
<Video stream={peer.peer} key={peer.peerID} peer={peer.peer} />
</li>
))}
</ul>
</div>
<div className='meeting_controls_lyt'>
<ul className='meeting_controls_list'>
<li className='meeting_control_item'>
<button className='meeting_control_button' onClick={() => console.log(peers)}>
<FullVolumeIcon color={'white'} />
</button>
</li>
<li className='meeting_control_item'>
<button className='meeting_control_button' onClick={toggleVideo}>
{
isVideo ? <VideoOnIcon color={'white'} /> : <VideoOffIcon color={'white'} />
}
</button>
</li>
<li className='meeting_control_item'>
<button className='meeting_control_button' onClick={toggleAudio}>
{
isAudio ?
<MicrophoneOnIcon color={'white'} />
:
<MicrophoneOffIcon color={'white'} />
}
</button>
</li>
<li className='meeting_control_item'>
<button className='meeting_control_button' onClick={hangUp}>
<EndCall color={'white'} />
</button>
</li>
<li className='meeting_control_item'>
<button className='meeting_control_button'>
<UsersIcon color={'white'} />
</button>
</li>
<li className='meeting_control_item'>
<button
onClick={() => setShowChat(!showChat)}
className='meeting_control_button'>
<MessageIcon color={'white'} />
</button>
</li>
</ul>
</div>
</div>
)
}
[Back-end]
server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
bodyParser.urlencoded({ extended: false });
app.use(bodyParser.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World!');
});
const server = require('http').createServer(app);
const socketio = require('socket.io');
const e = require('express');
const io = socketio(server, {
cors: {
origin: '*',
methods: ['GET', 'POST'],
allowedHeaders: ['Access-Control-Allow-Headers'],
}
});
const rooms = {};
const users = {};
const socketToRoom = {};
// when the user is forming a connection with socket.io
io.on("connection", socket => {
console.log("user connected");
// handling Group Video Call
socket.on("join room group", ({ roomID, userName }) => {
// getting the room with the room ID and adding the user to the room
if (users[roomID]) {
users[roomID].push({ id: socket.id, userName });
// socket.join(roomID);
} else {
users[roomID] = [{ id: socket.id, userName }];
}
// returning new room with all the attendees after new attendee joined
socketToRoom[socket.id] = roomID;
const usersInThisRoom = users[roomID].filter(id => id.id !== socket.id);
socket.emit("all users", usersInThisRoom);
});
// sending signal to existing members when user join
socket.on("sending signal", payload => {
const user = users[socketToRoom[socket.id]].find(user => user.id === payload.callerID);
console.log({ callerID: payload.callerID })
console.log({ socketID: socket.id })
io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID, userName: user.userName });
});
// signal recieved by the user who joined
socket.on("returning signal", payload => {
io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });
});
// Chat message
socket.on("message", payload => {
console.log("Chat message triggered", payload);
io.to(payload.roomID).emit('chat-message', { message: payload.message, userID: payload.userID });
});
// handling user disconnect in group call
socket.on('disconnect', () => {
console.log('user disconnected');
// getting the room array with all the participants
const roomID = socketToRoom[socket.id];
let room = users[roomID];
if (room) {
// finding the person who left the room
// creating a new array with the remaining people
room = room.filter(id => id.id !== socket.id);
users[roomID] = room;
}
// emiting a signal and sending it to everyone that a user left
socket.broadcast.emit('user left', socket.id);
});
});
const port = process.env.PORT || 5000;
server.listen(port, () => {
console.log('listening on port ', port);
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
