Use HTML5 to capture webcam video

Discover how to use JavaScript and HTML5 to cut out third-party applications and Flash components for webcam use


HTML5 is fast becoming the developer tool of choice, moving away from heavy Flash apps, and switching to a fast, lightweight solution. A new generation of web interaction is coming, where users are able to play full games in their browser without a hint of Flash.

Typically, interacting with a user’s webcam required a third-party application or a Flash component, but now we can access this data via the cutting-edge HTML5 technology known as getUserMedia. As with anything this new and exciting there are bound to be some teething problems, the main one is the cross-browser compatibility of getUserMedia. It is recommended that you use the latest version of Chrome as most other browsers simply won’t work. We’ll cover a bit on using Flash as a fallback to HTML5, but it is probably wise to hold off putting this technology into a production environment until it becomes standardised.
Another problem with getUserMedia is that no browsers currently support the use of audio. This is fine for this tutorial as we will only be covering images, but worth noting if you want to deviate from the tutorial steps.


HTML page setup

Before we get into any coding, it is worth noting that the DOCTYPE for an HTML5 page is different from a standard page. There is a lot less information that goes into it as HTML5-compatible browsers do not require as much information. Create a new HTML document and replace the standard DOCTYPE information with the following.

01 &lt!DOCTYPE html>
 002 &lthead>
 003 &lttitle>WebCam Access&lt/title>
 004 &lt/head>
 006 &ltbody>
 007 &lt/body>
 008 &lt/html>

The video tag

Go into the body section of your HTML document and add the following video tag. The video tag is new to HTML5 and allows us to easily embed video into a page, simply by adding a source. In this case we do not need a source, but can just add an autoplay element.

001  < video autoplay>< /video>

Link to a JS file

We’ll create our webcam access script in a separate JS file. This allows us to use it on multiple sites and pages if need be. Add the following code underneath our video tag. Go ahead and create a new JS document called ‘webcam.js’ and save it into the same directory as your index file.

001< script type="text/javascript" src="webcam.js">< /script>

Checking browser capabilities

The first thing we will do in our webcam.js file is check to make sure that the browser used is capable of calling the getUserMedia command. This can be done with the following JavaScript code. Everything we do from here on in will be placed inside this if statement.

001 if(navigator.webkitGetUserMedia!=null) {
 003 } 

Requesting feeds

At this point we need to set some options that we will use further down the line. As mentioned in the introduction to this tutorial, there are problems accessing audio via a webcam. However, we will set audio to true for future use. Add the following code within the previous if statement.

001 var options = { 
 002 video:true, 
 003 audio:true  0
 04 };

Calling getUserMedia

It’s now time to make a call to getUserMedia from within our webcam.js file. Place the following code underneath the closing bracket of the previous step, but before the closing bracket of our if statement. This code will call getUserMedia and pass all of our required options through.

001 navigator.webkitGetUserMedia(options, 
 003 );

Add streaming function

Within the brackets of the previous step, add the following function. This function, when called, will look for our video tag and create an object URL based on it. This object URL will be used at various points in our code further on. Remember to place this within our if statement still.

001 function(stream) { 
 002 var video = document. querySelector('video'); 
 003 video.src = window.webkitURL. createObjectURL(stream); 
 004 }, 

Error handling

The next step is to add an error statement that will write data to console log if there is a problem with getUserMedia. Add the following underneath our previous step, still within the navigator.webkitGetUser Media brackets. Now we will be able to debug our code via the console if there is a problem.

001 function(e) { 
 002 console.log("There was a problem with webkitGetUserMedia"); 
 003 } 

Running our code

It’s finally time to run our code! Open the latest version of Google Chrome and navigate to your working directory. The first thing you will notice is a notification in your browser window, asking for permission to access the webcam. Click Allow and you should see a livestream from your webcam.

In-browser options

You may also notice that the notification bar in Google Chrome has an option drop-down menu. Opening this will allow a user to select which webcam the application has access to. Sound options are also displayed here, even though we cannot use them at this stage. If you have multiple cameras connected to your machine, try out the different options.

Handling a denied request

If a user clicks Deny in the previous step, our code will fail and we will have no way of informing them why. The easiest thing to do is to create an alert event that is tied into the error console. This can be done by amending our console.log section to include the following additional line.

001 function(e) { 
 002 alert("You need to allow webcam access  for this page");
 003 console.log("There was a problem with webkitGetUserMedia"); 
 004 } 

Adding a capture button

Now we need a way to capture a still image from our webcam feed. Go back to your index.html file. Adding the following form element underneath our video tag will give us the means to capture a still image using some more JavaScript and a canvas element that we will add over the next few steps.

001 < form>< input id="capture" type="button" value="Smile!" />< /form>

Adding a canvas

Canvas is another new element to HTML5. Adding the following tag underneath the previous step will give us a place to display the captured image once it has been processed by the JavaScript. You can set the width and height to anything you like, but remember that not all webcams are HD and may produce bad image quality.

001 < canvas id="canvas" width="300" height="300">< /canvas>

Link button to JavaScript

Adding the following script code underneath the previous step will link our button to our JavaScript. The code listens out for a click on a button with the ID capture. If you have multiple buttons on your page that do different things, ensure all IDs are unique. This code also determines the video source and canvas output.

001< script type="text/javascript" language="JavaScript">// < ![CDATA[  document.getElementById('capture').onclick =  function() {  002 var video = document. querySelector('video');  003 var canvas = document. getElementById('canvas');  004 }  005 // ]]>< /script>

Outputting an image

Adding two more lines of code to the previous step will draw the captured image into our canvas. As you can see, the canvas can be used for both 2D and 3D elements. As we are working with images, we set this to 2D. Running the code now will show a captured image in our canvas.

001 document.getElementById('capture').
 onclick = function() { 
 002 var video = document.
 003 var canvas = document.
 004 var ctx = canvas.getContext('2d'); 
 005 ctx.drawImage(video,0,0); 
 006 }

Non-cropped images

The eagle-eyed among you may have noticed that the image we produced in the previous step was very heavily cropped. To avoid this and to display a full
size image, we simply have to pass two more variables into our ctx.drawImage command. By passing a width and a height we are able to scale our image to the canvas size, rather than capturing the top-left section
of the image.

001 ctx.drawImage(video,0,0,300,250);

Getting image data

What else can we do with our image? Well, we can modify the pixel data with code. An example of this is replacing all colour with greyscale. To do this we first need to interpret the pixel data with the following line.

001 var data = ctx.getImageData(0,0,canvas.width,canvas.height);

Creating a loop

Now we have the pixel data of the image set as a variable, we can loop through and remove all colour. The following code bracket sets us up with a loop that will do just that. Add this within the onclick brackets underneath the previous step. The loop will stop once it reaches the image width and height.

001 for(n=0; n
 003 } 

Removing all colour

The following complete loop will take the red, green and blue channels and reduce the data value by 255. Those familiar with RGB values will know that any colour can be made using a combination of red, green and blue in 255 increments. Taking these all to 0 will produce a black and white image.

001 for(n=0; n002 var index = n*4; 
 003[index+0] = 255-data.
 004[index+1] = 255-data.
 005[index+2] = 255-data.
 006 }

Outputting the image

Now we have removed all colour, we can output our new black and white image. Placing this code outside of the loop will put the new pixel data back into the canvas, at this point you can specify a new canvas if you wish to keep the original, unedited capture.

001 ctx.putImageData(data,0,0); 

Flash fallback

As mentioned before, webcam access is only available in a select few browsers. To combat this we will use a jQuery fallback. Download the jQuery webcam plug-in from, copy the files to your working directory and add the following lines of code to the head section of your index.html file.

001< script type="text/javascript" src="">< /script>
 002< script type="text/javascript" src="jquery. webcam.min.js">< /script>

Add a flash version

Adding the following code under our video tag in the index.html file will display the Flash fallback. The correct way to do this would be to create two pages and do some level of browser detection. You would then have a Flash or HTML5 version depending on the capabilities of a user’s browser.

001 < div id="”webcam”">< /div>
 002 < a href="”JavaScript:webcam.">Smile!< /a>
 003< script type="text/javascript">// < ![CDATA[ 004 jQuery(“#webcam”).webcam({ 005 width: 320, 006 height: 240, 007 mode: “callback”, 008 swffile: “jscam.swf”, 009 }); 010 // ]]>< /script>