Color blocks showing 240p to 2K video sizes with title “getUserMedia() Video Constraints.”

getUserMedia() Video Constraints

WebRTC is constantly evolving, and with it, its most well-known function is getUserMedia(). With it, you can access the device’s webcams and microphones and request a video stream, an audio stream, or both.

In this article, we will be focusing on the video constraints available to us when requesting a video stream through getUserMedia(). In a previous blog post, we focused on the audio constraints.

MediaStreamConstraints

The getUserMedia() function receives only one parameter, a MediaStreamConstraints object used to specify what kind of tracks (audio, video, or both) to request, and, optionally, any requirements for each track.

Here’s a basic example of how you sent this object to the newer, promise-based, getUserMedia():

var constraints = {
    audio: true,
    video: true
}
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
    /* use the stream */
}).catch(function(err) {
    /* handle the error */
});

The constraints object can have one or both of these two properties:

  • video – indicates whether or not a video track is required
  • audio – indicates whether or not an audio track is required

Here’s how a basic constraint object that requires both an audio and a video stream looks like (the same one used above):

var constraints = { audio:true, video:true}

If you’re taking a picture and don’t need an audio track, just set the audio property to false like this:

var constraints = {
    audio: false,
    video: true
}

Suppose true is specified for video or audio. In that case, the resulting stream requires to have that particular media track in it; else the call to getUserMedia() will result in a NotFoundError error (see common getUserMedia() Errors for more details).

MediaTrackConstraints

The audio and video properties can take two types of values:

  • a Boolean value (true or false) as above
  • a MediaTrackConstraints object which provides specific properties like width and height that the track must meet.

Video Track Constraints: Resolution

One can use the width and height properties to request a specific resolution from the webcam. In this example, the browser will request a 720p (1280×720) video stream:

{
    audio: true,
    video: {
        width: 1280,
        height: 720
    }
}

The browser will try to honor this, but may return a different resolution stream. From my experience, this often happens because the webcam does not support the requested resolution (try requesting odd resolutions like 721×55 and see what happens). It might also be that another getUserMedia() overrode the constraints call from a different app on Mac (where webcam access is shared) or a different Chrome tab (shared access). Other reasons might exist, too.

You can try the Webcam Resolution Tester to see what resolutions your browser and webcam combo support.

Keywords

If the resolution is important to you and the device and browser cannot guarantee it, then you can use the min, max, and exact keywords to help you get the best resolution from any device. These keywords apply to any MediaTrackConstraint property.

If, for example, you’re doing image recognition in video streams and require 1280×720 resolution, use this constraint:

{
    audio: true,
    video: {
        width: {
            exact: 1280
        },
        height: {
            exact: 720
        }
    }
}

In the example above, if no camera exists that supports the exact resolution, then the returned promise will be rejected with OverconstrainedError, and the user will not be prompted (see common getUserMedia() Errors for details).

The following constraint also requests a resolution of 1280×720. Still, it also mentions 320×240 as the minimum resolution since not all webcams support 1280×720, and in some use cases, it’s better to get something rather than nothing:

{
    audio: true,
    video: {
        width: {
            min: 320,
            max: 1280
        },
        height: {
            min: 240,
            max: 720
        }
    }
}

Values without the min, max, and exact keywords are considered ideal values, which itself is a keyword, but it is not mandatory. These two examples do the same thing:

{
    audio: true,
    video: {
        width: 1280,
        height: 720
    }
}
{
    audio: true,
    video: {
        width: {
            ideal: 1280
        },
        height: {
            ideal: 720
        }
    }
}

Video Track Constraints: Getting The Front Or Rear Camera On Mobile Devices

One can use the facingMode property for the video track constraint. Accepted values are: user (front camera), environment (rear camera), left, and right.

Here’s how to request a video stream that should ideally come from the back camera:

{
    audio: true,
    video: {
        width: 640,
        height: 480,
        facingMode: "environment"
    }
}

or

{
    audio: true,
    video: {
        width: 640,
        height: 480,
        facingMode: {
            ideal: "environment"
        }
    }
}

Here’s how to request a video stream that should come from the back camera:

{
    audio: true,
    video: {
        width: 640,
        height: 480,
        facingMode: {
            exact: "environment"
        }
    }
}

I am not sure how well mobile browsers support these.

Video Track Constraints: Frame Rate

Since frame rate has a direct impact on video quality and bandwidth, in some cases, such as publishing a video stream over low-bandwidth connections, it might be a good idea to limit the frame rate. I was able to obtain a 60fps stream from the Logitech C925E by using:

{
    audio: true,
    video: {
        width: 320,
        height: 240,
        frameRate: {
            ideal: 60,
            min: 10
        }
    }
}

Keep in mind that the frame rate of a stream coming from a webcam depends a lot on the light in the room.

Using a Certain Webcam or Microphone Device

There is one constraint property that applies to both audio and video tracks: deviceId. It specifies the device ID (or an array of IDs) that you should use for capturing that stream. The device ID is unique and will be the same across browsing sessions on the exact origin. You will first need to obtain the device ID using MediaDevices.enumerateDevices().

Once you know the deviceId, you can ask for a specific webcam or microphone:

{
    audio: true,
    video: {
        deviceId: {
            exact: "the_device_id"
        }
    }
}

There's also groupId, a shared ID for all media sources that come from the same physical device. For example, a microphone and speaker that come from the same headset will share the same group ID.

This example allows you to switch between the available devices used for input (mic & cam) and output (speaker).

MediaDevices.getSupportedConstraints()

Chrome 53, Firefox 44, and Safari 11 added support for MediaDevices.getSupportedConstraints(). The function returns a dictionary listing the constraints supported by the user agent.

Click here to run it for your current browser.

The function seems to return a lot of false positives; track.getSettings() gives better results.

MediaStreamTrack.getSettings()

You can also check which constraints are supported by using track.getSettings(). It returns an object containing all applicable constraints, including those supported by the browser but whose defaults didn't change through code.

Here's how to use the function and print the result to the console:

navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
    video.srcObject = stream;
    stream.getTracks().forEach(function(track) {
        console.log(track.getSettings());
    })
});

This code pen writes on the page the result of track.getSettings() for your browser.

Chrome 59 added the function, and Firefox and Safari 11 also support it.

Old Constraints

The specifications for the constraints object have changed in the past. Constraints using the old spec looked like this:

var constraints = {
    audio: true,
    video: {
        mandatory: {
            minWidth: 640,
            maxWidth: 640,
            minHeight: 480,
            maxHeight: 480
        }
    }
}

The old spec was the only one supported by Chrome until Chrome 59 (June 2017), which added support for the new one. Older versions of Chrome can also use the latest spec through adapter.js

Firefox 38+ (May 2015) and Safari 11 both support the new video constraints spec.

getUserMedia() Video Constraints
Share this
IT TAKES 1 MINUTE
Sign up for a 14 Day Trial

With our 14 days (336 hours) trial you can add audio, video and screen + camera recording to your website today and explore Pipe for 2 weeks