WebRTC(Web Real-Time Communication) is an API supporting real time audio and video communication through a browser. It is now a recommended W3C standard. This post is to show you how to capture video stream and screenshot with WebRTC.
Capture video stream
To play video stream from the video camera, we first need to put a video tag in our code:
<video id="video"></video>
The main function to get the video stream is the navigator.getUserMedia, as of now only few of the browsers support this, you can check the browser support for this on caniuse.com. This API is well supported by Chrome and Firefox now.
Before using this function, we need to do the compatibility check first:
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
The prototype of navigator.getUserMedia is:
navigator.getUserMedia(constraints, successCallback, errorCallback);
The first parameter is an object, the object should contain some options for video and audio. For example, if you want to activate the video device, you should pass:
{ video: true }
If you want both video and audio, then you need to pass:
{ video: true, audio: true }
The other two parameters are callback functions for successful activating the device or failed to activate the device. The first parameter to the successCallback function is the video stream object. You can call window.URL.createObjectURL to convert the video stream to object URL. But if the device is failed to activate, the first parameter to errorCallback is an error object(Chrome) or error string(Firefox).
var video = document.getElementById('video'); navigator.getUserMedia({ video: true }, function(stream) { video.src = window.URL.createObjectURL(stream); video.play(); }, function(error) { alert(error.name || error); });
When the browser execute above codes, it may ask the user whether to allow using the video camera or not. If allowed, the real time video stream can be displayed on the webpage; otherwise, the error event will be triggered.
Capture screenshot
To capture the screenshot, what it does is to pass the first frame of the video stream to the canvas.
<input type="button" id="capture" value="Capture" /> <canvas id="canvas"></canvas>
You can call drawImage to draw image on the canvas. It has four parameters, the start drawing coordinates(x,y), width and height of the image. The image size should have the same size as the video frame. To be noted that the video frame size can be available only after the video is loaded.
video.addEventListener('loadeddata', function() { console.log(this.videoWidth); }, false);
Unfortunately, the above code will always get 0 in Firefox even in the playing event. Hence we can only use setTimeout to get the size.
function bindCapture() { var videoWidth = video.videoWidth, videoHeight = video.videoHeight; if (videoWidth && videoHeight) { var canvas = document.getElementById('canvas'); canvas.width = videoWidth; canvas.height = videoHeight; document.getElementById('capture').addEventListener( 'click', function() { canvas.getContext('2d').drawImage( video, 0, 0, videoWidth, videoHeight ); }, false ); } else { setTimeout(bindCapture, 200); } } bindCapture();
Bonus
- If you have started the video camera in one browser, then it will trigger the error event if you try to start the camera in another browser. But within the same browser, it's ok.
- If you want to provide screenshot saving capability, you'd better send the image back to the server. The user experience of local storage is not satisfying.