Dear reader, before we start writing the code, let's take a look at the concept of video calls.Imagine the situation: we have a chat platform and we need to fasten video calls to it, that is, a certain Vasya is sitting online and he wants to call Petya, to implement such a feature, we need WebSocket technology .Well, let's raise our WebSocket server, node.js will help us with this;Create the sockets.js file and write the server socket code there:const WebSocketServer = require('websocket').server;
const http = require('http');
const server = http.createServer(function(request, response) {
});
server.listen(1337, function() {});
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
let connection = request.accept(null, request.origin);
})
Create an index.html file and write the code there to open a socket connection: <video autoplay muted height='300' width='300' style="position:fixed;bottom:0;left:0;z-index: 9999;" src="" id='my'>
</video>
<video autoplay height='300' width='300' style="position:fixed;bottom:0;left:300px;z-index: 999999;" src="" id='not_my'>
</video>
Now create and connect the script.js file to our html file: let connection = new WebSocket('ws://127.0.0.1:1337');
connection.onopen = function(){
}
connection.onmessage = function(message){
}
connection.onerror = function (error) {
console.error(error)
};
So, back to our Vasya and Petya
This is the initial stage at which Vasya and Petya simply exchange JSON about whether we will receive a call or not. That is, when entering our page, we must open a WebSocket connection to communicate with our socket server.- We first send a helmet to the JSON server socket so that we want to call Petya from Vasya’s account
connection.send(JSON.stringify({
}))
- We must accept this JSON on the socket server, after we receive the request, we attach the message event to our server :
connection.on('message',function(message){
let self = JSON.parse(message.utf8Data);
})
Having talked and decided that both users are ready for a conversation, we need to figure out how video communication works in a browser, a module for this is built in js - RTCPeerConnection
We need to open RTCPeerConnection, with which we can generate an offer and send it to the user we need, again through our socket server, which, upon receiving it, will generate a response and send it back, after which we begin to exchange ice packets containing information about the environment this computer, which is necessary for the successful establishment of video communications.We generate and send offer
var pc = new RTCPeerConnection();
var peerConnectionConfig = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302'
}
]
}
pc.onicecandidate = function (event) {
console.log('new ice candidate', event.candidate);
if (event.candidate !== null) {
connection.send(JSON.stringify({
}))
}
};
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.getUserMedia({video: true,audio:true}, function(stream) {
var my_video = document.getElementById('my')
my_video.srcObject = stream
pc.onaddstream = e => {
document.getElementById('not_my').srcObject = e.stream;
console.log('not stream is added')
}
pc.addStream(stream);
pc.createOffer(function(offer) {
pc.setLocalDescription(offer, function() {
}))
}, e=> console.log(e));
}, e=> console.log(e));
},function (){console.warn("Error getting audio stream from getUserMedia")});
function endCall() {
var videos = document.getElementsByTagName("video");
for (var i = 0; i < videos.length; i++) {
videos[i].pause();
}
pc.close();
}
function error(err) {
endCall();
}
We process offer and generate answer
var pc = new RTCPeerConnection();
var peerConnectionConfig = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302'
}
]
}
pc.onicecandidate = function (event) {
console.log('new ice candidate', event.candidate);
if (event.candidate !== null) {
}
};
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.getUserMedia({video: true,audio:true}, function(stream) {
var my_video = document.getElementById('my')
my_video.srcObject = stream
console.log('stream is added while offering')
pc.onaddstream = e => {
console.log('not my stream is added while offering')
document.getElementById('not_my').srcObject = e.stream;
}
pc.addStream(stream);
pc.setRemoteDescription(new RTCSessionDescription(data.offer), function() {
pc.createAnswer(function(answer) {
pc.setLocalDescription(answer, function() {
}, e => console.log(e));
}, e => console.log(e));
}, e => console.log(e));
},function (){console.warn("Error getting audio stream from getUserMedia")});
}
}
We accept the answer and create a video stream
pc.setRemoteDescription(new RTCSessionDescription(data.answer), function() { }, error);
And the last thing we need to do is process the ice packets
pc.addIceCandidate(new RTCIceCandidate(ice))