WebRTC for Beginners ® Muaz Khan

© 2013 Muaz Khan<@muazkh> » @WebRTC Experiments » Google+ » What's New?

Suggestions

  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;
});

Getting USER MEDIA using Firefox media capture APIs

var streamToAttach;
navigator.mozGetUserMedia({ audio: true, video: true }, function (stream) {
    video.mozSrcObject = stream;
    video.play();
    streamToAttach = stream;
}, function(error) {throw 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.

Offerer

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.

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) {
    peerConnection.setLocalDescription(sessionDescription);

    // POST-Offer-SDP-For-Other-Peer(sessionDescription.sdp, sessionDescription.type);

}, null, { 'mandatory': { 'OfferToReceiveAudio': true, 'OfferToReceiveVideo': true } });

Answerer

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:

setRemoteDescription!

peerConnection.setRemoteDescription(new RTCSessionDescription(offerSDP));

And to createAnswer...

peerConnection.createAnswer(function (sessionDescription) {
    peerConnection.setLocalDescription(sessionDescription);
    
    // POST-answer-SDP-back-to-Offerer(sessionDescription.sdp, sessionDescription.type);

}, null, { 'mandatory': { 'OfferToReceiveAudio': true, 'OfferToReceiveVideo': true } });

Offerer received answer sdp from answerer

setRemoteDescription!

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;
    
    waitUntilRemoteStreamStartsFlowing();
}
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);
}
Are you interested in a "more" simple full-fledged guide? Read this document.

Latest Updates

Feedback

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