WebRTC Video Conference Change the quality of video NodeJS - javascript

I am trying to create a video conference app using the tutorial https://youtu.be/DvlyzDZDEq4 . I want to add one feature to change the quality of video( not the resolution of the video ) user can see like we have in YouTube videos auto, high picture quality etc. I am very new to WebRTC and Peer library so any help is appreciated. Thank you.
script.js
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/',
port: '3001'
})
const myVideo = document.createElement('video')
myVideo.muted = true
const peers = {}
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
addVideoStream(myVideo, stream)
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
room.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script>
const ROOM_ID = "<%= roomId %>"
</script>
<script defer src="https://unpkg.com/peerjs#1.2.0/dist/peerjs.min.js"></script>
<script src="/socket.io/socket.io.js" defer></script>
<script src="script.js" defer></script>
</head>
<body>
<div id="video-grid"></div>
</body>
</html>
server.js
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.to(roomId).broadcast.emit('user-connected', userId)
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId)
})
})
})
server.listen(3000)
Updated Script.js
const socket = io('/zoom')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/',
port: '3002'
})
let pc;
const myVideo = document.createElement('video')
myVideo.muted = true
const peers = {}
let myVideoStream;
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
myVideoStream = stream;
addVideoStream(myVideo, stream,user)
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream,user)
})
})
socket.on("user-connected", (userId, username) =>
{ console.log("checking "+ username);
setTimeout(function ()
{ connectToNewUser(userId, stream);
console.log("zoooom "+ username);
}, 1000);
});
let text = $("input");
// when press enter send message
$('html').keydown(function (e) {
if (e.which == 13 && text.val().length !== 0) {
socket.emit('message', text.val());
text.val('')
}
});
socket.on("createMessage", (message, username) => {
//$("ul").append(`<li class="message"><b>${username}</b><br/>${message}</li>`);
scrollToBottom()
})
})
socket.on('user-disconnected', (userId, username) => {
$("ul").append(`<span class="messageHeader"><small>${username} Left Meeting</small></span>`);
if (peers[userId]) peers[userId].close()
})
const offerOptions = {
offerToReceiveAudio: 0,
offerToReceiveVideo: 1
};
myPeer.on('open', id => {
const servers = null;
pc1 = new RTCPeerConnection(servers);
pc1.createOffer({
offerToReceiveAudio: 0,
offerToReceiveVideo: 1
})
.then((desc)=>{const videobitrate = 20000;
return pc1.setLocalDescription(desc);
/* let offer = pc1.localDescription;
console.log("offer "+pc1.localDescription);
// Set bandwidth for video
offer.sdp = offer.sdp.replace(/(m=video.*\r\n)/g, `$1b=AS:125\r\n`);
pc1.setLocalDescription(offer);*/}).then(()=>{
let offer = pc1.localDescription;
console.log("offer "+pc1.localDescription);
// Set bandwidth for video
offer.sdp = offer.sdp.replace(/(m=video.*\r\n)/g, `$1b=AS:20000\r\n`);
return pc1.setLocalDescription(offer);
}).then(()=>{console.log(pc1.localDescription.sdp)})
.catch((err)=>{ console.log('Failed to set session description: ' + err);});
console.log("user mypeer"+user);
socket.emit('join-room', ROOM_ID,id,user);
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const servers = null;
pc2 = new RTCPeerConnection(servers);
pc2.createOffer({
offerToReceiveAudio: 0,
offerToReceiveVideo: 1
})
.then((desc)=>{const videobitrate = 20000;
return pc2.setLocalDescription(desc);
/* let offer = pc1.localDescription;
console.log("offer "+pc1.localDescription);
// Set bandwidth for video
offer.sdp = offer.sdp.replace(/(m=video.*\r\n)/g, `$1b=AS:125\r\n`);
pc1.setLocalDescription(offer);*/}).then(()=>{
let offer = pc2.localDescription;
console.log("offer "+pc2.localDescription);
// Set bandwidth for video
offer.sdp = offer.sdp.replace(/(m=video.*\r\n)/g, `$1b=AS:20000\r\n`);
return pc2.setLocalDescription(offer);
}).then(()=>{console.log(pc2.localDescription.sdp)})
.catch((err)=>{ console.log('Failed to set session description: ' + err);});
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream,user)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream,username) {
video.srcObject = stream
console.log("adding video")
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
video.insertAdjacentHTML('beforebegin',`<b style="color:white">${username}</b>`);
}
const scrollToBottom = () => {
var d = $('.main__chat_window');
d.scrollTop(d.prop("scrollHeight"));
}
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
setUnmuteButton();
} else {
setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
}
const playStop = () => {
console.log('object')
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
setPlayVideo()
} else {
setStopVideo()
myVideoStream.getVideoTracks()[0].enabled = true;
}
}
const setMuteButton = () => {
const html = `
<i class="fas fa-microphone"></i>
<span>Mute</span>
`
document.querySelector('.main__mute_button').innerHTML = html;
}
const setUnmuteButton = () => {
const html = `
<i class="unmute fas fa-microphone-slash"></i>
<span>Unmute</span>
`
document.querySelector('.main__mute_button').innerHTML = html;
}
const setStopVideo = () => {
const html = `
<i class="fas fa-video"></i>
<span>Stop Video</span>
`
document.querySelector('.main__video_button').innerHTML = html;
}
const setPlayVideo = () => {
const html = `
<i class="stop fas fa-video-slash"></i>
<span>Play Video</span>
`
document.querySelector('.main__video_button').innerHTML = html;
}

Related

WebRtc works on Firefox but not on Chrome after changing signaling

I basicly Implemented a simple webrtc application where a client streams a video and then another client can connect and access the remote stream from each other.
The first implementation I did was with AgoraRTM signaling and it worked well in all browsers. After that I wanted to try to move to websockets as the signaling part.
When I finished moving to websockets, I noticed that it kept working at Firefox, but at Chrome and Edge (probably chromium browsers) the remoteStream doesn't show up (it shows up the first and second time, but stops working if I disconnect and connect a new client)
Here is my code:
main.js (frontend logic, webrtc)
let token = null;
let uid = String(Math.floor(Math.random() * 10000));
let queryString = window.location.search;
const urlSearch = new URLSearchParams(queryString);
const room = urlSearch.get("room");
if (!room) {
window.location = "lobby.html";
}
let client;
let channel;
let socket;
const constraints = {
video: {
width: { min: 640, ideal: 1920, max: 1920 },
height: { min: 480, ideal: 1080, max: 1920 },
aspectRatio: 1.777777778,
},
audio: false,
};
const servers = {
iceServers: [
{
urls: [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302",
"stun:stun3.l.google.com:19302",
"stun:stun4.l.google.com:19302",
],
},
],
};
const localVideoRef = document.getElementById("localVideo");
const remoteVideoRef = document.getElementById("remoteVideo");
let localStream;
let remoteStream;
let peerConnection;
const configureSignaling = async () => {
socket = await io.connect("http://localhost:4000");
socket.emit("join", { room, uid });
socket.on("MemberJoined", handleMemberJoined);
socket.on("MessageFromPeer", handleMessageFromPeer);
socket.on("MemberLeft", handleMemberLeft)
};
const handleMemberLeft = async () => {
remoteVideoRef.style.display = "none";
};
const handleMessageFromPeer = (m, uid) => {
const message = JSON.parse(m.text);
if(message.type !== "candidate") {
console.log('handleMessageFromPeer: ', message, uid)
}
if (message.type === "offer") {
createAnswer(uid, message.offer);
}
if (message.type === "answer") {
addAnswer(message.answer);
}
if (message.type === "candidate") {
if (peerConnection && peerConnection.currentRemoteDescription) {
peerConnection.addIceCandidate(message.candidate);
}
}
};
const createLocalStream = async () => {
localStream = await navigator.mediaDevices.getUserMedia(constraints);
localVideoRef.srcObject = localStream;
localVideoRef.play()
remoteVideoRef.play()
};
const init = async () => {
await configureSignaling();
await createLocalStream();
};
const handleMemberJoined = async (uid) => {
createOffer(uid);
};
let createOffer = async (uid) => {
await createPeerConnection(uid);
let offer = await peerConnection.createOffer();
console.log({ offer })
await peerConnection.setLocalDescription(offer);
console.log('localStream: ', offer)
socket.emit(
"sendMessageToPeer",
{ text: JSON.stringify({ type: "offer", offer: offer }) },
uid
);
};
let createPeerConnection = async (uid) => {
peerConnection = new RTCPeerConnection(servers);
remoteStream = new MediaStream();
remoteVideoRef.srcObject = remoteStream;
remoteVideoRef.style.display = "block";
remoteVideoRef.classList.add("remoteFrame");
if (!localStream) {
await createLocalStream();
}
localStream.getTracks().forEach((track) => {
peerConnection.addTrack(track, localStream);
});
peerConnection.ontrack = (event) => {
event.streams[0].getTracks().forEach((track) => {
remoteStream.addTrack(track);
});
};
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
socket.emit(
"sendMessageToPeer",
{
text: JSON.stringify({
type: "candidate",
candidate: event.candidate,
}),
},
uid
);
}
};
};
let createAnswer = async (uid, offer) => {
await createPeerConnection(uid);
await peerConnection.setRemoteDescription(offer);
console.log('remoteStream: ', offer)
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);
console.log('localStream: ', answer)
socket.emit(
"sendMessageToPeer",
{ text: JSON.stringify({ type: "answer", answer: answer }) },
uid
);
};
let addAnswer = async (answer) => {
if (!peerConnection.currentRemoteDescription) {
peerConnection.setRemoteDescription(answer);
}
console.log(peerConnection)
};
let onLogout = async () => {
peerConnection.close()
remoteVideoRef.classList.remove("remoteFrame");
await socket.emit('onLeaveRoom', room)
};
let onToggleCamera = async () => {
const videoTrack = localStream
.getTracks()
.find((track) => track.kind === "video");
if (videoTrack.enabled) {
videoTrack.enabled = false;
document.getElementById("camera-btn").style.backgroundColor =
"rgb(255, 80, 80)";
} else {
videoTrack.enabled = true;
document.getElementById("camera-btn").style.backgroundColor =
"rgb(179, 102, 249, .9)";
}
};
let onToggleMic = async () => {
const audioTrack = localStream
.getTracks()
.find((track) => track.kind === "audio");
if (audioTrack.enabled) {
audioTrack.enabled = false;
document.getElementById("mic-btn").style.backgroundColor =
"rgb(255, 80, 80)";
} else {
audioTrack.enabled = true;
document.getElementById("mic-btn").style.backgroundColor =
"rgb(179, 102, 249, .9)";
}
};
window.addEventListener("beforeunload", onLogout);
init();
index.js (server logic, websockets)
const express = require("express");
const app = express();
const PORT = 4000;
const http = require("http").Server(app);
const cors = require("cors");
const users = []
app.use(cors());
const socketIO = require("socket.io")(http, {
cors: {
origin: "http://127.0.0.1:5501",
},
});
//Add this before the app.get() block
socketIO.on("connection", (socket) => {
socket.on('join', async ({room, uid}) => {
users.push(uid)
await socket.join(room);
socket.broadcast.to(room).emit('MemberJoined', uid)
})
socket.on("onLeaveRoom", async (room) => {
socket.broadcast.to(room).emit('MemberLeft')
})
socket.on("disconnect", async (room) => {
socket.broadcast.to(room).emit('MemberLeft')
})
socket.on('sendMessageToPeer', (data, uid) => {
socket.broadcast.emit('MessageFromPeer', data, uid )
});
});
app.get("/api", (req, res) => {
res.json({
message: "Hello world",
});
});
http.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
I tried a couple of things like:
Checking if the offer and the answer was sended correctly, just 1 time and with the correct SDP
Checked if there was a problem disconnecting from a socket that leads to have more clients in a room
Tried also to add localVideoRef.play() to check if there is an issue with the autoplay for chrome, since there was a similar thread at stackoverflow (Ended up not working)

Send message to iframe inside of a promise

I have this promise? How can I postMessage to an iframe from then. Currently i have function with timer that sends info on page load but i want to get more info.
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
path: '/peerjs',
host: '/',
port: '3000'
})
const peers = {}
let myVideoStream;
const myVideo = document.createElement('video')
myVideo.muted = true;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function brodcastStatus(postMsg) {
for (let i = 0; i < 10; i++) {
parent.postMessage(postMsg, "*");
console.log(postMsg)
await sleep(1500)
}
}
if (KIND === 'server'){
Promise.resolve(navigator.mediaDevices.getUserMedia({
video: {
width: 1920,
height: 1080,
aspectRatio: { ideal: 1.7777777778 },
frameRate: { max: 24, }
},
audio: true
})).then(stream => {
brodcastStatus("server | camera | mic")
myVideoStream = stream;
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
}).catch(() => {
Promise.resolve(navigator.mediaDevices.getUserMedia({
video: {
width: 1920,
height: 1080,
aspectRatio: { ideal: 1.7777777778 },
frameRate: { max: 24, }
},
audio: false
})).then(stream => {
brodcastStatus("server | camera | no mic")
myVideoStream = stream;
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
}).catch(() => {
console.log("nocamera or microphone")
})
})
}else if (KIND === 'client'){
Promise.resolve(navigator.mediaDevices.getUserMedia({
video: false,
audio: true
})).then(stream => {
brodcastStatus("client | no camera | mic")
myVideoStream = stream;
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
}).catch(() => {
console.log("Client")
newStream = new MediaStream();
stream = newStream;
myVideoStream = stream;
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
})
}
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.setAttribute("style", "object-fit:cover; background: transparent url(/images/New_DACL_Logo.png) no-repeat center center; background-size: auto; overflow: hidden;")
video.addEventListener('loadedmetadata', () => {
})
videoGrid.append(video)
}
More context
this app send audio/video to user via webrtc. I using this webpage as an iframe in other application (flask) and i want to get some data about current connected user to lock/unlock other options

Joining random room by peerjs socketio

I am making chatroulette website. right now whenever i will send link other user can connect to my call, but i want it to work as follow:
Whenever user will click button it will find random user and join it to that room.
How can i implement this feature in socketio and peerjs libraries.
server.js
if (process.env.NODE_ENV !== "production") {
require('dotenv').config();
}
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const {v4:uuidV4} = require('uuid');
const {MongoClient} = require('mongodb');
const client = new MongoClient(process.env["DB_URL"], {
useUnifiedTopology: true
});
app.set('view engine', 'ejs');
app.use(express.static('public'));
// app.get('/', (req, res)=>{
// res.render("landing")
// });
app.get('/', (req, res)=>{
res.render('landing');
});
app.get('/chat', (req, res)=>{
res.redirect(`/${uuidV4()}`)
});
app.get('/:room', (req, res)=>{
res.render('room', {roomId: req.params.room});
});
io.on('connection', socket => {
let room = '';
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.to(roomId).broadcast.emit('user-connected', userId)
socket.on('message', message =>{
io.to(roomId).emit('createMessage', message);
});
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId)
})
})
})
const port = process.env.port || 3000;
server.listen(port, ()=> {
console.log("3000")
});
script.js
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/',
port: '3001'
})
let myVideoStream;
const myVideo = document.createElement('video')
myVideo.muted = true
const peers = {};
navigator.mediaDevices.getUserMedia({
video: true,
audio: false
}).then(stream => {
myVideoStream = stream;
addVideoStream(myVideo, stream)
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
})
let text = $('input');
$('html').keydown((e)=>{
if(e.which == 13 && text.val().length !== 0){
console.log(text.val());
socket.emit('message', text.val());
text.val('')
}
});
socket.on('createMessage', message =>{
$('ul').append(`<li class="message"><b>user</b><br/>${message}</li>`);
scrollToBottom();
});
});
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
const scrollToBottom = () => {
let d = $('.main__chat_window');
d.scrollTop(d.prop("scrollHeight"));
}
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
setUnmuteButton();
} else {
setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
}
const playStop = () => {
console.log('object')
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
setPlayVideo()
} else {
setStopVideo()
myVideoStream.getVideoTracks()[0].enabled = true;
}
}
const setMuteButton = () => {
const html = `
<i class="fas fa-microphone"></i>
<span>Mute</span>
`
document.querySelector('.main__mute_button').innerHTML = html;
}
const setUnmuteButton = () => {
const html = `
<i class="unmute fas fa-microphone-slash"></i>
<span>Unmute</span>
`
document.querySelector('.main__mute_button').innerHTML = html;
}
const setStopVideo = () => {
const html = `
<i class="fas fa-video"></i>
<span>Stop Video</span>
`
document.querySelector('.main__video_button').innerHTML = html;
}
const setPlayVideo = () => {
const html = `
<i class="stop fas fa-video-slash"></i>
<span>Play Video</span>
`
document.querySelector('.main__video_button').innerHTML = html;
}
You Have to Save All PeerJS Id in Array & then Choose a random Id and Send it to the Client. And If Any User Disconnects remove the ID From the Array.
server.js
if (process.env.NODE_ENV !== "production") {
require('dotenv').config();
}
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const {v4:uuidV4} = require('uuid');
const {MongoClient} = require('mongodb');
const client = new MongoClient(process.env["DB_URL"], {
useUnifiedTopology: true
});
app.set('view engine', 'ejs');
app.use(express.static('public'));
// app.get('/', (req, res)=>{
// res.render("landing")
// });
app.get('/', (req, res)=>{
res.render('landing');
});
app.get('/chat', (req, res)=>{
res.redirect(`/${uuidV4()}`)
});
app.get('/:room', (req, res)=>{
res.render('room', {roomId: req.params.room});
});
let Ids = []; // Creating Ids Array
io.on('connection', socket => {
let room = '';
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
Ids.push(userId); // Push Id in Ids Array when User Join
socket.to(roomId).broadcast.emit('user-connected', userId)
socket.on('message', message =>{
io.to(roomId).emit('createMessage', message);
});
socket.on('getId',() =>{
id = Ids[Math.floor(Math.random() * Ids.length)]; // Taking a Random Id
io.to(roomId).emit('recieveId', {id:id,userId:userId}); //Sending The Id with The UserId
});
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId)
const index = Ids.indexOf(userId);
if (index > -1) {
Ids.splice(index, 1);
} // removing Id From Ids Array When User Disconnect
})
})
})
//arr[Math.floor(Math.random() * arr.length)];
const port = process.env.port || 3000;
server.listen(port, ()=> {
console.log("3000")
});
script.js
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/',
port: '3001'
})
let myVideoStream;
const myVideo = document.createElement('video')
myVideo.muted = true
const peers = {};
navigator.mediaDevices.getUserMedia({
video: true,
audio: false
}).then(stream => {
myVideoStream = stream;
addVideoStream(myVideo, stream)
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => {
connectToNewUser(userId, stream)
socket.emit('getId'); //sending GetId Event
})
let text = $('input');
$('html').keydown((e)=>{
if(e.which == 13 && text.val().length !== 0){
console.log(text.val());
socket.emit('message', text.val());
text.val('')
}
});
socket.on('createMessage', message =>{
$('ul').append(`<li class="message"><b>user</b><br/>${message}</li>`);
scrollToBottom();
});
});
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
socket.on('reciveId', data => {
if data['userId'] == id{
connectToNewUser(data['id'],stream) // send Your Stream Here
}
}); // Recieving Recive Id Event
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
const scrollToBottom = () => {
let d = $('.main__chat_window');
d.scrollTop(d.prop("scrollHeight"));
}
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
setUnmuteButton();
} else {
setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
}
const playStop = () => {
console.log('object')
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
setPlayVideo()
} else {
setStopVideo()
myVideoStream.getVideoTracks()[0].enabled = true;
}
}
const setMuteButton = () => {
const html = `
<i class="fas fa-microphone"></i>
<span>Mute</span>
`
document.querySelector('.main__mute_button').innerHTML = html;
}
const setUnmuteButton = () => {
const html = `
<i class="unmute fas fa-microphone-slash"></i>
<span>Unmute</span>
`
document.querySelector('.main__mute_button').innerHTML = html;
}
const setStopVideo = () => {
const html = `
<i class="fas fa-video"></i>
<span>Stop Video</span>
`
document.querySelector('.main__video_button').innerHTML = html;
}
const setPlayVideo = () => {
const html = `
<i class="stop fas fa-video-slash"></i>
<span>Play Video</span>
`
document.querySelector('.main__video_button').innerHTML = html;
}
Note: Please Follow The Comments in The Code

WebRTC doesn't show the video peerConnection remote video

I have tried to connect my video (No webcam) to sync with the other video remotely. But I don't know where I'm wrong. I did it taking into account that they were going to connect to the same room. One performs the stream (LocalVideo) and the other sees what the other does (Remote). Something very similar to this: https://webrtc.github.io/samples/src/content/capture/video-pc/. But I still haven't given an answer for the problem, PLEASE if someone who knows about node.js and WebRTC can rescue me!
main.js:
let divSelectRoom = document.getElementById("selectRoom")
let divConsultingRoom = document.getElementById("consultingRoom")
let divConsultingRoom2 = document.getElementById("consultingRoom2")
let inputRoomNumber = document.getElementById("roomNumber")
let btnGoRoom = document.getElementById("goRoom")
let localVideo = document.getElementById("localVideo")
let remoteVideo = document.getElementById("remoteVideo")
let locallabel = document.getElementById("locallabel")
let visitlabel = document.getElementById("visitlabel")
let roomNumber, localStream, remoteStream, rtcPeerConnection, isCaller
let stream;
const iceServers = {
'iceServer': [
{ 'urls': 'stun:stun.services.mozilla.com' },
{ 'urls': 'stun:stun.l.google.com:19302' }
]
}
const streamConstraints = {
audio: 1,
video: 1
}
let startTime;
const socket = io();
btnGoRoom.onclick = () => {
if (inputRoomNumber.value == '') {
alert("please type a room name")
} else {
roomNumber = inputRoomNumber.value
socket.emit('create or join', roomNumber)
divSelectRoom.style = "display: none"
}
}
function maybeCreateStream() {
if (stream) {
return;
}
if (localVideo.captureStream) {
stream = localVideo.captureStream();
console.log('Captured stream from localVideo with captureStream',
stream);
} else if (localVideo.mozCaptureStream) {
stream = localVideo.mozCaptureStream();
console.log('Captured stream from localVideo with mozCaptureStream()',
stream);
} else {
console.log('captureStream() not supported');
}
localStream = stream
}
localVideo.play();
socket.on('created', room => {
divConsultingRoom.style = "display: block"
// Video tag capture must be set up after video tracks are enumerated.
localVideo.oncanplay = maybeCreateStream;
if (localVideo.readyState >= 3) { // HAVE_FUTURE_DATA
// Video is already ready to play, call maybeCreateStream in case oncanplay
// fired before we registered the event handler.
maybeCreateStream();
}
isCaller = true
})
socket.on('joined', room => {
divConsultingRoom2.style = "display: block"
remoteVideo.srcObject = localStream;
isCaller = false
socket.emit('ready', roomNumber)
})
socket.on('ready', () => {
console.log('enter ready')
const videoTracks = stream.getVideoTracks();
const audioTracks = stream.getAudioTracks();
if (videoTracks.length > 0) {
console.log(`Using video device: ${videoTracks[0].label}`);
}
if (audioTracks.length > 0) {
console.log(`Using audio device: ${audioTracks[0].label}`);
}
if (isCaller) {
rtcPeerConnection = new RTCPeerConnection(iceServers)
rtcPeerConnection.onicecandidate = onIceCandidate
rtcPeerConnection.ontrack = onAddStream
rtcPeerConnection.addTrack(localStream.getTracks()[0], localStream)
rtcPeerConnection.addTrack(localStream.getTracks()[1], localStream)
rtcPeerConnection.createOffer()
.then(sessionDescription => {
console.log('sending offer', sessionDescription)
rtcPeerConnection.setLocalDescription(sessionDescription)
socket.emit('offer', {
type: 'offer',
sdp: sessionDescription,
room: roomNumber
})
}).catch(err => {
console.log(err)
})
}
})
socket.on('offer', (event) => {
console.log('enter offer', isCaller)
if (!isCaller) {
rtcPeerConnection = new RTCPeerConnection(iceServers)
rtcPeerConnection.onicecandidate = onIceCandidate
rtcPeerConnection.ontrack = onAddStream
//rtcPeerConnection.addTrack(localStream.getTracks()[0], localStream)
//rtcPeerConnection.addTrack(localStream.getTracks()[1], localStream)
console.log('received offer', event)
rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(event))
rtcPeerConnection.createAnswer().then(sessionDescription => {
console.log('sending answer', sessionDescription)
socket.emit('answer', {
type: 'answer',
sdp: sessionDescription,
room: roomNumber
})
}).catch(err => {
console.log(err)
})
}
})
socket.on('answer', event => {
console.log('received answer', event)
rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(event))
})
socket.on('candidate', event => {
const candidate = new RTCIceCandidate({
sdpMLineIndex: event.label,
candidate: event.candidate
})
console.log('received candidate', candidate)
rtcPeerConnection.addIceCandidate(candidate)
})
function onAddStream(event) {
console.log('Stream It')
remoteVideo.srcObject = event.streams[0];
remoteStream = event.streams[0]
console.log('visit received remote stream', event.streams[0]);
}
function onIceCandidate(event) {
if (event.candidate) {
console.log('sending ice candidate', event.candidate)
socket.emit('candidate', {
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate,
room: roomNumber
})
}
}
app.js:
const { Socket } = require('dgram')
const express = require('express')
const app = express()
let http = require('http').Server(app)
const port = process.env.PORT || 3000
let io = require('socket.io')(http)
app.use(express.static('public'))
http.listen(port, () => {
console.log('listening on', port)
})
io.on('connection', socket => {
console.log('a user connected')
socket.on('create or join', room => {
console.log('create or join to room', room)
const myRoom = io.sockets.adapter.rooms[room] || {length: 0}
const numClients = myRoom.length
console.log(room, 'has',numClients,'clients')
if(numClients == 0){
socket.join(room)
socket.emit('created', room)
}else if (numClients == 1){
socket.join(room)
socket.emit('joined', room)
}else{
socket.emit('full', room)
}
})
socket.on('ready', room => {
socket.broadcast.to(room).emit('ready')
})
socket.on('candidate', event => {
socket.broadcast.to(event.room).emit('candidate', event)
})
socket.on('offer', event => {
socket.broadcast.to(event.room).emit('offer', event.sdp)
})
socket.on('answer', event => {
socket.broadcast.to(event.room).emit('answer', event.sdp)
})
})
index.html:
<!DOCTYPE html>
<head>
<title>WebRTC Training</title>
</head>
<body>
<h1>WebRTC TRAINING</h1>
<div id="selectRoom">
<label>Type room name</label>
<input id="roomNumber" type="text"/>
<button id="goRoom">Go</button>
</div>
<div id="consultingRoom" style="display: none;">
<video id="localVideo" playsinline controls loop muted>
<source src="videos/dudu.webm" type="video/webm"/>
<source src="videos/dudu.mp4" type="video/mp4"/>
<p>This browser does not support the video element.</p>
</video>
<label id="locallabel">local</label>
</div>
<div id="consultingRoom2" style="display: none;">
<video id="remoteVideo" playsinline autoplay></video>
<label id="visitlabel">visit</label>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="main.js"></script>
</body>
This is a picture so you can understand it better.

PeerJs Issue On locahost

I am trying to implement the zoom clone with WebRTC using peerjs, the problem is myPeer.on("call", (call) => { its never calling, this same code is executing on the locahost for the others who made the tutorial on zoom clone, I am not sure where is the problem with my code,
Its working on heroku though its not working on localhost, so where is the problem with my localhost setup, why i am not getting the other users who joined the room on localhost, I am not understanding.
script.js
const socket = io("/");
const videoGrid = document.getElementById("video-grid");
const myPeer = new Peer(undefined, {
path: "/peerjs",
host: "/",
port: "3030",
});
let myVideoStream;
const myVideo = document.createElement("video");
myVideo.muted = true;
const peers = {};
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
// Never Called this myPeer.on call
myPeer.on("call", (call) => {
call.answer(stream);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on("user-connected", (userId) => {
console.log("User Connected", userId);
connectToNewUser(userId, stream);
});
// input value
let text = $("input");
// when press enter send message
$("html").keydown(function (e) {
if (e.which == 13 && text.val().length !== 0) {
socket.emit("message", text.val());
text.val("");
}
});
socket.on("createMessage", (message) => {
$("ul").append(`<li class="message"><b>user</b><br/>${message}</li>`);
scrollToBottom();
});
});
socket.on("user-disconnected", (userId) => {
if (peers[userId]) peers[userId].close();
});
myPeer.on("open", (id) => {
socket.emit("join-room", ROOM_ID, id);
});
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
call.on("close", () => {
video.remove();
});
peers[userId] = call;
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
});
videoGrid.append(video);
}
const scrollToBottom = () => {
var d = $(".main__chat_window");
d.scrollTop(d.prop("scrollHeight"));
};
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
setUnmuteButton();
} else {
setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
};
const playStop = () => {
console.log("object");
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
setPlayVideo();
} else {
setStopVideo();
myVideoStream.getVideoTracks()[0].enabled = true;
}
};
const setMuteButton = () => {
const html = `
<i class="fas fa-microphone"></i>
<span>Mute</span>
`;
document.querySelector(".main__mute_button").innerHTML = html;
};
const setUnmuteButton = () => {
const html = `
<i class="unmute fas fa-microphone-slash"></i>
<span>Unmute</span>
`;
document.querySelector(".main__mute_button").innerHTML = html;
};
const setStopVideo = () => {
const html = `
<i class="fas fa-video"></i>
<span>Stop Video</span>
`;
document.querySelector(".main__video_button").innerHTML = html;
};
const setPlayVideo = () => {
const html = `
<i class="stop fas fa-video-slash"></i>
<span>Play Video</span>
`;
document.querySelector(".main__video_button").innerHTML = html;
};
server.js
const express = require("express");
const app = express();
// const cors = require('cors')
// app.use(cors())
const server = require("http").Server(app);
const io = require("socket.io")(server);
const { ExpressPeerServer } = require("peer");
const peerServer = ExpressPeerServer(server, {
debug: true,
});
const { v4: uuidV4 } = require("uuid");
app.use("/peerjs", peerServer);
app.set("view engine", "ejs");
app.use(express.static("public"));
app.get("/", (req, res) => {
res.redirect(`/${uuidV4()}`);
});
app.get("/:room", (req, res) => {
res.render("room", { roomId: req.params.room });
});
io.on("connection", (socket) => {
socket.on("join-room", (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).broadcast.emit("user-connected", userId);
// messages
socket.on("message", (message) => {
//send message to the same room
io.to(roomId).emit("createMessage", message);
});
socket.on("disconnect", () => {
socket.to(roomId).broadcast.emit("user-disconnected", userId);
});
});
});
server.listen(process.env.PORT || 3030);
the function connectToNewUser get executed before the myPeer.on('call')
try modifying the function as
socket.on("user-connected", (userId) => {
console.log("User Connected", userId);
//connectToNewUser(userId, stream);
setTimeout(connectToNewUser,1000,userId,stream)
});
I had the same issue and it seemed to be a race condition with socket.emit("join-room", ROOM_ID, id);.
The server will emit socket.to(roomId).broadcast.emit("user-connected", userId); which will trigger the function that calls the peer in connectToNewUser before the user has finished the navigator promise.
I solved my issue by making sure the navigator promise has finished before firing socket.emit("join-room", ROOM_ID, id);.

Categories

Resources