WebRTC Introduction - Client Side Signalling
- Get Video Source
- Signalling with Websockets
- Scaffolding the Signalling Server
- Client Side Signalling Events
WIP
- WebRTC Introduction - Websockets
- WebRTC Introduction - Client Side Signalling
- WebRTC Introduction - Interactive Connectivity Establishment
Resources:
Get Video Source
Get Video from Webcam with getUserMedia():
chat.js
const chatLobby = document.getElementById('chat-lobby')
const chatRoom = document.getElementById('room-name')
const chatJoin = document.getElementById('join')
const chatLocal = document.getElementById('video-local')
let constraints = {
audio: false,
video: { width: 320, height: 180 },
}
const browserSupportsMedia = () => {
return navigator.mediaDevices.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.mzGetUserMedia
}
const fetchLocalStream = () => {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
userStream = stream;
chatLobby.style = "display:none";
chatLocal.srcObject = stream;
chatLocal.onloadedmetadata = function (e) {
chatLocal.play();
}
})
.catch(function (err) {
/* handle the error */
alert('ERROR :: ' + error.name);
})
}
chatJoin.addEventListener('click', function() {
if (chatRoom.value == "") {
alert('INFO :: Please enter a room name first!')
} else {
fetchLocalStream()
}
})
Signalling with Websockets
Use socket.io
to manage connections:
index.js
const express = require("express");
const socket = require("socket.io");
const port = 6969
var app = express();
var server = app.listen(port, function () {
console.log('INFO :: Webserver is running on :: http://localhost:' + port)
});
app.use(express.static("public"));
var io = socket(server);
io.on("connection", function (socket) {
console.log("INFO :: Websocket connection established :: ", socket.id)
socket.on("join", function (roomName) {
// check if is already full = 2 participants
let rooms = io.sockets.adapter.rooms;
let room = rooms.get(roomName);
// if room doesn't exists create it
if(room == undefined) {
socket.join(roomName)
console.log('INFO :: Participant created room ::', roomName)
// if room exists and only has 1 participant - join
} else if(room.size == 1) {
socket.join(roomName)
console.log('INFO :: Participant joined room ::', roomName)
} else {
console.log('WARNING :: Room', roomName, 'is full!')
}
})
});
Use the websocket connection to emit the join
event when a user clicked the join button:
chat.js
const socket = io.connect("http://localhost:6969")
chatJoin.addEventListener('click', function() {
if (chatRoom.value == "") {
alert('INFO :: Please enter a room name first!')
} else {
socket.emit("join", chatRoom.value)
fetchLocalStream()
}
})
Start the application and open the application frontend from three different devices:
npm start
> webrtc-intro@1.0.0 start
> node index.js
INFO :: Webserver is running on :: http://localhost:6969
INFO :: Websocket connection established :: _I-Guhml-JEa9VJwAAAF
INFO :: Participant created room :: test
INFO :: Websocket connection established :: TAaYXAYJDbm4lDP5AAAH
INFO :: Participant joined room :: test
INFO :: Websocket connection established :: lAgg07QE2DSltIwsAAAJ
WARNING :: Room test is full!
Scaffolding the Signalling Server
index.js
io.on("connection", function (socket) {
console.log("INFO :: Websocket connection established :: ", socket.id)
socket.on("join", function (roomName) {
// check if is already full = 2 participants
let rooms = io.sockets.adapter.rooms;
let room = rooms.get(roomName);
// if room doesn't exists create it
if(room == undefined) {
socket.join(roomName)
socket.emit('created')
} else if(room.size == 1) {
socket.join(roomName)
socket.emit('joined')
} else {
socket.emit('occupied')
}
})
// emit ready state to room when created
socket.on('ready', function(roomName) {
socket.broadcast.to(roomName).emit('ready')
console.log('INFO :: Room is ready')
})
// establish connection between candidates (ICE)
socket.on('candidate', function(candidate, roomName) {
socket.broadcast.to(roomName).emit('candidate', candidate)
console.log('INFO :: Candidate ready to establish connection')
})
// make offer to other participant
socket.on('offer', function(offer, roomName) {
socket.broadcast.to(roomName).emit('offer', offer)
console.log('INFO :: Offer to establish connection')
})
// send answer to connection offer
socket.on('answer', function(answer, roomName) {
socket.broadcast.to(roomName).emit('answer', answer)
console.log('INFO :: Answer to connection offer')
})
});
Client Side Signalling Events
The server now emits each of those events through the websocket connection. We now need to handle those events on the client side:
Created, Joined and Occupied
chat.js
let creator = false
chatJoin.addEventListener('click', function() {
if (chatRoom.value == "") {
alert('INFO :: Please enter a room name first!')
} else {
socket.emit("join", chatRoom.value)
}
})
// Room created event -> fetch video
socket.on('created', function() {
creator = true
fetchLocalStream()
})
// Room joined event -> fetch video
socket.on('joined', function() {
creator = false
fetchLocalStream()
})
// Room is full event
socket.on('occupied', function() {
alert("WARNING :: Room occupied. Please try again later.")
})