I'm using socket.io with peerjs to create a video conference app it shows me this error in the console of browser :
http://localhost:3000/socket.io/?EIO=3&transport=polling&t=O0Hrv-4&sid=2C_b3aCCfINuuUFNAAAA 400 (Bad Request)
and
WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=3&transport=websocket&sid=TIij4-ksOm6WI8URAAAA' failed: Invalid frame header
Can anyone please help?
i have a final soon
#server.js#
const express = require('express');
const app = express();
const server = require('http').Server(app);
const { v4: uuidv4 } = require('uuid');
const io = require('socket.io')(server);
const { ExpressPeerServer } = require('peer');
const peerServer = ExpressPeerServer(server, {
debug: true
});
app.use(express.static('public'));
app.use('/peerjs', peerServer);
app.set('view engine', 'ejs');
app.get('/', (req, res) => {
res.redirect(`/${uuidv4()}`);
});
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.param.room })
});
io.on('connection', socket => {
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)
})
})
})
server.listen(process.env.PORT || 3000)
##room.ejs##
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zoom-Clone</title>
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script src="https://kit.fontawesome.com/c939d0e917.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
const ROOM_ID = "<%= roomId %>";
</script>
</head>
<body>
<div class="main">
<div class="main_left">
<div class="main_videos">
<div id='video-grid'>
</div>
</div>
<div class="main_controls">
<div class="main_controls_block">
<div onclick="muteUnmute()" class="main_controls_button main_mute_button">
<i class="fas fa-microphone"></i>
<span>Mute</span>
</div>
<div onclick="playStop()" class="main_controls_button main_video_button">
<i class="fas fa-video"></i>
<span>Stop Video</span>
</div>
</div>
<div class="main_controls_block">
<div class="main_controls_button">
<i class="fas fa-shield-alt"></i>
<span>Security</span>
</div>
<div class="main_controls_button">
<i class="fas fa-user-friends">< <span>Participants</span>
</div>
<div class="main_controls_button">
<i class="fas fa-comment-alt"></i>
<span>Chat</span>
</div>
</div>
<div class="main_controls_block">
<div class="main_controls_button">
<span class="leave_meeting">Leave Meeting</span>
</div>
</div>
</div>
</div>
<div class="main_right">
<div class="main_header">
<h6>Chat</h6>
</div>
<div class="main_chat_window">
<ul class="messages">
</ul>
</div>
<div class="main_message_container">
<input id="chat_message" type="text" placeholder="Type message here...">
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
###script.js###
const socket = io('/');
const videoGrid = document.getElementById('video-grid');
const myVideo = document.createElement('video');
myVideo.muted = true;
var peer = new Peer(undefined, {
path: '/peerjs',
host: '/',
port: '3001'
});
let myVideoStream;
const addVideoStream = (video, stream) => {
video.srcObject = stream;
video.addEventListener('loadedmetadata', () => {
video.play();
})
videoGrid.append(video);
};
const connectToNewUser = (userId, stream) => {
const call = peer.call(userId, stream);
const video = document.createElement('video');
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream);
})
}
const scrollToBottom = () => {
let d = $('main_chat_window');
d.scrollTop(d.prop("scrollHeight"));
}
const setMuteButton = () => {
const html = `
<i class="fas fa-microphone"></i>
<span>Mute</span>`
$('.main_mute_button').html(html);
}
const setUnmuteButton = () => {
const html = `
<i class="unmute fas fa-microphone-slash"></i>
<span>Ummte</span>`
$('.main_mute_button').html(html);
}
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
setUnmuteButton();
}
else {
setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
}
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
peer.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);
})
})
peer.on('open', id => {
socket.emit('join-room', ROOM_ID, id);
});
let text = $('input');
$('html').keydown(e => {
if (e.which == 13 && text.val().length !== 0) {
socket.emit('message', text.val());
console.log(text.val());
text.val('')
}
});
socket.on('createMessage', message => {
$('ul').append(`<li class="message"><b>user</b><br />${message}</li>`)
scrollToBottom();
})
const setPlayVideo = () => {
const html = `
<i class="stop fas fa-video-slash"></i>
<span>PlayVideo</span>`
$('.main_video_button').html(html);
}
const setStopVideo = () => {
const html = `
<i class="fas fa-video"></i>
<span>Stop Video</span>`
$('.main_video_button').html(html);
}
const playStop = () => {
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
setPlayVideo();
}
else {
setStopVideo();
myVideoStream.getVideoTracks()[0].enabled = true;
}
}
Related
I have done a video call POC with peerjs. It works perfectly with web to web (both video, audio & text) but when I try to connect with mobile. It asks permission for audio and video. When I accepts ,I could see the mic icon and video icon on mobile which means audio and video is enabled in mobile. But I couldn't see the video on mobile and mobile's video on web. NOTE: Text chat between mobile to web is working fine only video not rendering.
What I see on web
What I see on mobile
Code
server.js
const express = require("express");
const app = express();
const dotenv = require('dotenv');
dotenv.config();
var random = Math.floor(1000 + Math.random() * 9000);
const server = require("http").Server(app);
const { v4: uuidv4 } = require("uuid");
const io = require("socket.io")(server, {
cors: {
origin: "*",
},
});
// Peer
const { ExpressPeerServer } = require("peer");
const peerServer = ExpressPeerServer(server, {
debug: true,
port: 443
});
const PORT = 3000;
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use("/peerjs", peerServer);
app.get("/", (req, rsp) => {
rsp.redirect(`/${random}`);
});
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("message", (message) => {
io.to(roomId).emit("createMessage", message);
});
});
});
server.listen(PORT,()=>{
console.log("Started")
});
script.js
const socket = io('/')
const chatInputBox = document.getElementById("chat_message");
const all_messages = document.getElementById("all_messages");
const main__chat__window = document.getElementById("main__chat__window");
const videoGrid = document.getElementById("video-grid");
const myVideo = document.createElement("video");
myVideo.muted = true;
let peer = new Peer(undefined, {
path: "/peerjs",
host: "XXXXXXXXXXXXXXXXX.XXX.XXXX",
port: 443,
});
let myVideoStream;
var getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
peer.on("call", (call) => {
call.answer(stream);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on('user-connected', userId => {
// user is joining`
setTimeout(() => {
// user joined
connectToNewUser(userId, stream)
}, 1000)
})
document.addEventListener("keydown", (e) => {
if (e.which === 13 && chatInputBox.value != "") {
socket.emit("message", chatInputBox.value);
chatInputBox.value = "";
}
});
socket.on("createMessage", (msg) => {
console.log(msg);
let li = document.createElement("li");
li.innerHTML = msg;
all_messages.append(li);
main__chat__window.scrollTop = main__chat__window.scrollHeight;
});
});
peer.on("call", function (call) {
getUserMedia(
{ video: true, audio: true },
function (stream) {
call.answer(stream); // Answer the call with an A/V stream.
const video = document.createElement("video");
call.on("stream", function (remoteStream) {
addVideoStream(video, remoteStream);
});
},
function (err) {
console.log("Failed to get local stream", err);
}
);
});
peer.on("open", (id) => {
socket.emit("join-room", ROOM_ID, id);
});
// CHAT
const connectToNewUser = (userId, streams) => {
var call = peer.call(userId, streams);
console.log(call);
var video = document.createElement("video");
call.on("stream", (userVideoStream) => {
console.log(userVideoStream);
addVideoStream(video, userVideoStream);
});
};
const addVideoStream = (videoEl, stream) => {
videoEl.srcObject = stream;
videoEl.addEventListener("loadedmetadata", () => {
videoEl.play();
});
videoGrid.append(videoEl);
let totalUsers = document.getElementsByTagName("video").length;
if (totalUsers > 1) {
for (let index = 0; index < totalUsers; index++) {
document.getElementsByTagName("video")[index].style.width =
100 / totalUsers + "%";
}
}
};
const playStop = () => {
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
setPlayVideo();
} else {
setStopVideo();
myVideoStream.getVideoTracks()[0].enabled = true;
}
};
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
setUnmuteButton();
} else {
setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
};
const setPlayVideo = () => {
const html = `<i class="unmute fa fa-pause-circle"></i>
<span class="unmute">Resume Video</span>`;
document.getElementById("playPauseVideo").innerHTML = html;
};
const setStopVideo = () => {
const html = `<i class=" fa fa-video-camera"></i>
<span class="">Pause Video</span>`;
document.getElementById("playPauseVideo").innerHTML = html;
};
const setUnmuteButton = () => {
const html = `<i class="unmute fa fa-microphone-slash"></i>
<span class="unmute">Unmute</span>`;
document.getElementById("muteButton").innerHTML = html;
};
const setMuteButton = () => {
const html = `<i class="fa fa-microphone"></i>
<span>Mute</span>`;
document.getElementById("muteButton").innerHTML = html;
};
ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/peerjs/1.3.1/peerjs.js.map"></script> -->
<script src="/socket.io/socket.io.js"></script>
<script>
const ROOM_ID = "<%= roomId %>";
</script>
</head>
<body>
<div class="main">
<div class="main__left">
<div class="main__videos">
<div id="video-grid"></div>
</div>
<div class="main__controls">
<div class="main__controls_block">
<div
class="main__controls_button"
id="muteButton"
onclick="muteUnmute()"
>
<i class="fa fa-microphone"></i>
<span>Mute</span>
</div>
<div
class="main__controls_button"
id="playPauseVideo"
onclick="playStop()"
>
<i class="fa fa-video-camera"></i>
<span>Pause Video</span>
</div>
</div>
<!-- <div class="main__controls_block">
<div class="main__controls_button">
<i class="fa fa-shield"></i>
<span>Security</span>
</div>
<div class="main__controls_button">
<i class="fa fa-users"></i>
<span>Participants</span>
</div>
<div class="main__controls_button">
<i class="fa fa-comment"></i>
<span>Chat</span>
</div>
</div> -->
<div class="main__controls_block">
<div class="main__controls_button leaveMeeting" id="leave-meeting">
<i class="fa fa-times"></i>
<span class="">Leave Meeting</span>
</div>
</div>
</div>
</div>
<div class="main__right">
<div class="main__header">
<h6>Chat</h6>
</div>
<div class="main__chat__window" id="main__chat__window">
<ul class="messages" id="all_messages"></ul>
</div>
<div class="main__message_container">
<input
type="text"
id="chat_message"
placeholder="Type message here.."
/>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
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;
}
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
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);.
I have written code in javascript and html. The goal of that was to get a user to log in into youtube and once they do, they will see some feed. Now i want to use this code into a reactjs project. the question is how can i do this. I am having trouble doing that. the code below is the html and java script code i wrote. Now the code at the bottom is what i tried to do in reactjs.
// Options
const CLIENT_ID = '530254027383-djo7723li5ju3c6t4e2taacvj5idbp50.apps.googleusercontent.com';
const DISCOVERY_DOCS = [
'https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest'
];
const SCOPES = 'https://www.googleapis.com/auth/youtube.readonly';
const authorizeButton = document.getElementById('authorize-button');
const signoutButton = document.getElementById('signout-button');
const content = document.getElementById('content');
const channelForm = document.getElementById('channel-form');
const channelInput = document.getElementById('channel-input');
const videoContainer = document.getElementById('video-container');
const defaultChannel = 'techguyweb';
// Form submit and change channel
channelForm.addEventListener('submit', e => {
e.preventDefault();
const channel = channelInput.value;
getChannel(channel);
});
// Load auth2 library
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
// Init API client library and set up sign in listeners
function initClient() {
gapi.client
.init({
discoveryDocs: DISCOVERY_DOCS,
clientId: CLIENT_ID,
scope: SCOPES
})
.then(() => {
// Listen for sign in state changes
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle initial sign in state
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
// Update UI sign in state changes
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
content.style.display = 'block';
videoContainer.style.display = 'block';
getChannel(defaultChannel);
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
content.style.display = 'none';
videoContainer.style.display = 'none';
}
}
// Handle login
function handleAuthClick() {
gapi.auth2.getAuthInstance().signIn();
}
// Handle logout
function handleSignoutClick() {
gapi.auth2.getAuthInstance().signOut();
}
// Display channel data
function showChannelData(data) {
const channelData = document.getElementById('channel-data');
channelData.innerHTML = data;
}
// Get channel from API
function getChannel(channel) {
gapi.client.youtube.channels
.list({
part: 'snippet,contentDetails,statistics',
forUsername: channel
})
.then(response => {
console.log(response);
const channel = response.result.items[0];
const output = `
<ul class="collection">
<li class="collection-item">Title: ${channel.snippet.title}</li>
<li class="collection-item">ID: ${channel.id}</li>
<li class="collection-item">Subscribers: ${numberWithCommas(
channel.statistics.subscriberCount
)}</li>
<li class="collection-item">Views: ${numberWithCommas(
channel.statistics.viewCount
)}</li>
<li class="collection-item">Videos: ${numberWithCommas(
channel.statistics.videoCount
)}</li>
</ul>
<p>${channel.snippet.description}</p>
<hr>
<a class="btn grey darken-2" target="_blank" href="https://youtube.com/${
channel.snippet.customUrl
}">Visit Channel</a>
`;
showChannelData(output);
const playlistId = channel.contentDetails.relatedPlaylists.uploads;
requestVideoPlaylist(playlistId);
})
.catch(err => alert('No Channel By That Name'));
}
// Add commas to number
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function requestVideoPlaylist(playlistId) {
const requestOptions = {
playlistId: playlistId,
part: 'snippet',
maxResults: 10
};
const request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(response => {
console.log(response);
const playListItems = response.result.items;
if (playListItems) {
let output = '<br><h4 class="center-align">Latest Videos</h4>';
// Loop through videos and append output
playListItems.forEach(item => {
const videoId = item.snippet.resourceId.videoId;
output += `
<div class="col s3">
<iframe width="100%" height="auto" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
`;
});
// Output videos
videoContainer.innerHTML = output;
} else {
videoContainer.innerHTML = 'No Uploaded Videos';
}
});
}
now the code above was the javascript and now the code below is the html I used.
<!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">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/css/materialize.min.css">
<style>
#content,
#authorize-button,
#signout-button {
display: none
}
</style>
<title>YouTube Channel Data</title>
</head>
<body>
<nav class="black">
<div class="nav-wrapper">
<div class="container">
YouTube Channel Data
</div>
</div>
</nav>
<br>
<section>
<div class="container">
<p>Log In With Google</p>
<button class="btn red" id="authorize-button">Log In</button>
<button class="btn red" id="signout-button">Log Out</button>
<br>
<div id="content">
<div class="row">
<div class="col s6">
<form id="channel-form">
<div class="input-field col s6">
<input type="text" placeholder="Enter Channel Name" id="channel-input">
<input type="submit" value="Get Channel Data" class="btn grey">
</div>
</form>
</div>
<div id="channel-data" class="col s6"></div>
</div>
<div class="row" id="video-container"></div>
</div>
</div>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/js/materialize.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="main.js"></script>
<script async defer src="https://apis.google.com/js/api.js" onload="this.onload=function(){};handleClientLoad()" onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
the code below is the code i tried to do in reactjs ,but it is not working . Any idea on how i can get it to work or if it is even possible?
import React, { Component } from 'react'
import YouTube from 'react-youtube';
/* global gapi */
const CLIENT_ID = '530254027383-djo7723li5ju3c6t4e2taacvj5idbp50.apps.googleusercontent.com';
const DISCOVERY_DOCS = [
'https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest'
];
const SCOPES = 'https://www.googleapis.com/auth/youtube.readonly';
const authorizeButton = document.getElementById('authorize-button');
const signoutButton = document.getElementById('signout-button');
const content = document.getElementById('content');
const channelForm = document.getElementById('channel-form');
const channelInput = document.getElementById('channel-input');
const videoContainer = document.getElementById('video-container');
const defaultChannel = 'techguyweb';
export default class youtube extends Component {
// Form submit and change channel
channelForm.addEventListener('submit', e => {
e.preventDefault();
const channel = channelInput.value;
getChannel(channel);
});
// Load auth2 library
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
// Init API client library and set up sign in listeners
function initClient() {
gapi.client
.init({
discoveryDocs: DISCOVERY_DOCS,
clientId: CLIENT_ID,
scope: SCOPES
})
.then(() => {
// Listen for sign in state changes
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle initial sign in state
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
// Update UI sign in state changes
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
content.style.display = 'block';
videoContainer.style.display = 'block';
getChannel(defaultChannel);
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
content.style.display = 'none';
videoContainer.style.display = 'none';
}
}
// Handle login
function handleAuthClick() {
gapi.auth2.getAuthInstance().signIn();
}
// Handle logout
function handleSignoutClick() {
gapi.auth2.getAuthInstance().signOut();
}
// Display channel data
function showChannelData(data) {
const channelData = document.getElementById('channel-data');
channelData.innerHTML = data;
}
// Get channel from API
function getChannel(channel) {
gapi.client.youtube.channels
.list({
part: 'snippet,contentDetails,statistics',
forUsername: channel
})
.then(response => {
console.log(response);
const channel = response.result.items[0];
const output = `
<ul class="collection">
<li class="collection-item">Title: ${channel.snippet.title}</li>
<li class="collection-item">ID: ${channel.id}</li>
<li class="collection-item">Subscribers: ${numberWithCommas(
channel.statistics.subscriberCount
)}</li>
<li class="collection-item">Views: ${numberWithCommas(
channel.statistics.viewCount
)}</li>
<li class="collection-item">Videos: ${numberWithCommas(
channel.statistics.videoCount
)}</li>
</ul>
<p>${channel.snippet.description}</p>
<hr>
<a class="btn grey darken-2" target="_blank" href="https://youtube.com/${
channel.snippet.customUrl
}">Visit Channel</a>
`;
showChannelData(output);
const playlistId = channel.contentDetails.relatedPlaylists.uploads;
requestVideoPlaylist(playlistId);
})
.catch(err => alert('No Channel By That Name'));
}
// Add commas to number
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function requestVideoPlaylist(playlistId) {
const requestOptions = {
playlistId: playlistId,
part: 'snippet',
maxResults: 10
};
const request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(response => {
console.log(response);
const playListItems = response.result.items;
if (playListItems) {
let output = '<br><h4 class="center-align">Latest Videos</h4>';
// Loop through videos and append output
playListItems.forEach(item => {
const videoId = item.snippet.resourceId.videoId;
output += `
<div class="col s3">
<iframe width="100%" height="auto" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
`;
});
// Output videos
videoContainer.innerHTML = output;
} else {
videoContainer.innerHTML = 'No Uploaded Videos';
}
});