Webcam Video Capture in HTML5 and CSS3 filters

Webcam Video Capture in HTML5 and CSS3 filters

22 3531
Webcam Video Capture in HTML5 and CSS3 filters

Webcam Video Capture in HTML5 and CSS3 filters

As we know – HTML5 defines a new element called <video> for embedding video. Usually people use this element to embed a video into web page. It is very convenient. Because the <video> element is designed to be usable without any detection scripts. You can just specify multiple video files, and browsers that support HTML5 video will choose one based on what video formats they support. Now, let’s imagine that we can use the same element to access a user’s camera and microphone. Our article opens these boundaries. I’m going to show you how to capture a video from your webcam in HTML5, and even more, I will show you how to pass this video into <canvas> object, and even – how to apply custom CSS3 filters to our video.

Today we will create a script which will capture a video stream from our webcam (into <video> element), at the right of our <video> element I will put a <canvas> element, and we will transfer the video from the video object directly into the canvas object. I’m going to use a new HTML5 – navigator.getUserMedia(). This function gives access to a user’s camera and microphone. Also, before we start I would like to inform you that our result works well only in few browsers, this are Chrome (I recommend to use the latest version) and Opera (version 12 and higher). But, it is going to work in future versions of FireFox browser too.

Live Demo

Step 1. HTML

Our basic HTML markup does not contain a big deal, on the contrary – it is very easy:

index.html

<div class="warning"><h2>Native web camera streaming (getUserMedia) is not supported in this browser.</h2></div>
<div class="container">
    <h3>Current filter is: None</h3>
    <button>Click here to change video filter</button>
    <div style="clear:both"></div>
    <div class="col">
        <h2>HTML5 &lt;video&gt; object</h2>
        <video></video>
    </div>
    <div class="col">
        <h2>HTML5 &lt;canvas&gt; object</h2>
        <canvas width="600" height="450"></canvas>
    </div>
</div>

There are a warning message (for browsers that do not support this functionality), a <video> element and <canvas> element.

Step 2. CSS

As I told in the beginning of our tutorial – we are going to use CSS3 filters. It is the time to define all these CSS3 filters:

style.css

.grayscale{
    -webkit-filter:grayscale(1);
    -moz-filter:grayscale(1);
    -o-filter:grayscale(1);
    -ms-filter:grayscale(1);
    filter:grayscale(1);
}

.sepia{
    -webkit-filter:sepia(0.8);
    -moz-filter:sepia(0.8);
    -o-filter:sepia(0.8);
    -ms-filter:sepia(0.8);
    filter:sepia(0.8);
}

.blur{
    -webkit-filter:blur(3px);
    -moz-filter:blur(3px);
    -o-filter:blur(3px);
    -ms-filter:blur(3px);
    filter:blur(3px);
}

.brightness{
    -webkit-filter:brightness(0.3);
    -moz-filter:brightness(0.3);
    -o-filter:brightness(0.3);
    -ms-filter:brightness(0.3);
    filter:brightness(0.3);
}

.contrast{
    -webkit-filter:contrast(0.5);
    -moz-filter:contrast(0.5);
    -o-filter:contrast(0.5);
    -ms-filter:contrast(0.5);
    filter:contrast(0.5);
}

.hue-rotate{
    -webkit-filter:hue-rotate(90deg);
    -moz-filter:hue-rotate(90deg);
    -o-filter:hue-rotate(90deg);
    -ms-filter:hue-rotate(90deg);
    filter:hue-rotate(90deg);
}

.hue-rotate2{
    -webkit-filter:hue-rotate(180deg);
    -moz-filter:hue-rotate(180deg);
    -o-filter:hue-rotate(180deg);
    -ms-filter:hue-rotate(180deg);
    filter:hue-rotate(180deg);
}

.hue-rotate3{
    -webkit-filter:hue-rotate(270deg);
    -moz-filter:hue-rotate(270deg);
    -o-filter:hue-rotate(270deg);
    -ms-filter:hue-rotate(270deg);
    filter:hue-rotate(270deg);
}

.saturate{
    -webkit-filter:saturate(10);
    -moz-filter:saturate(10);
    -o-filter:saturate(10);
    -ms-filter:saturate(10);
    filter:saturate(10);
}

.invert{
    -webkit-filter:invert(1);
    -moz-filter:invert(1);
    -o-filter: invert(1);
    -ms-filter: invert(1);
    filter: invert(1);
}

As you can see – vendors prefixes are required. It gives possibility to use these filters in all major browsers.

Step 3. HTML5 JavaScript

Now, the most important step – html5, please create an empty script.js file and paste the next code:

script.js

// Main initialization
document.addEventListener('DOMContentLoaded', function() {

    // Global variables
    var video = document.querySelector('video');
    var audio, audioType;
    var canvas = document.querySelector('canvas');
    var context = canvas.getContext('2d');

    // Custom video filters
    var iFilter = 0;
    var filters = [
        'grayscale',
        'sepia',
        'blur',
        'brightness',
        'contrast',
        'hue-rotate',
        'hue-rotate2',
        'hue-rotate3',
        'saturate',
        'invert',
        'none'
    ];

    // Get the video stream from the camera with getUserMedia
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
        navigator.mozGetUserMedia || navigator.msGetUserMedia;

    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
    if (navigator.getUserMedia) {

        // Evoke getUserMedia function
        navigator.getUserMedia({video: true, audio: true}, onSuccessCallback, onErrorCallback);

        function onSuccessCallback(stream) {
            // Use the stream from the camera as the source of the video element
            video.src = window.URL.createObjectURL(stream) || stream;

            // Autoplay
            video.play();

            // HTML5 Audio
            audio = new Audio();
            audioType = getAudioType(audio);
            if (audioType) {
                audio.src = 'polaroid.' + audioType;
                audio.play();
            }
        }

        // Display an error
        function onErrorCallback(e) {
            var expl = 'An error occurred: [Reason: ' + e.code + ']';
            console.error(expl);
            alert(expl);
            return;
        }
    } else {
        document.querySelector('.container').style.visibility = 'hidden';
        document.querySelector('.warning').style.visibility = 'visible';
        return;
    }

    // Draw the video stream at the canvas object
    function drawVideoAtCanvas(obj, context) {
        window.setInterval(function() {
            context.drawImage(obj, 0, 0);
        }, 60);
    }

    // The canPlayType() function doesn’t return true or false. In recognition of how complex
    // formats are, the function returns a string: 'probably', 'maybe' or an empty string.
    function getAudioType(element) {
        if (element.canPlayType) {
            if (element.canPlayType('audio/mp4; codecs="mp4a.40.5"') !== '') {
                return('aac');
            } else if (element.canPlayType('audio/ogg; codecs="vorbis"') !== '') {
                return("ogg");
            }
        }
        return false;
    }

    // Add event listener for our video's Play function in order to produce video at the canvas
    video.addEventListener('play', function() {
        drawVideoAtCanvas(this, context);
    }, false);

    // Add event listener for our Button (to switch video filters)
    document.querySelector('button').addEventListener('click', function() {
        video.className = '';
        canvas.className = '';
        var effect = filters[iFilter++ % filters.length]; // Loop through the filters.
        if (effect) {
            video.classList.add(effect);
            canvas.classList.add(effect);

            document.querySelector('.container h3').innerHTML = 'Current filter is: ' + effect;
        }
    }, false);

}, false);

Let’s review our code. In order to use webcam (or microphone) we use new navigator.getUserMedia function. As params, we use {video: true, audio: true}. In this case when we open the page, Chrome browser can throw an information bar with request to allow or deny use your webcam and microphone. Allow it. This is just browser’s security system. Beside main params, we can point two callback functions for navigator.getUserMedia: onSuccessCallback and onErrorCallback. In case of any error – we hide Video and Canvas objects and the display warning message: ‘Native web camera streaming (getUserMedia) is not supported in this browser’. If everything is fine – we use the stream from the camera as the source of the video element and play it. Beside html5 video, you can see here html5 audio as well. Next, in order to produce video stream to the <canvas> object – I use basic ‘drawImage’ function (which is invoked periodically to re-draw the canvas object). And finally, when we need to apply custom CSS3 filter, we can just change className of our Video and Canvas objecs.


Live Demo

Conclusion

The future is getting closer. I hope that everything is clean for today. If you have any suggestions about further ideas for articles – you are welcome to share them with us. Good luck in your work!

SIMILAR ARTICLES


22 COMMENTS

  1. Getting “Native web camera streaming (getUserMedia) is not supported in this browser” error in the loaded page.

    • Hi Hanumanth,
      If you see this message, it means that your browser doesn’t support streaming video (with HTML5). Try to use another (modern) browser.

  2. Hola, a mi me funciono perfectamente gracias por el aporte, pero quisiera saber como hago para ver la captura que se esta haciendo desde otra computadora, o se tendria que gravar la captura y reproducirla en un reproductor de video para que un gropo de usuarios vea lo que se esta transmitiendo? como se grabaría la captura de vídeo que se esta haciendo?

    • Hello henry,
      Right now, my code doesn’t contain any save function, so, before answering your question – we should add this possibility to save captured video.

  3. Hello ! i get the same fault as Hanumanth gets which was : “Native web camera streaming (getUserMedia) is not supported in this browser”

    the weird thing is… if i run your live demo… it works ! in the browers but when i write the source code myself i get the error ? what can cause this ?

  4. Is there any way to record a video as well as its audio in html 5?
    This has been a headache for me from the past 2 days…. Kindly help..

  5. hi,

    cool explanations, however when I download the package and try it locally i get an error: An error occurred: [Reason: undefined]. Your demo works though … am I missing something ?

Leave a Reply