Video Conferencing in HTML5: WebRTC via Socket.io
Six months ago I experimented with Web sockets for WebRTC and the early implementations of PeerConnection in Chrome. Last week I gave a presentation about WebRTC at Linux.conf.au, so it was time to update that codebase.
I decided to use socket.io for the signalling following the idea of Luc, which made the server code even smaller and reduced it to a mere reflector:
var app = require('http').createServer().listen(1337);
var io = require('socket.io').listen(app);
io.sockets.on('connection', function(socket) {
socket.on('message', function(message) {
socket.broadcast.emit('message', message);
});
});
Then I turned to the client code. I was surprised to see the massive changes that PeerConnection has gone through. Check out my slide deck to see the different components that are now necessary to create a PeerConnection.
I was particularly surprised to see the SDP object now fully exposed to JavaScript and thus the ability to manipulate it directly rather than through some API. This allows Web developers to manipulate the type of session that they are asking the browsers to set up. I can imaging e.g. if they have support for a video codec in JavaScript that the browser does not provide built-in, they can add that codec to the set of choices to be offered to the peer. While it is flexible, I am concerned if this might create more problems than it solves. I guess we’ll have to wait and see.
I was also surprised by the need to use ICE, even though in my experiment I got away with an empty list of ICE servers – the ICE messages just got exchanged through the socket.io server. I am not sure whether this is a bug, but I was very happy about it because it meant I could run the whole demo on a completely separate network from the Internet.
The most exciting news since my talk is that Mozilla and Google have managed to get a PeerConnection working between Firefox and Chrome – this is the first cross-browser video conference call without a plugin! The code differences are minor.
Since the specification of the WebRTC API and of the MediaStream API are now official Working Drafts at the W3C, I expect other browsers will follow. I am also looking forward to the possibilities of:
- multi-peer video conferencing like the efforts around webrtc.io,
- the media stream recording API,
- and the peer-to-peer data API.
The best places to learn about the latest possibilities of WebRTC are webrtc.org and the W3C WebRTC WG. code.google.com has open source code that continues to be updated to the latest released and interoperable features in browsers.
The video of my talk is in the process of being published. There is a MP4 version on the Linux Australia mirror server, but I expect it will be published properly soon. I will update the blog post when that happens.
on February 9th, 2013 at 6:23 am
Hi,
I am actually looking for video conferencing using HTML5. One to one is easy to implement using WebRTC. Is it possible to get atleast 1:N webcam video ( to simulate teaching on net ) ?
1 –> teacher
N –> Students who should be able to see teacher
Cheers,
Siddhartha
on February 12th, 2013 at 5:33 am
I am trying to run your demo on an online node.js server. If I try to estabilish a videochat within my network it works, but when I try to videochat with a friend in another network I see only a black screen for the receiver. Did you try a similar scenario? I think that thare are some problems with the NAT.
on February 12th, 2013 at 7:36 am
Yes, for outside the network you need to use an ICE server. Try https://apprtc.appspot.com/ with your friend. If it works, you can add the ICE server into the peer connection setup.
on February 12th, 2013 at 7:40 am
@Siddartha you can probably send your local video to many peers – just set up one PeerConnection per connect request.
on February 13th, 2013 at 12:39 am
@Silvia should I only put the address of the ICE server in this?
var pc_config = {
“iceServers” : ["stun.l.google.com:19302"]
};
on February 13th, 2013 at 3:07 am
@Silvia I tried the apprtc.appspot.com with my friends using chromium and it doesn’t work; however it works in my local network.
I tried to add an ICE server in your code but it doesn’t work for me (the ip address is from apprtc example)
var pc_config = {
“iceServers” : [{"url":"stun:23.21.150.121"}]
};
I can see the ICE messages in the console and I can also see the address of my remote friend, but I can’t see the remote video
on February 13th, 2013 at 2:02 pm
@Luigi your friend must be using a modern version of Chrome, too (preferably a beta version). Try to get apprtc working first.
on February 15th, 2013 at 8:49 am
I am able to successfully create webrtc video conference between two clients. But the remote videos on both the clients freeze after ~10 sec. Please suggest ways to overcome this problem.
on February 15th, 2013 at 10:55 am
@Laks register a bug on chrome and provide details on how this is happening
on March 4th, 2013 at 8:40 pm
I am trying to implement one demo it is working properly on lan but when i am trying on iternet chat is working but video is not working it display black screen only plz tell me i am new one and it is argent. thank you in advance.
on March 7th, 2013 at 11:48 am
With regards to:
io.sockets.on(‘connection’, function(socket) {
socket.on(‘message’, function(message) {
socket.broadcast.emit(‘message’, message);
});
});
Is it a privacy/security issue to blindly broadcast all new connection messages to all other clients? I’m not sure what data is exposed but it seems kinda dangerous to me?
Also something minor but your indentation is quirky, prolly just a typo
on March 8th, 2013 at 4:35 pm
@John – sure is – that example was a quick and dirty hack to get the signalling working – I would not recommend using this in anger or in production!
on March 14th, 2013 at 2:18 am
Have you tried to interface between Firefox and Chrome? I have followed the guide on the WebRTC website to implement interoperability between the two with no avail. The code I am working from is: https://github.com/tomasbasham/SocialVidRTC/blob/master/javascript/main.js
Do you have any insight?
on March 16th, 2013 at 5:19 am
I am getting this error.
Uncaught TypeError: Cannot call method ‘createOffer’ of null
I believe its the sessiondescription of function setLocalAndSendMessage is causing the error.
Please if you have any suggestions
on March 16th, 2013 at 12:55 pm
@ray what browser are you running?
on March 16th, 2013 at 12:56 pm
@Tomas I’ve not been very successful with Firefox either, but apparently apprtc.appspot.com supports both.
on March 16th, 2013 at 3:12 pm
Im using the latest version of chrome.
on March 16th, 2013 at 3:37 pm
@ray you’re trying to call createOffer() with a null function – did you define setLocalAndSendMessage() after createOffer()?
on March 16th, 2013 at 3:48 pm
First i have placed the “setLocalAndSendMessage()”, then “errorCallBack()” and followed by “mediaconstraint”
Only after that
peerConn.createOffer(setLocalAndSendMessage,
errorCallback,
mediaConstraints);
Am i missing something ?
on March 16th, 2013 at 3:52 pm
@ray s setLocalAndSendMessage(sessionDescription) setting the SDP for local and sending it to remote: peerConn.setLocalDescription(sessionDescription); ?
Put a console.log into setLocalAndSendMessage on the sessionDescription so you can see what it contains.
on March 16th, 2013 at 4:40 pm
sessionDescription error
console.log(“error check:” + peerConn.setLocalDescription.sessionDescription);
Uncaught TypeError: Cannot read property ‘setLocalDescription’ of null
And yes setLocalAndSendMessage(sessionDescription) is setting the SDP for both local and remote.
on March 16th, 2013 at 5:04 pm
Should my signaling channel be open before the call for createOffer() ?
on March 16th, 2013 at 5:17 pm
@ray how much javascript programming have you done before? Your console.log should be inside the setLocalAndSendMessage function and should just print sessionDescription, not the function call. It also seems your peerConn object has not been set up yet. And yes, the first thing you need to do is opening the signalling channel.
on March 16th, 2013 at 5:33 pm
I have placed a logg once the channel is open.
I get the createOffer error before the channel is open logg. Is there a way to first open the connection ?
And thanks for all the replies.
I know you have many other things to do. Much appreciated !
on March 16th, 2013 at 5:38 pm
@ray your code sounds pretty messed up – I’m sorry I can’t help you more without seeing the code and blog comments are not the best way to get help. Ask on stackoverflow and put your code into a snippet sharer, see http://www.sitepoint.com/top-5-places-to-share-code-quickly/ .
on March 21st, 2013 at 8:56 am
It works like a charm. Thanks a lot silvia
I made a small change, instead of using Node js, I used Java Websockets.
on March 21st, 2013 at 9:36 am
@Akane Excellent!
on April 19th, 2013 at 1:56 am
hi!
i was trying your code. i installed nodejs and i am able to run the server(reflector.js).how ever i could not figure it out how the client side can be implemented in nodejs. i want it to give html page.
i was trying it on local host first.
can you please tell me how to integrate the client side with the server?
on April 19th, 2013 at 12:40 pm
The client page that I am using is simply a HTML page. I didn’t serve it through the node server, but through a separate server – I’m using apache but any web server will do. If you want to use node to also serve the static page, you need to adapt reflector.js e.g. http://stackoverflow.com/questions/6084360/node-js-as-a-simple-web-server but listen on port 80 for that server.
on May 6th, 2013 at 5:48 am
hi silvia
thanks so much for your post ! This helped me a lot to set up my first working example with webRTC. It feels like this is now a good starting point to begin to implement own ideas.
cheers
on May 13th, 2013 at 9:45 am
hallo silvia,
we have been trying running your code on this link : https://googledrive.com/host/0B_SthAHTAe0gTThIX1F0MU1HR00/index.html deploying the io server code on https://www.nodejitsu.com/ ‘s hosting platform ,but failing with errors ” Uncaught ReferenceError: io is not defined ”
and ” Failed to load resource “, even being unable to see local video .
any help then ? thanks a lot .
on May 13th, 2013 at 10:06 am
@sola – that is a socket.io error. You should google for that. It means that your code cannot load the socket.io javascript library. You’re trying to load it from http://165.225.130.239:80/socket.io/socket.io.js , but it’s not there.
on May 14th, 2013 at 9:24 pm
HI silvia,
Thanks a lot for your support. Your blog is very helpful.
we successfully implemented your code and we are trying to learn by writing our own video conferencing application. I am new for java script and html. When we deploy your code(the one using socket.io) the video experienced a delay. Is it how it is expected to be or we have done something wrong in the deployment?
Is there any drawbacks of signaling mechanism using web socket(socket.io) in comparison with the signaling mechanism using XHR and channel API?
on May 16th, 2013 at 9:12 am
@hila Any delays in the video have nothing to do with the signaling mechanism, because the video will flow directly from browser to browser once the connection is set up. Thus, it depends on the direct connection between the two browsers and the available bandwidth and processing power of the end points. You can test that by setting up the connection and then taking down the signalling server – your video should continue streaming.
on May 19th, 2013 at 10:01 pm
hi
i am new to webRTC. i read your post i got many things clear, but i could not get the source code. where i can get source code with proper instructions to run.
cheers
on May 20th, 2013 at 8:17 am
@suhail The source code is in the presentations. The presentations are HTML5.
on May 21st, 2013 at 3:30 am
@Siddartha any proress you can share on 1 to N broadcast.
cheers
on May 23rd, 2013 at 8:45 am
Hallo Silvia,
am trying to impliment 3-party chat locally by slightly modifying your code.
In doing so,I am able to see three videos on two tabs,whereas on the third one, only the local video; the other two being “black screen” . Seeing the console,I can only suspect that it might be a code-ordering problem if it should work this way.On the code,i simply added only a third video element, and include another event listening line for the second remote video :{
peerConn.addEventListener(“addstream”, onRemoteStreamAdded1, false);
peerConn.addEventListener(“addstream”, onRemoteStreamAdded2, false);
peerConn.addEventListener(“removestream”, onRemoteStreamRemoved1, false);
peerConn.addEventListener(“removestream”, onRemoteStreamRemoved2, false); }
thanks a lot.