WebRTC for Beginners

HOME © Muaz Khan . @WebRTCWeb . Github . Latest issues . What's New?

This tutorial is out-dated (written in 2013). Please check this tutorial instead: https://codelabs.developers.google.com/codelabs/webrtc-web/#0


  1. If you're newcomer, newbie or beginner; you're suggested to try RTCMultiConnection.js or DataChannel.js libraries.

Getting USER MEDIA using Chrome media capture APIs

First of all: you need to get access to microphone and camera if you want to build a video streaming app.

var streamToAttach;
navigator.webkitGetUserMedia({ audio: true, video: true }, function (stream) {
    video.src = webkitURL.createObjectURL(stream);
    streamToAttach = stream;
}, function(error) {

Getting USER MEDIA using Firefox media capture APIs

var streamToAttach;
navigator.mozGetUserMedia({ audio: true, video: true }, function (stream) {
    video.mozSrcObject = stream;
    streamToAttach = stream;
}, function(error) {

There are following possible situations:

  1. A person wants to share camera with his friend(s): so, he will make an offer to his friend to join him.
    He is the offerer.
  2. A person who receives an offer from a friend: so, he will join him. He is the answerer.

There are so many other possible situations. Let go to the point.


The first situation: a person wants to make an offer request to his friend. He will create offer sdp and send that sdp to his friend.

First of all: we need to open a peer connection:

var peerConnection = new webkitRTCPeerConnection(
    { "iceServers": [{ "url": "stun:stun.l.google.com:19302" }] }

webkitRTCPeerConnection (or mozRTCPeerConnection) constructor takes two objects (arguments):

  1. ICE servers (STUN or TURN)
  2. Optional (like RtpDataChannels)

For Firefox, you can use this STUN server:
{ "iceServers": [{ "url": "stun:stun.services.mozilla.com" }] }

Setting event handlers for peer connection object:

peerConnection.onicecandidate = onicecandidate;
peerConnection.onaddstream = onaddstream;
peerConnection.addStream (streamToAttach);

In simple words: onicecandidate returns locally generated ICE candidates so you can pass them over other peer(s) via XHR or Socket.

  • "locally-generated" means ice candidates that are trickled or gathered for your peer object; i.e. list of ice candidates that are returned by STUN/TURN servers; these ice candidates contains your public ipv4/ipv6 addresses as well as UDP random addresses; you need to share these ice candidates with target peer so WebRTC ICE Agent can use your ports to setup your connection with target peer!
  • onaddstream returns remote stream (microphone and camera of your friend!).

    peerConnection.addStream attaches your local microphone and camera for other peer.

    Creating Offer SDP

    peerConnection.createOffer(function (sessionDescription) {
        // POST-Offer-SDP-For-Other-Peer(sessionDescription.sdp, sessionDescription.type);
    }, function(error) {
    }, { 'mandatory': { 'OfferToReceiveAudio': true, 'OfferToReceiveVideo': true } });


    Assume that you sent offer sdp to your friend using XHR. Now, "process" that offer sdp and then create answer sdp and send it back to offerer:


    peerConnection.setRemoteDescription(new RTCSessionDescription(offerSDP));

    And to createAnswer...

    peerConnection.createAnswer(function (sessionDescription) {
        // POST-answer-SDP-back-to-Offerer(sessionDescription.sdp, sessionDescription.type);
    }, function(error) {
    }, { 'mandatory': { 'OfferToReceiveAudio': true, 'OfferToReceiveVideo': true } });

    Offerer received answer sdp from answerer


    peerConnection.setRemoteDescription(new RTCSessionDescription(answerSDP));

    Offer/Answer exchange is done. What remaining is ICE candidates.

    On getting locally generated ICE

    function onicecandidate(event) {
        if (!peerConnection || !event || !event.candidate) return;
        var candidate = event.candidate;
        // POST-ICE-to-other-Peer(candidate.candidate, candidate.sdpMLineIndex);

    On getting ICE sent by other peer

    peerConnection.addIceCandidate(new RTCIceCandidate({
        sdpMLineIndex: candidate.sdpMLineIndex,
        candidate: candidate.candidate

    onaddstream event handling

    function onaddstream(event) {
        if (!event) return;
        remote_video.src = webkitURL.createObjectURL(event.stream);
        // remote_video.mozSrcObject  = event.stream;

    Wait until remote stream starts flowing

    function onaddstream(event) {
        if (!event) return;
        remote_video.src = webkitURL.createObjectURL(event.stream);
        // remote_video.mozSrcObject  = event.stream;
    function waitUntilRemoteStreamStartsFlowing()
        if (!(remote_video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA 
            || remote_video.paused || remote_video.currentTime <= 0)) 
            // remote stream started flowing!
        else setTimeout(waitUntilRemoteStreamStartsFlowing, 50);

    Single Page Demos

    1. Simplest Example!
    2. Simple Demo using Socket.io
    3. Simple Demo using WebSocket
    4. A few other single-page demos can be found here

    Real Demos

    1. Simple demo using WebSockets / Source Code
    2. Simple demo using Socket.io / Source Code

    Other Tutorials

    1. Are you interested in a "more" simple full-fledged guide? Read this tutorial.
    2. Are you interested in a "more" detailed guide? Read this tutorial.
    3. You can find many tutorials here: https://www.webrtc-experiment.com/#documentations

    Latest Updates


    Enter your email too; if you want "direct" reply!