Andi Smith

Introduction to getUserMedia

It's been a while since my last blog post, but I've actually been working on a number of exciting things in the last couple of months, so I'm going to take this opportunity to write about one of them - video/audio capture.

For a long time in the "Flash vs HTML5″ comparison arguments, one advantage Flash had was the ability to capture audio and video from the users computer. With upcoming browser releases, it is now possible to do this with JavaScript and the HTML5 video element, and its very simple to do. Unfortunately, audio doesn't work through the <audio> element at the time of writing, but video does - so let's use that!

Implementation

Firstly you'll need a browser that supports getUserMedia. Currently this list is Chrome Canary 18+ (turned on from about:flags) and Opera 12+ - although it will be Firefox nightly any minute now. You'll also need a machine that has a webcam and microphone, which should be any laptop nowadays.

On your HTML page, you need to include an empty <video> element. This will be used to show the feed from the video stream.

Due to the joy of vendor prefixes, we need to make sure we're referencing getUserMedia correctly. This quick shim helps us out:

navigator.getUserMedia || (navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia);

Note, I haven't left out the Opera prefix because I hate Opera (I don't) - but instead because Opera have implemented getUserMedia unprefixed.

Checking for Browser Support

The next step is to check the browser we're using has an implementation of getUserMedia and if it does, request a video and audio stream.

if (navigator.getUserMedia) {
  navigator.getUserMedia({video: true, audio: true, toString : function() {
      return "video,audio";
    }
  }, onSuccess, onError);
} else {
    // getUserMedia is not supported in this browser.
}

We pass an the object with video and audio set to true ({ video: true, audio: true }) to tell the browser we wish to capture both video and audio, but we could set either of these to false to only capture one (when audio works, that is). Unfortunately before Chrome Canary 20, Chrome required a string for this parameter so the included toString function hack is actually a way around this (credit to @agektmr).

The next two parameters are the function to call when getUserMedia is successful, and what to call when there is an error (such as the user declines the invitation to capture video and audio). So, our next step is to write these functions!

Handling Success

function onSuccess(stream) {

  var source;

  if (window.webkitURL) {
    source = window.webkitURL.createObjectURL(stream);
  } else {
    source = stream; // Opera and Firefox
  }

  var video = document.querySelector('video');
  video.autoplay = true;
  video.src = source;

}

A successful connection provides us with a stream object. Different browsers have different implementations of this - Opera and Firefox set this directly to the stream object, while WebKit provides a Blob URL.

We then need to tell our <video> element to autoplay; set the source and we have written our success function.

Handling Failure

An error may occur in our request such as if the user denies us permission to capture their video, so we need to create an error function that alerts the user to this (you could print something out to the screen, or use an alert). Once that's done, we're good to go!

See Yourself!

Load your page in your favourite browser - you'll need to set it up to run on a HTTP server as permissions won't be requested from the file protocol - and your page should ask for you to share your webcam and microphone. Hit accept, and you should hopefully see a face prettier than mine.

Not very pretty photo of Andi

I've created a really simple demo if you'd like to play and poke around with the code.