Take photo from a webcam using JavaScript

Do you want to capture photos from your web-camera and generate images in any supported format e.g. PNG, JPEG, GIF, WebP etc.?

First method, capture photo using Canvas2D API:

Live demo: https://www.webrtc-experiment.com/takePhoto/

Below example captures photo from an HTML5 Video element:

var yourVideoElement = document.querySelector('video');

// pass your HTML5 Video Element
var photo = takePhoto(yourVideoElement);
window.open(photo);

function takePhoto(video) {
    var canvas = document.createElement('canvas');
    canvas.width = video.videoWidth || video.clientWidth;
    canvas.height = video.videoHeight || video.clientHeight;

    var context = canvas.getContext('2d');
    context.drawImage(video, 0, 0, canvas.width, canvas.height);

    return canvas.toDataURL('image/png');
}

Above code returns PNG. Here is how to get different formats:

var PNG = canvas.toDataURL('image/png');
var JPEG = canvas.toDataURL('image/jpeg');
var GIF = canvas.toDataURL('image/gif');
var WebP = canvas.toDataURL('image/webp', 1);


Second method, capture photo using "ImageCapture" API:

Live Demo: https://www.webrtc-experiment.com/ImageCapture/

You need to pass MediaStreamTrack (aka Video-Track) object:

if (typeof ImageCapture === 'function') {
    var firstVideoTrack = yourCameraStream.getVideoTracks()[0];
    var imageCapture = new ImageCapture(firstVideoTrack);
    imageCapture.takePhoto().then(function(blob) {
        var photo = URL.createObjectURL(blob);
        window.open(photo);
    });
}

Note: ImageCapture API requires Chrome version >= 60.

WebRTC captureStream API

You can use "captureStream" method to generate a realtime media stream from any HTML5 video or canvas-2d element.
var realtimeStream = canvasElement.captureStream(15);

Using captureStream API:

  • You can record WebGL based 3D games; you can also share in realtime with many users using RTCPeerConnection API
  • You can record canvas-2D animation or drawings; you can share in realtime as well using same RTCPeerConnection API
  • You can share your local video files e.g. WebM, Mp4, FLV, TS-M3U8 (hls-live-streaming) or audio files e.g. Wav, Ogg, Mp3 etc. You can record specific portions of these files as well.

How to record WebGL or Canvas2D animations?

You can use RecordRTC to record canvas-2D or 3D animations. You can try a few demos here:
First step, generate a realtime stream from HTML5 canvas element:
var realtimeStream = canvasElement.captureStream(15);
The parameter "15" is named as "frame-rates". We requested 15 fps stream.

Second step, record the resulting stream using RecordRTC or MediaStreamRecorder API:
var realtimeStream = canvasElement.captureStream();

var parameters = {
    mimeType: 'video/webm'
};

var recorder = RecordRTC(realtimeStream, parameters);

recorder.setRecordingDuration(5 * 1000).onRecordingStopped(function() {
    var recordedVideo = recorder.getBlob();
    var file = new File([recordedVideo], 'filename.webm', {
        type: 'video/webm'
    });
    var fileURL = URL.createObjectURL(file);
    window.open(fileURL);
});

recorder.startRecording();
Third and last step, repeatedly draw shapes or animations on canvas 2d surface:
var context = canvasElement.getContext('2d');

(function looper() {
    context.clearRect(0, 0, canvasElement.width, canvasElement.height);
    context.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);

    // draw shapes every 10 milliseconds
    setTimeout(looper, 10);
})();

How to broadcast/share WebGL or Canvas2D animations with other users?

You can "[RTCPeerConnection] addStream" method to share (broadcast) canvas-2D or 3D animations with remote users. You can try this demo:
First step, generate a realtime stream from HTML5 canvas element:
var realtimeStream = canvasElement.captureStream(15);
Second and last step, share with remote users using RTCPeerConnection API:
var peer = new webkitRTCPeerConnection(parameters);

// check this line
peer.addStream(canvasStream);

// now either create offer or answer descriptions
peer.createOffer(successCallback, failureCallback, parameters);

How to share or record microphone audio along with Canvas2D animations?

It is simple: use "addTrack" method to merge tracks.
var microphoneStream = captureUsingNavigatorDotGetUserMediaAPI({
    audio: true
});

// merge audio tracks into canvas stream
microphoneStream.getAudioTracks().forEach(function(track) {
    // check this line
    canvasStream.addTrack(track);
});

// now either record "canvasStream" or share using RTCPeerConnection API
peer.addStream(canvasStream); // microphone+canvas2D

Can I capture stream from an <audio> element?

Simply yes. You can capture audio either from <audio> tag or otherwise <video> element.

Remember: <video> tag also accepts audio-only stream. Your stream do NOT need to have video tracks. Here is how to capture audio stream from a <video> element:
videoElement.src = URL.createObjectURL(microphoneStream);

// capture from <video> tag
var capturedStream = videoElement.captureStream();

// initiate a standalone instance
var audioOnlyStream = new webkitMediaStream();

// merge only audio tracks
capturedStream.getAudioTracks().forEach(function(track) {
    audioOnlyStream.addTrack(track);
});

// either record "audioOnlyStream" or share using RTCPeerConnection API
peer.addStream(audioOnlyStream);

Unable to use "captureStream" API?

You may need to enable following chrome-flag; then relaunch the chrome browser:
chrome://flags/#enable-experimental-web-platform-features

References: