Saturday, November 28, 2020

Browser Video Capture, screenshot and compatibilities

Introduction

Hey all,

Ever considered to incorporate to your web page a video capture system to your page?
The process is really simple. We just need to add the video element to the HTML and a one-liner in the JS to have it started. 

Sometimes not even that is needed! 

Let's see how.


HTML Media Capture

This old method uses an HTML form extension to access a device's capture mechanism, such as camera, from within a file upload control.

<input type="file" accept="image/*;capture=camera">

This method is very simple and works well with mobile Chrome, but doesn't have support from some other mobile browsers, like Firefox, and is not supported by computers webcams.

WebRTC

WebRTC is an API that can be used by video-chat Web apps.

With this method we'll need the HTML5 element <video>, with an autoplayt attribute, to automatically display the video.

<video autoplay></video>
Then if you want to take a snapshot, just add a button and somewhere to display the image, either a canvas or an image. I'll showcase both:

  <button data-capture-video>Take Shot</button>
  <canvas></canvas>
  <img src="#"/>
  
Then when we press the button, we take the image from the video and display in our canvas/image element:

  buttonElement.addEventListener("click", () => {
   canvasElement.height = videoElement.videoHeight;
   canvasElement.width = videoElement.videoWidth;
   canvasElement.getContext("2d").drawImage(videoElement, 0, 0);
   imageElement.src = canvasElement.toDataURL("image/jpeg");
  });  

This has the advantage that it's accepted in all major browsers, mobile and non-mobile, and allows the image to be edited. Like on CSS:


  .video--inverted {
      filter: invert(1);
  }

And edit the video element on HTML to:


<video autoplay class="video--inverted"></video>

One my notice that the image quality is not the best. This can happen for 3 reasons: Either the video element is compressing too much the webcam image, or the snapshot image compression is too high, or the camera hasn't got as good resolution as we'd expect.

If we (or anything else) is compressing too much the video image, we can add a constraint to force the image to be bigger


var constrains = {
    video: {width: 9999}
};

If the issue is the compression from video to image is too high, then we'd need to change the parameters on how we convert the image. If we want to use an image format with a lossy compression such as image/jpeg and image/webp, we'd want to increase the 2nd argument to a value near 1 (retain 100% quality)(the default is 0.92), like so:


imageElement.src = canvasElement.toDataURL("image/jpeg", 0.95);

Here's a fiddle with some of the above code.

https://jsfiddle.net/sesteves86/956acpx2/34/

Resources

https://www.html5rocks.com/en/tutorials/getusermedia/intro/

https://www.w3.org/TR/html-media-capture/

https://developer.mozilla.org