Accessing the Device Camera with getUserMedia

blogVideo

One of the funnest technologies to come to web browsers in the last couple years is the ability to access the webcam and microphone without the need for a third party plugin. When you combine these native media streams with the new CSS3 filters you have a recipe for awsomeness.

In this blog post you are going to learn how to access the device camera using getUserMedia and stream this input into a <video> element. To finish up you will play around with using CSS3 filters to add cool effects to the video.

Browser Support for getUserMedia

browser-support

Before we start it’s worth taking a look at browser support. Support for getUserMedia has been around in desktop browsers for a little while now.

Google Chrome (stable) has supported getUserMedia since v24. However the API is currently still prefixed as webkitGetUserMedia.

Firefox has support for the API through mozGetUserMedia. You may need to enable media support though. To do this go to about:config and toggle the media.navigator.enabled option to true.

Opera supports the unprefixed getUserMedia function.

Unfortunately IE and Safari don’t currently support getUserMedia.

For more detailed information on browser support check out the compatibility table on caniuse.com

Setting Up The Demo

Lets dive in and create a demo so that you can see how to use getUserMedia.

First you need to create a HTML file for your markup. Create a new file called index.html and save it in a folder that is accessible from your local development server.


Note: You cannot use getUserMedia on web pages served using file:// URLs.


Copy the following code into your index.html file. This will setup a basic web page with a <video> element and a <div> that will be used for styling purposes.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>HTML5 Demo: getUserMedia (Treehouse Blog)</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div id="video-container">
    <video id="camera-stream" width="500" autoplay></video>
  </div>
  <script src="script.js"></script>
</body>
</html>

Pro Tip: Adding a controls attribute to the video will allow you to pause the video stream and go fullscreen.


Now create a new stylesheet called style.css and save it in the same folder as your index.html file. Copy the following CSS code into your new stylesheet.

body {
  background: #F7F7F7;
  margin: 0;
  padding: 0;
}

#video-container {
  margin: 2em auto 0;
  width: 500px;
  padding: 2em;
  background: white;
  -webkit-box-shadow: 0 1px 10px #D9D9D9;
  -moz-box-shadow: 0 1px 10px #D9D9D9;
  -ms-box-shadow: 0 1px 10px #D9D9D9;
  -o-box-shadow: 0 1px 10px #D9D9D9;
  box-shadow: 0 1px 10px #D9D9D9;
}

Finally you need to setup a JavaScript file that will contain the code used to access the camera. Name this file script.js and save it in the same folder as your other assets. The code below will alias the vendor prefixed versions of getUserMedia so that you only need to call navigator.getUserMedia once rather than having to call of the vendor prefixed versions seperately in order to get your demo working across browsers.

window.onload = function() {

  // Normalize the various vendor prefixed versions of getUserMedia.
  navigator.getUserMedia = (navigator.getUserMedia ||
                            navigator.webkitGetUserMedia ||
                            navigator.mozGetUserMedia || 
                            navigator.msGetUserMedia);

}

Accessing The Camera

Now that you have all of your assets setup it’s time to take a look at getUserMedia in more detail.

The getUserMedia function takes three parameters:

  • constraints – This should be an object that specifies which media streams you would like to access. For example, to get both video and audio you would use: { video: true, audio: true }
  • successCallback – A function that will be called if the media stream is successfully loaded. The function will be passed a LocalMediaStream object.
  • errorCallback (optional) – A function that will be called if the media stream cannot be loaded.

Copy the following code into your script.js file, just inside the last curly brace.

// Check that the browser supports getUserMedia.
// If it doesn't show an alert, otherwise continue.
if (navigator.getUserMedia) {
  // Request the camera.
  navigator.getUserMedia(
    // Constraints
    {
      video: true
    },

    // Success Callback
    function(localMediaStream) {

    },

    // Error Callback
    function(err) {
      // Log the error to the console.
      console.log('The following error occurred when trying to use getUserMedia: ' + err);
    }
  );

} else {
  alert('Sorry, your browser does not support getUserMedia');
}

This code first does a check to see if the getUserMedia function is available in the browser. If it’s not it will show an alert to the user.

Once it has been established that the browser supports getUserMedia we issue the function call, passing in a constraints object that specifies we want a video stream; a callback function; and an error handler that will log any errors to the console.

getUserMedia Permissions Dialog

getUserMedia Permissions Dialog

When the function is called the user will be presented with a permissions dialog (like the one in the image above) giving them the ability to allow or deny access to the camera. This is a very important privacy feature which stops websites from being able to spy on users without their knowledge.

Hooking Up The Video Stream

The final thing to do in order to get your video stream working is to hook up the LocalMediaStream object to the <video> element in your HTML markup.


Note: The LocalMediaStream object is passed into the success callback through the  localMediaStream parameter you specified in the previous section.


Add the following code to the success callback in your getUserMedia call.

// Get a reference to the video element on the page.
var vid = document.getElementById('camera-stream');

// Create an object URL for the video stream and use this 
// to set the video source.
vid.src = window.URL.createObjectURL(localMediaStream);

Here you first get a reference to the <video> element on your web page. You then generate an object URL for the LocalMediaStream provided by getUserMedia and use this URL as the src for the video. You can use an object URL just like you would any other URL.

Now if you load up your demo page and accept the permissions dialog you should see the video feed from your camera being displayed on the page, as shown in the figure below.

getusermedia-video

Congratulations! You now know how to access the webcam without using any third-party plugins. It’s really not as hard as you might have thought.

You could stop here, but if you’re feeling a little adventurous, continue on to see how you can use CSS3 filters to add effects to the video stream.

Adding Effects with CSS3 Filters

CSS3 Filter Effects

CSS3 Filter Effects

CSS3 Filters allow you to easily add effects like grayscale, blur and sepia to your video stream. This works by using the -webkit-filter CSS rule directly on the <video> element on your web page. It’s super easy so lets give it a go!

Add the following CSS code to your style.css file. This will add a sepia effect to the video stream.

#camera-stream {
  -webkit-filter: sepia(1);
}

Now if you reload the page you should the sepia effect on the video. Pretty nifty!

Here are some other CSS3 filters for you to play around with.

-webkit-filter: blur(3px);
-webkit-filter: grayscale(1);
-webkit-filter: sepia(1);
-webkit-filter: brightness(2.5);
-webkit-filter: contrast(5);
-webkit-filter: hue-rotate(125deg);
-webkit-filter: invert(1);
-webkit-filter: saturate(3);
-webkit-filter: opacity(0.3);

Summary

I hope you’ve had as much fun playing around with getUserMedia as I did when I was writing this article!

Being able to access device hardware like the webcam and microphone without the need for third-party plugins is a big step forward for the web. There are already a number of web applications that are taking advantage of this emerging technology and I’m excited to see what developers are going to do with it in the future.

How do you plan to use getUserMedia in your projects?

Free Workshops

Watch one of our expert, full-length teaching videos. Choose from either HTML, CSS or Wordpress.

Start learning

Comments

42 comments on “Accessing the Device Camera with getUserMedia

  1. Nice! That is really cool! I don’t have any use for this other than to play with it and make something for fun. It’s good to know though!

  2. Hi Matt! Amazing stuff! Really amazing! I have been a big fan of HTML5. However, can you just give me starting point on how to proceed if I want to upload this video on server in real time?

    • My initial thought would be to use websockets to create a bi-directional connection between the browser and the server and then stream camera input through this connection.
      You might also want to look into WebRTC.

  3. Hi, this article is very nice, i checked out this example, it works, but it shows my video stream mirrored horizontal, how can i fix it?

  4. Matt, would this work on ANY mobile device that runs Chrome (for example)? I run a site that currently uses Flash to capture video and audio from users but need to make the jump something that tablet users can use. The advice I’ve had so far is to develop an app as HTML5 is too wobbly when it comes to camera/mic access but I’d be interested in your view. Thanks.

  5. hi Matt, I probe in tablet and I have this message: getUserMedia() not support in your browser. I installed in my tablet google chrome how I can resolve this problem for tablet?

  6. I must be missing something.. after spending long time to get a browser that supports getUserMedia, i get the page appearing as expected, with an empty box for video. the request to authorize video capture does not show.

    Can someone help here?

  7. Nice article!
    Do you think it would be possible to process the captured media for face detection and set up some kind of interaction based on the head tilt? That processing, could it be done in JS or it would need to be on server side?
    Thank you veru much.

  8. Hi Matt, as a newbie to HTML5 and Javascript, I could follow your post easily as it’s extremely apprehensible. I’m glad to get the webcam feed along with the audio. But, I’ve got a query- how do I record and play the video (which can possibly be used later)? As of now, it’s just taking the feed from the webcam. Please help.
    Thanks.

  9. Good Article! Matt can I capture and store audio and video both in one media file like mp4, webm, etc…?

  10. This is fantastic! Thanks so much for posting this. Does this also work with just photos? I need to be able to take a photo with a device camera within a web based app I am building. Would you just reference ?

  11. Nice tutorial! Do you know why the css styles are missing when I capture an image using ctx.drawImage ?

  12. Hey Matt,

    I am very new to HTML5 and I have to built something similar for a client but for some reason I am not getting this right. can you help me with this? http://rbbiapps.com/test/camera/index2.html.. The idea would is to upload the pic/video to a server owned by the client. Is this possible?

    Thank you

  13. Hello Matt, great article, thanks! I have a question regarding CSS and alerting the user to the allow button. Is there a way to detect that the chrome prompt has been activated and then cover the screen with a dimmed out DIV that has one arrow pointing to the allow button. I have on many occasions had human error not understand where the allow button is.. this is really a usability query. Any ideas on how to achieve this?

    • Hi Josef,

      getUserMedia includes success and error callbacks so you could display the shaded div just before your call to getUserMedia and then remove this overlay in the success/error callbacks.

      Chrome and Firefox will ask the user for permission every time the page is loaded.

      Hope this helps! :)

      • Thanks @mattantwest:disqus! I solved it, and now have the overlay translucent div working nicely. I am planning to package this up as an independent widget and hopefully put it up on github, when I get a moment.

  14. Hey MAtt, this is an awesome post..thanks a lot for this help..
    now i am writing a streaming application on a mobile device but using the javascript libraries.
    i see here that you are accessing the front camera.
    i wanted to access the back camera..
    how can i achieve that?any help or pointers regarding the same?

  15. Great tutorial. Is there any way to capture the video for a pre-determined time and upload to the server?

  16. Hi @Matt,

    do you know is there a way for receiving video to be analyzed and converted into a mathematical representation of movements into points for example.. ?

    This would be like wireframe the person that camera capture and then save the movements in points straam… :(