Tutorial #35
getUserMedia #1 - Camera Access Advanced   2013-12-31
Translations   Cz

Introduction

HTML5 includes an important and exciting new feature that allows the browser to access the Microphone and Camera on your device - Navigator.getUserMedia.

getUserMedia is not yet implemented in all browsers but this will change over time and I will update the following status message accordingly...

As of December 2013, getUserMedia is only supported in Google Chrome and Mozilla Firefox browsers.

There are so many potential uses for this technology - from fun things like taking your own photo and applying filters, to more serious Audio Recording, Speech Recognition and Video Conferencing.

This is the first of several tutorials that use getUserMedia. Later tutorials will integrate it with the Web Audio API for audio recording, etc. This first one shows how to access the Camera and take snapshots from the video stream.

The demo shows two windows - live video in the top one and a static photo captured from that feed.

Demo 1 screenshot for this tutorial


Step by Step

1: The Demo page initially has two blank rectangles and three buttons.

Image 1 for this tutorial

2: When you click the Start Video your browser will request access to your camera. In Google Chrome you will see a bar like this, with Deny and Allow buttons on the right hand side.

Image 2 for this tutorial

In Mozilla Firefox you will see a dialog like this. Clicking Share Selected Device allows access.

Image 3 for this tutorial

3: After about a second you should see a live video feed from your webcam in the top window. Both the video window, and the one below it, will resize to the width specified in the script.

Image 4 for this tutorial

4: Click Capture Photo any time you want to grab a still image from the video feed.

5: Stop Video stops the video feed and disables the camera. You can start and stop the video multiple times.


Understanding the Code

The code has three parts - the HTML block contains a video, which is initially empty, three buttons and a canvas element, also initially empty.

The style block places the elements in the center of the page and draws borders around them so we can see them when the page loads.

The script uses jQuery to simplify some of the code, so you need to load this library before doing anything.

Because getUserMedia is not fully supported, the main browser vendors prefix the function with webkit, moz, etc. The hack at the start of the script enables it to run on more than one browser.

The script defines a few global variables to use throughout the script, and then calls the ready function when the page has finished loading. This is the standard layout for many of the scripts on this web site.

The script now defines the callback functions for the three buttons when they are clicked.


The Start Video button callback is what calls navigator.mozGetUserMedia and starts up the video camera feed.

navigator.getUserMedia takes three arguments. The first is a hash that specifies, in this example, that we want to access the video source, but not the audio source.

The second is a function that is called if getUserMedia suceeds, with stream, representing the input video stream, being passed to it.

This function connects the stream to the src of the video object. This varies slightly between Firefox and Chrome. Firefox connects it to the mozSrcObject attribute. Chrome connects it to the src attribute. The url.createObjectURL(stream) call handles the stream as a JavaScript Blob - a data structure that I'm going to skip over in this tutorial, for the sake of clarity.

The stream is copied into the global variable mediaStream, for use elsewhere. Finally video.play() begins playing the live video feed from the device's camera in the <video> element that we created in the html block.

The third argument is called if an error occurs during set up of the video stream.

            navigator.getUserMedia(
                {
                  video: true,
                  audio: false
                },
                function(stream) {
                  if (navigator.mozGetUserMedia) {
                    video.mozSrcObject = stream;
                  } else {
                    var url = window.URL || window.webkitURL;
                    video.src = url ? url.createObjectURL(stream) : stream;
                  }
                  mediaStream = stream;
                  video.play();
                },
                function(error) {
                  console.log("ERROR: " + error);
                }
            );

Because the dimensions of a video source can vary between devices, and because we want to control the size of the playback window, we need to resize our video and canvas elements. But we can't get these dimensions until the video source is loaded and ready to play...

We handle this by defining an event handler on the video element - $("video").on('canplay', function(e) { ...}. The canplay event is fired when the video is loaded and can be played. The first time this happens, this callback gets the videoHeight and videoWidth attributes from the feed and uses them to scale the output windows accordingly.

In Firefox I need to scale the canvas element in the Capture Button callback for some reason - not sure why.


At this point there should be live video streaming to the video element and there should be some indicator in the browser tab, and by the camera itself, that shows that the camera is activated.

This will stay on as long as that page is open in your browser, which I think is too intrusive, so I always include a way to stop the video stream. The Stop Button callback simply calls the stop function on the mediaStream object that we created earlier. The video is stopped but the final frame remains in the video window.

The third button allows us to capture still images from the video feed whenever we click the Capture Photo button. This uses the drawImage function in the canvas API which can grab data from one of several sources, including the video element. We simply call that function with the canvas dimensions and it grabs the static image for us - a very nice, simple interface.



More Information

Mozilla documentation for Navigator.getUserMedia

Mozilla tutorial on Web Cam Access

getUserMedia Tutorial by Ian Devlin


Code for this Tutorial


Share this tutorial


Translations


Related Tutorials

6 : Play an Audio file using JavaScript   (Intermediate)

36 : getUserMedia #2 - Microphone Access   (Advanced)


Comment on this Tutorial


comments powered by Disqus