Lights, Camera, Action!


So You Want to Access Your Webcam from Javascript?

Web Real-Time Communications or WebRTC is an exciting new HTML5 technology that not only gives JavaScript the ability to do peer-to-peer (P2P) audio/video conferencing and P2P data communications between browsers, it also lets you have programmatic access to attached cameras and microphones. Prior to WebRTC you had to rely on a browser plugin such as Adobe Flash to be able to do similar things. But recently there has been a big push to add these capabilites as intrinsic features to web browsers with Google really leading the charge and through standardization efforts by the W3C WebRTC working group. It is a brave new world in that only some browsers have added WebRTC support and even those that do can have subtle (and some not so subtle) differences in both interface and implementation. But more and more you’re seeing real applications appearing that are using WebRTC in very cool and interesting ways. One great example of WebRTC in action is a PhotoBooth-like app called WebCam Toy. This application should give you a sense of the possibilites that WebRTC is opening up.

In the rest of this article, I’m going to walk you through the minimum code needed to get your webcam to display video in your browser. The latest versions of Chrome or Firefox are recommended for running the code included in this article and for experimenting with WebRTC. If you already have one of these browsers you can try out my example.

So lets get started…

WebRTC defines the getUserMedia method on the top level navigator object as the mechanism for getting access to an attached camera/microphone. Since WebRTC is still in a state of flux, we do have to shim a number of vendor prefixed variants to increase the portability of our code as follows:


// Alias the vendor prefixed variants of getUserMedia 
// so we can access them via navigator.getUserMedia
navigator.getUserMedia = navigator.getUserMedia ||  
    navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||    
    navigator.msGetUserMedia;

After checking to make sure that the getUserMedia method is available it can be invoked as follows:


if (navigator.getUserMedia) {
    // Call the getUserMedia method here
    navigator.getUserMedia({video: true}, successCallback, 
        failureCallback);
}

This will cause the browser to prompt the user for permission to access an attached camera. Note: This is done for security reasons so that a random website can’t access your camera without your permission. If there is an attached camera and the user grants access then the function passed in as successCallback in the above example will get invoked; otherwise the failureCallback function will be called. Note: Unfortunately at the time of this writing you can not determine whether the failure was due to the lack of an attached camera or whether the user denied access. On success, the successCallback function will be passed a stream object that be used to stream the video data from the camera to the video object that cooresponds to our video tag.


// Alias the vendor prefixed variants of the URL object 
// so that we can access them via window.URL
window.URL = window.URL || 
    window.webkitURL || window.mozURL || window.msURL;

// This function will be called if a webcam is available 
// and the user has granted access for the web 
// application to use it.
function successCallback(stream) {
    if (video.mozSrcObject !== undefined) {
        video.mozSrcObject = stream;
    } else {
        video.src = (window.URL && 
            window.URL.createObjectURL(stream)) ||
            stream;
    };
    video.play();
}

WebRTC leverages the HTML5 <video> tag as the DOM element for rendering video content from your camera. If you look at the example you’ll see that we included the video tag with no attributes in the body of our document.


<video/>

Now that we have a reference to the video stream. We need to connect it up to the video object defined by the video tag so we can see the video. Things get a little messy here because of some interface differences between browsers. Most browsers allow you to set the src property to a URL generated from the createObjectURL method but Firefox defines a different property called mozSrcObject that allows you to pass the stream object in directly. The code snippet shown above shows how to deal with this minor inconvenience. Once we’ve hooked up the stream to the video object, we simply have to call play on the video object to start rendering the video.

That’s all there is to it to get the output of your camera working in your browser with WebRTC. Very very cool…

All in all WebRTC is off to a great start for further enhancing the web. But there are a number of unfortunate and annoying limitations that hopefully get addressed in future enhancements to WebRTC. Currently you can’t enumerate the set of supported resolutions for a given camera and its not really possibly to cleanly probe for supported resolutions. However if you do know the set of resolutions supported by your camera you can specify them by passing in additional constraints to the getUserMedia method. As an example:


navigator.getUserMedia({video: {mandatory: {minWidth: 1024, 
    minHeight: 768 }}}, 
    successCallback, failureCallback);

Again you can get the full source code for this article here and I hope you have a great time exploring the new frontier that is WebRTC!

Join my mailing list to get my tips, tricks and articles delivered straight to your inbox.

 

Leave a Comment