Welcome! (This field is for presenter notes and commentary.)
Press:
  • Space or ← / → to move around
  • Ctrl/Command / – or + to zoom in and out if slides don’t fit
  • N to show/hide speaker notes
  • H to highlight important elements in code snippets

Code up your own
video conference in HTML5


by Silvia Pfeiffer
Linux.conf.au, 28th January 2013, 10:40 - 11:25
Slide Template by HTML5 WOW
About me

@silviapfeiffer
  • W3C HTML WG co-editor
  • W3C and WHATWG video standards
  • HTML5 Accessibility Task Force
  • Google & Mozilla video accessibility contractor
  • Video research at CSIRO

WebRTC: Real-Time Communication between Browsers

WebRTC Website / WebRTC Spec
Video Conferencing is hard: you need
  • Wideband codecs (voice and video)
  • Echo cancellation
  • Automatic Gain Control
  • Noise reduction/suppression
  • Dynamic jitter buffers
  • Error concealment
  • Network Traversal
  • P2P protocols
  • Session setup

Take a deep breath and don't worry

Taking it step by step
  1. set up video on a Web page
    • <video> element
  2. access local devices: camera, microphone
    • MediaStream API
  3. display a/v from local or remote peer
    • createObjectURL
  4. connect to remote peers
    • Session setup
    • PeerConnection API

Plugin-free video conferencing in the browser!

Time for a demo
  1. Start up Google Chrome
  2. Go to http://apprtc.appspot.com.
  3. Share the resulting URL with a friend
  4. Source code from Google code
1. Set up an empty video on a Webpage
<video id="localvid" autoplay></video>
<video id="remotevid" autoplay></video>
    
2. Access local device and display: getUserMedia(), createObjectURL
<video id="sourcevid" autoplay></video>
<script>
  var video = document.getElementById('sourcevid');
  navigator.getUserMedia({audio: true, video: true}, success, error);
  function success(stream) {
      video.src = window.URL.createObjectURL(stream);
  }
</script>
Browser support for getUserMedia() and createObjectURL
    • v21+ native support
    • webkitGetUserMedia
    • v12+ native support
    • no prefix
    • v18 nightly
    • need to activate "media.navigator.enabled" in about:config
    • mozGetUserMedia, set video.mozSrcObject
    • prototype ActiveX/ browser plugin, 17th Jan
    • msGetUserMedia/getUserMedia
Privacy Alerts

Chrome permissions:

Opera privacyUI:

Firefox permissions:

Cool things to do with getUserMedia()

Face Detection

Photo Booth

Augmented Reality Slides

WebCam with effects

Xylophone

Many more Demos

Bring in the remote user
  1. Establish a local stream (DONE)
  2. Establish a connection: we need a protocol
  3. Add the remote stream to the local display: PeerConnection
Establish a connection
  • Signalling methods and protocols are not specified by WebRTC
  • Signalling needs:
    • Shared server: share my computer's IP address and port
    • Session setup / teardown
    • Media capabilities: codecs and resolutions negotiation
Create the signalling server: node.js and socket.io

Server: reflector.js

var server = require('http').createServer();
var app = server.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);
    });
});
Prepare the signalling channel
<script src="http://192.168.1.3:1337/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://192.168.1.3:1337/');
var channelReady = false;

socket.on('connect', onChannelOpened);

function onChannelOpened(evt) {
  channelReady = true;
}
Prepare the peer connection object

ICE = Interactive Connection Establishment

STUN = Session Traversal Utilities for NAT (give me my public IP address)

function createPeerConnection() {
  var pc_config = {"iceServers":[]};

  peerConn = new RTCPeerConnection(pc_config);

  peerConn.onicecandidate = function (evt) {
    socket.json.send({type: "candidate", evt.candidate});
  };

  peerConn.onaddstream = function (evt) {
    remotevid.src = window.URL.createObjectURL(evt.stream);
  };

  peerConn.addStream(localStream);
}

OK, we're almost there

Send connection offer
var mediaConstraints = {'mandatory': {
                        'OfferToReceiveAudio':true, 
                        'OfferToReceiveVideo':true }};

function setLocalAndSendMessage(sessionDescription) {
  peerConn.setLocalDescription(sessionDescription);
  socket.json.send(sessionDescription);
}

peerConn.createOffer(setLocalAndSendMessage,
                     errorCallback,
                     mediaConstraints);
Receive connection offer & reply
socket.on('message', onMessage);

function onMessage(evt) {
  if (evt.type === 'offer') {
    if (!started) {
      createPeerConnection();
      started = true;
    }
    peerConn.setRemoteDescription(new RTCSessionDescription(evt));
    peerConn.createAnswer(setLocalAndSendMessage,
                          errorCallback,
                          mediaConstraints);

  } else if (evt.type === 'answer' && started) {
    peerConn.setRemoteDescription(new RTCSessionDescription(evt));

  } else if (evt.type === 'candidate' && started) {
    var candidate = new RTCIceCandidate(evt.candidate);
    peerConn.addIceCandidate(candidate);
  }
}

Resulting Web Page
<video id="sourcevid" autoplay
  src="blob:http%3A//localhost/58436a28-df4a-4dd7-8678-3224e021585f">
</video>
<button type="button" onclick="startVideo();">Start video</button>
<button type="button" onclick="stopVideo();">Stop video</button>

<video id="remotevid" autoplay
  src="blob:http%3A//localhost/ee3fd875-ce9f-410c-9856-61e6fa18862d">
</video>
<button type="button" onclick="connect();">Connect</button>
<button type="button" onclick="hangUp();">Hang Up</button>

Putting it all together

Cool things to do with PeerConnection

Video Conference

WebMeeting

We Blend

Puzzlible

VoIP calls (SIP Client)

Outlook: record video

Using requestAnimantionFrame and canvas - better API TBD

Go out and play!

Silvia Pfeiffer
blog.gingertech.net
silviapfeiffer1@gmail.com
@silviapfeiffer
Slides: http://html5videoguide.net/presentations/LCA_2013_webrtc/