HTML5

HTML5 Webcam Tutorial

1. Introduction

In this article, we will look at how to capture images as well as video from user’s webcam. There have been several iterations to enable access to devices from JavaScript. Starting from special attributes for existing input tags to getUserMedia part of the WebRTC APIs. We will look at how to use these and leverage them for accessing devices, specifically, webcam from the browser.
 
 
 
 

2. Tools & Technologies

The toolset for the project that we are going to build is as follows:

  1. Nodejs v6.3.0
  2. Express
  3. Visual Studio Code IDE

We use Nodejs and the express module to quickly spin up a bare minimum Web Server to serve our HTML files. I have used the Integrated Development Environment that I’m most comfortable with, i.e., Visual Studio Code.

3. Project Layout

Our project has the layout as shown below:

Project Layout

css folder
This folder stores our css files that we create and use for the UI of the project.
js folder
This folder has the client side JavaScript files we write for this project.
index.html
This is our main landing page with all the HTML markup.
index.js
This is our server side JavaScript file where our barebones web server resides and is the starting point of the application.

4. Capture Webcam

To capture the video from the Webcam we will use getUserMedia HTML5 API. Firstly, we stream the Webcam video to a video element on our page. This does require permission from the user and as soon as we try to access the Webcam the user is asked to approve the same. We also use the constraints object to modify the default video from the Webcam.
To begin with, we place a video Html tag in our index.html page. This is where we will show the video feed from the Webcam. The markup looks like below:

index.html

<video height="480px" width="640px" id="webcamfeed" autoplay controls></video>

Two things to note in the above markup is the autoplay and controls attributes. The autoplay causes the video to start playing once we wire things up like you will see below. The controls attribute specifies that video controls be displayed like play/pause buttons.
Now that we have the markup in place let us look at how to request access to the webcam and wire it to our video element. We use the getUserMedia API call to request access on the click of the capturewebcam button like below:

html5.webcam.demo.js

var captureWebcam = document.getElementById("capturewebcam");
function getUserMedia(){
    if(navigator.getUserMedia){
        navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia
        ||navigator.mozGetUserMedia||navigator.msGetUserMedia;

    }else{
        navigator.getUserMedia=navigator.mediaDevices.getUserMedia;
    }
    return navigator.getUserMedia;
}

captureWebcam.addEventListener("click", function(){
    var media = getUserMedia();
    if(media){
        navigator.getUserMedia({video: { width: 640, height: 480}, audio: false}, function(stream){
            
            videoElement.src = window.URL.createObjectURL(stream);
            
        }, function(error){
            //Catch errors and print to the console
            console.log("There was an error in GetUserMedia!!!");
            console.log(error);
        });
    }
});

We set the src attribute of the video element to an ObjectURL created from the stream object returned by the call to getUserMedia attribute. The URL.createObjectURL() static method creates a DOM containing the URL of the BLOB object passed to it, that is the stream object here from getUserMedia API call. The result would look like below, with video from your Webcam, of course.

5. Take a Snap

Let us take a look to an interesting feature where we allow the user to take snapshots from the Webcam. To start with this we will add a canvas element to our HTML. This element will host the snap captured on click of a button by the user. The HTML markup we need to add looks like below:

Screenshot – Index.html

index.html

<canvas height="480px" width="640px" id="snap"></canvas>

To take a snap we will get the 2d context of the canvas element which allows us to draw an image onto it. Once we have the context all we need to do is to call drawImage method on the context and pass it the video element that is displaying the video from the webcam. We need to add the following:

html5.webcam.demo.js

var videoElement = document.getElementById("webcamfeed");
var captureWebcam = document.getElementById("capturewebcam");
var captureSnap = document.getElementById("takesnap");
var canvas = document.getElementById("snap");

captureSnap.addEventListener("click", function(){
    var context = canvas.getContext('2d');
    context.drawImage(videoElement, 0, 0, 640, 480, 0, 0, 640, 480);
});

6. Applying Filters

Let us do something even more interesting with the snapshots that we have captured. Allow users to apply css filters, which are similar to the filters available in image editing software packages, to the snapshots captured from webcam. Some of the filters that we will look at are: Blur, Sepia and GrayScale.
To start with this implementation we add a select tag and a checkbox markup to our HTML page. The checkbox will switch the filters on and off and the select tag would allow the user to switch between different filters. The markup we add looks like below:

index.html

<input type="checkbox" id="enablefilters" >Enable Filters</input>
<select id="filterName">
    <option value="blur">Blur</option>
    <option value="sepia">Sepia</option>
    <option value="grayscale">GrayScale</option>
    <option value="saturate">Saturate</option>
    <option value="brightness">Brightness</option>
</select>

Also, we create specific CSS classes for applying the above filters. Although we can apply more than one filter function at a time but to keep things simple for the purpose of this tutorial we will only apply one filter at a time. We create the following css classes in our css file:

html5.webcam.demo.css

.blur{
    filter: blur(30px);
}
.grayscale{
    filter: grayscale(100%);
}
.sepia{
    filter: sepia(60%);
}
.saturate{
    filter: saturate(60%);
}
.brightness{
    filter: brightness(150%);
}

Now to finally apply these classes when the “apply filters” checkbox is checked or selection is changed in the filters dropdown we write the following JavaScript in our JS file:

html5.webcam.demo.js

var canvas = document.getElementById("snap");
var filters = document.getElementById("enablefilters");
var filterName = document.getElementById("filterName");

filters.addEventListener("change", function(evt){
    applyFilter(filterName.value);
});
filterName.addEventListener("change", function(evt){
    applyFilter(filterName.value);
});
function applyFilter(fName){
    if(filters.checked){
        canvas.className = fName;
    } else {
        canvas.className = "";
    }
}

Now we are able to apply or remove filters to the captured image or snapshot in our canvas element. We can also switch between various types of filters using the filter dropdown. The complete index.html, html5.webcam.demo.css and html5.webcam.demo.js files look like below:

The below HTML page has standard HTML5 Doctype apart from some additional meta tags. The meta tag indicate to the client browser that the latest standards need to be used to render the contents of the page. The tag is needed specifically for IE browser. We have included our CSS file in the head section and our JavaScript file towards the end of the page as well.

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
        <title>WCG -- HTML5 Webcam Tutorial</title>
        <link rel="stylesheet" href="css/html5.webcam.demo.css" />
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
    <script src="https://www.webcodegeeks.com/wp-content/litespeed/localres/aHR0cHM6Ly9vc3MubWF4Y2RuLmNvbS8=html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://www.webcodegeeks.com/wp-content/litespeed/localres/aHR0cHM6Ly9vc3MubWF4Y2RuLmNvbS8=respond/1.4.2/respond.min.js"></script>
<![endif]-->
    </head>
    <body>
        <h1>WCG -- HTML5 Webcam Tutorial</h1>

        <video height="480px" width="640px" id="webcamfeed" autoplay controls></video>
        <canvas height="480px" width="640px" id="snap"></canvas>
        <input type="button" id="capturewebcam" value="Start Webcam"/>
        <input type="button" id="takesnap" value="Take Snap"/>
        <input type="checkbox" id="enablefilters" >Enable Filters</input>
        <select id="filterName">
            <option value="blur">Blur</option>
            <option value="sepia">Sepia</option>
            <option value="grayscale">GrayScale</option>
            <option value="saturate">Saturate</option>
            <option value="brightness">Brightness</option>
        </select>
<!--Our script-->
        <script src="js/html5.webcam.demo.js"></script>

    </body>
</html>

In the below complete CSS file there are two additional classes targeting the video and the canvas elements. These classes set the height and width of the two elements and initial background colors of the two.

html5.webcam.demo.css

video{
    display: inline-block;
    background-color:grey;
    height: 480px;
    width: 640px;
}
canvas{
    display:inline-block;
    background-color: lightgray;
    height: 480px;
    width: 640px;
}
.blur{
    filter: blur(30px);
}
.grayscale{
    filter: grayscale(100%);
}
.sepia{
    filter: sepia(60%);
}
.saturate{
    filter: saturate(60%);
}
.brightness{
    filter: brightness(150%);
}

In the JavaScript file below you will notice the function getUserMedia which is needed to insulate our code from API changes. The WebRTC APIs are a work in progress and have varying levels of support in different browser versions. Some browser versions support prefixed API methods and in some newer browsers the method has moved to the Navigator object’s mediaDevices property.

html5.webcam.demo.js

var videoElement = document.getElementById("webcamfeed");
var captureWebcam = document.getElementById("capturewebcam");
var captureSnap = document.getElementById("takesnap");
var canvas = document.getElementById("snap");
var filters = document.getElementById("enablefilters");
var filterName = document.getElementById("filterName");
function getUserMedia(){
    if(navigator.getUserMedia){
        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia
        || navigator.mozGetUserMedia || navigator.msGetUserMedia;

    } else {
        navigator.getUserMedia = navigator.mediaDevices.getUserMedia;
    }
    return navigator.getUserMedia;
}
captureWebcam.addEventListener("click", function(){
    var media = getUserMedia();
    if(media){
        navigator.getUserMedia({video: { width: 640, height: 480}, audio: false}, function(stream){

            videoElement.src = window.URL.createObjectURL(stream);

        }, function(error){
        //Catch errors and print to the console
        console.log("There was an error in GetUserMedia!!!");
        console.log(error);
        });
    }
});
captureSnap.addEventListener("click", function(){
    var context = canvas.getContext('2d');
    context.drawImage(videoElement, 0, 0, 640, 480, 0, 0, 640, 480) ;
});
filters.addEventListener("change", function(evt){
    applyFilter(filterName.value);
});
filterName.addEventListener("change", function(evt){
    applyFilter(filterName.value);
});
function applyFilter(fName){
    if(filters.checked){
        canvas.className = fName;
    } else {
        canvas.className = "";
    }
}

7. Run the Project

To run the project run the following commands at the root of the project:

>npm install

and

>node index.js

and then navigate to the URL http://localhost:8090/index.html

8. Download the Source Code

That was an example for HTML5 Webcam.

Download
You can download the full source code of this example here : WCG HTML5 Webcam Tutorial

Siddharth Seth

Siddharth is a Software Development Professional with a Master degree in Computer Applications from IGNOU. He has over 14 years of experience. And currently focused on Software Architecture, Cloud Computing, JavaScript Frameworks for Client and Server, Business Intelligence.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button