DEV Community

Cover image for How to Access Device Cameras with JavaScript (Front and Rear)
Douglas Matoso
Douglas Matoso

Posted on • Originally published at webdevdrops.com

How to Access Device Cameras with JavaScript (Front and Rear)

Hey folks! In this post I will show you how to access the device’s cameras on a web page, via JavaScript, with support for multiple browsers and without the need for external libraries.

How to Access Device Cameras with JavaScript (Front and Rear)

How to access the camera

To access the user’s camera (and/or microphone) we use the JavaScript MediaStream API. This API allows to access the video and audio captured by these devices through streams.

The first step is to check if the browser supports this API:

if (
  "mediaDevices" in navigator &&
  "getUserMedia" in navigator.mediaDevices
) {
  // ok, browser supports it
}

Support is decent in modern browsers (no Internet Explorer, of course).

Capturing the video stream

To capture the video stream generated by the camera, we use the getUserMedia method of the mediaDevices object.

This method receives an object with the types of media we are requesting (video or audio) and some requirements. To start, we can just pass {video: true} to get the video from the camera.

const videoStream = await navigator.mediaDevices.getUserMedia({ video: true });

This call will ask the user for permission to access the camera. If the user denies it, it throws an exception and does not return the stream. So it must be done inside a try/catch block to handle this case.

Page requesting to use the camera

Note that it returns a Promise, so you have to use async/await or a then block.

Video requirements

We can improve the requirements of the video by passing information about the desired resolution and minimum and maximum limits:

const constraints = {
  video: {
    width: {
      min: 1280,
      ideal: 1920,
      max: 2560,
    },
    height: {
      min: 720,
      ideal: 1080,
      max: 1440,
    },
  },
};

const videoStream = await navigator.mediaDevices.getUserMedia(constraints);

That way the stream comes in the correct proportion of width and height. If it is a cell phone in portrait mode it takes care of inverting the dimensions.

Displaying the video on the page

Okay, now that we have the stream, what can we do with it?

We can display the video on the page, in a video element:

// considering there is a
// <video autoplay id="video"></video> 
// tag in the page
const video = document.querySelector("#video");
const videoStream = await navigator.mediaDevices.getUserMedia(constraints);
video.srcObject = videoStream;

Note the autoplay attribute in the video tag. Without it, you need to call video.play() to actually start displaying the image.

Accessing the phone’s front and rear cameras

By default getUserMedia will use the system’s default video recording device. In the case of a cell phone with two cameras, it uses the front camera.

To access the rear camera, we must include facingMode: "environment" in the video requirements:

const constraints = {
  video: {
    width: { ... },
    height: { ... },
    facingMode: "environment"
  },
};

The default is facingMode: "user", which is the front camera.

Be aware that, if you want to change the camera with the video already playing, you will need to stop the current stream before replacing it with the stream from the other camera:

videoStream.getTracks().forEach((track) => {
  track.stop();
});

Taking screenshots

Another cool thing you can do is capture images (screenshots) of the video.

You can draw the current video frame on a canvas, for example:

// considering there is a
// <canvas id="canvas"></canvas>
// tag in the page
const canvas = document.querySelector("#canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext("2d").drawImage(video, 0, 0);

You can also display the canvas content in an img element.

In the example I created for this tutorial, I added a button that creates images dynamically from the canvas and adds them to the page. Something like:

const img = document.createElement("img");
img.src = canvas.toDataURL("image/png");
screenshotsContainer.prepend(img);

Conclusion

See the running example here: https://doug2k1.github.io/javascript-camera/

And the complete source code is here: https://github.com/doug2k1/javascript-camera

Top comments (6)

Collapse
 
thisdotmedia_staff profile image
This Dot Media

Really helpful! Thanks Douglas 😃

Collapse
 
doug2k1 profile image
Douglas Matoso

Thanks for the feedback!

Collapse
 
thisdotmedia_staff profile image
This Dot Media

Our pleasure!

Collapse
 
appinteractive profile image
Grzegorz Leoniec

Sadly does not work in Firefox for mobile.

Collapse
 
doug2k1 profile image
Douglas Matoso

Hi, Grzegorz. I've tested in the latest version for Android and it worked.

Anyway, here is the compatibility table: caniuse.com/#feat=stream
Support is pretty decent.

Collapse
 
appinteractive profile image
Grzegorz Leoniec

Yeah it seems that Firefox for iOS sucks. It doesn’t even appear in the compatibility table of Mozilla which is odd. Currently trying to get it working with falling back to navigator.mozGetUserMedia