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 <video> object</h2> <video></video> </div> <div class="col"> <h2>HTML5 <canvas> 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
[sociallocker]
download package
[/sociallocker]
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!
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.
This is a really cool snippet, thanks for sharing.
“An error occured: [Reason: 1]”
Any idea what it means?
It means that you’ve clicked ‘Deny’ button (Permission Denied).
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 Carlos, English please, I can’t understand Spanish language, sorry
I liked the contribution, as captured on video and burn it to mp4?
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.
java script alert an error occured:[reason:1]
Hello Nishant,
Did you try it in IE? This browser is not supported.
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 ?
Hi Andreas, did you try it in Chrome browser?
Enough info to my search, Really writer have good knowledge. thanks
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..
Hi Jatin,
I already answered about complexity of this task before, however, you can try refer to:
http://stackoverflow.com/questions/13468217/html5-save-video-canvas-tag-to-file
error reason1 == with chrome = i allow to capture. How?
Hi Tie,
It might be: PERMISSION_DENIED error (number 1)
hey andrew , are you using webrtc here ?
Hi Arjun,
No, webrtc is not used in this article. Our article is about how to use the native html5 video
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 ?
Hi Nua,
It would be better if you run it at localhost (using wamp/xamp). It should work everywhere.