How to write video-conferencing application using WebRTC?
HOME © Muaz Khan . @WebRTCWeb . Github . Latest issues . What's New?
If you're newcomer, newbie or beginner; you're suggested to try RTCMultiConnection.js. |
How to video conferencing?
- Open multiple peer connections to support multi-users connectivity
You should
- create two reusable functions: one for creating offer and other for creating answer. These will be called/invoked many times on each new room participation request.
- create a function like "openSignalingChannel" that should open new socket on each invocation.
- uniquely identify the current user
It is preferred to use socket.io because it supports multiplexing.
Those functions
On invocation; those functions should:
- create a new peer connection
- create offer or answer session-descriptions accordingly
Then, on page load
On page load: call "openSignalingChannel" method. This time your "openSignalingChannel" must open "default-channel" that must be active all the time. That default channel will be used to:
- show list of all active rooms
- allow new users to send "participation requests"
For room creator
If someone creates new room; you should continuously transmit his room details over the "default-channel".
You can use transmission-interval i.e. 3 or 5 seconds. It should be your own preference.
For room participant
Send "participation request" over same "default-channel".
You should also send participant's unique id in the "participation request" message.
Call "openSignalingChannel" method to create new socket where you should use his unique id as channel name/label.
That newly created socket will be used to get offer-sdp from room owner. It will also be used to get ICE gathered by room owner.
As soon as room owner will receive participation-request
You should create new socket using "openSignalingChannel" method where you should use participant's unique id for channel name/label. Otherwise, use random number that must be passed along with "participation request" message.
That new socket will be used to exchange SDP/ICE between room owner and that participant.
On the room owner's side
You should quickly create a new peer connection.
You should also quickly create "offer" because room-owner is expected to play the role of "offerer" for each new participant.
As soon as offer is created; you should pass that "offer sdp" over same socket that is being used to exchange SDP/ICE between room owner and participant.
On the participant's side
Set remote descriptions using offer sdp sent by room owner.
Create answer. Participant will always play role of "answerer" on joining new room.
As soon as answer is created; you should pass that "answer sdp" over same socket that is being used to exchange SDP/ICE between room owner and participant.
Again, on the room owner's side
Set remote descriptions using answer sdp sent by participant.
And handshake is completed! Are you sure? Wait....there is something else!
ICE candidates gathered on room owner's side
You should use same socket to exchange/post/transfer these ICE candidates on participant's side.
ICE candidates gathered on participant's side
You should use same socket to exchange/post/transfer these ICE candidates on room owner's side.
Finally...
And finally handshake is completed. You're done! Good job Sir!
For upcoming participants
For each new participant; repeat above process and that's it!
For video-conferencing
After successful handshake between room owner and the participant; transmit participant's details over all other connected sockets i.e. toward all other room participants.
As soon as other participants will receive transmitted details; make "auto" participation request toward that "last participant".
And then follow above process again.
Explaining above theory using (a little bit real however) pseudo codes.
Reusable functions...
function openSignalingChannel(channel) { var socket = io.connect('http://your-site:8888/' + channel); } function createOffer() { var peer = new RTCPeerConnection(null); // pass ICE-Servers peer.createOffer({OfferToReceiveVideo:true}).then(onSuccess); } function createAnswer(offer_sdp) { var peer = new RTCPeerConnection(null); // pass ICE-Servers peer.setRemoteDescription(new RTCSessionDescription(offer_sdp)).then(function() { peer.createAnswer({OfferToReceiveVideo:true}).then(onSuccess); }); }
Opening default signaling channel
var channel = openSignalingChannel('default-channel'); channel.onmessage = function(message) { if(message.participationRequest) {} if(message.sharingRoomDetails) {} };
Assuming a new participant
channel.send({ isNewParticipant: true, participant_id: participant_id }); // this private socket will be used to exchange sdp/ice var privateChannel = openSignalingChannel(participant_id); privateChannel.onmessage = function(message) { if(message.type === 'offer') { createAnswer(message.sdp); // on creating answer-sdp; transmit it over "privateChannel" privateChannel.send(answer_sdp); } };
On participation request
if(message.isNewParticipant) { var privateChannel = openSignalingChannel(message.participant_id); createOffer(); // on creating offer-sdp; transmit it over "privateChannel" privateChannel.send(offer_sdp); privateChannel.onmessage = function(message) { if(message.type === 'answer') peer.setRemoteDescription(new RTCSessionDescription(message.sdp)); }; }
Exchanging ICE
privateChannel.onmessage = function(message) { if(message.ice) peer.addIceCandidate(new RTCIceCandidate(message.ice)); }; peer.onicecandidate = function(event) { if(!event.candidate) return; privateChannel.send(event.candidate); };
For video-conferencing
After successful handshake:
for(var i = 0; i < otherParticipants.length; i++) { var participant = otherParticipants[i]; // send/emit/push/etc. participant.send({ isNewParticipant: true, participant_id: '0123456789' }); }
Use "participant_id" you can make additional participation requests to him.