The MediaDevices.getUserMedia()
method prompts the user for permission to use a media input which produces a MediaStream
with tracks containing the requested types of media. That stream can include, for example, a video track (produced by either a hardware or virtual video source such as a camera, video recording device, screen sharing service, and so forth), an audio track (similarly, produced by a physical or virtual audio source like a microphone, A/D converter, or the like), and possibly other track types.
It returns a Promise
that resolves to a MediaStream
object. If the user denies permission, or matching media is not available, then the promise is rejected with PermissionDeniedError
or NotFoundError
respectively.
It's possible for the returned promise to neither resolve nor reject, as the user is not required to make a choice at all.
Generally, you will access the MediaDevices
singleton object using navigator.mediaDevices
, like this:
navigator.mediaDevices.getUserMedia(constraints) .then(function(stream) { /* use the stream */ }) .catch(function(err) { /* handle the error */ });
var promise = navigator.mediaDevices.getUserMedia(constraints);
constraints
A MediaStreamConstraints
object specifying the types of media to request, along with any requirements for each type.
The constraints parameter is a MediaStreamConstraints
object with two members: video
and audio
, describing the media types requested. Either or both must be specified. If the browser cannot find all media tracks with the specified types that meet the constraints given, then the returned promise is rejected with NotFoundError
.
The following requests both audio and video without any specific requirements:
{ audio: true, video: true }
If true
is specified for a media type, the resulting stream is required to have that type of track in it. If one cannot be included for any reason, the call to getUserMedia()
will result in an error.
While information about a user's cameras and microphones are inaccessible for privacy reasons, an application can request the camera and microphone capabilities it needs and wants, using additional constraints. The following expresses a preference for 1280x720 camera resolution:
{ audio: true, video: { width: 1280, height: 720 } }
The browser will try to honor this, but may return other resolutions if an exact match is not available, or the user overrides it.
To require a capability, use the keywords min
, max
, or exact
(a.k.a. min == max
). The following demands a minimum resolution of 1280x720:
{ audio: true, video: { width: { min: 1280 }, height: { min: 720 } } }
If no camera exists with this resolution or higher, then the returned promise will be rejected with OverconstrainedError
, and the user will not be prompted.
The reason for the difference in behavior is that the keywords min
, max
, and exact
are inherently mandatory, whereas plain values and a keyword called ideal
are not. Here's a fuller example:
{ audio: true, video: { width: { min: 1024, ideal: 1280, max: 1920 }, height: { min: 776, ideal: 720, max: 1080 } } }
An ideal
value, when used, has gravity, which means that the browser will try to find the setting (and camera, if you have more than one), with the smallest fitness distance from the ideal values given.
Plain values are inherently ideal, which means that the first of our resolution examples above could have been written like this:
{ audio: true, video: { width: { ideal: 1280 }, height: { ideal: 720 } } }
Not all constraints are numbers. For example, on mobile devices, the following will prefer the front camera (if one is available) over the rear one:
{ audio: true, video: { facingMode: "user" } }
To require the rear camera, use:
{ audio: true, video: { facingMode: { exact: "environment" } } }
A Promise
whose fulfillment handler receives a MediaStream
object when the requested media has successfully been obtained.
Rejections of the returned promise are made by passing a DOMException
error object to the promise's failure handler. Possible errors are:
AbortError
NotReadableError
, some problem occurred which prevented the device from being used.NotAllowedError
SecurityError
for this instead; SecurityError
has taken on a new meaning.NotFoundError
NotReadableError
OverconstrainedError
OverconstrainedError
, and has a constraint
property whose string value is the name of a constraint which was impossible to meet, and a message
property containing a human-readable string explaining the problem. SecurityError
Document
on which getUserMedia()
was called. The mechanism by which user media support is enabled and disabled is left up to the individual user agent.TypeError
false
.This example gives a preference for camera resolution, and assigns the resulting MediaStream
object to a video element.
// Prefer camera resolution nearest to 1280x720. var constraints = { audio: true, video: { width: 1280, height: 720 } }; navigator.mediaDevices.getUserMedia(constraints) .then(function(mediaStream) { var video = document.querySelector('video'); video.srcObject = mediaStream; video.onloadedmetadata = function(e) { video.play(); }; }) .catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.
Here's an example of using navigator.mediaDevices.getUserMedia()
, with a polyfill to cope with older browsers. Note that this polyfill does not correct for legacy differences in constraints syntax, which means constraints won't work well across browsers. It is recommended to use the adapter.js polyfill instead, which does handle constraints.
// Older browsers might not implement mediaDevices at all, so we set an empty object first if (navigator.mediaDevices === undefined) { navigator.mediaDevices = {}; } // Some browsers partially implement mediaDevices. We can't just assign an object // with getUserMedia as it would overwrite existing properties. // Here, we will just add the getUserMedia property if it's missing. if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function(constraints) { // First get ahold of the legacy getUserMedia, if present var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // Some browsers just don't implement it - return a rejected promise with an error // to keep a consistent interface if (!getUserMedia) { return Promise.reject(new Error('getUserMedia is not implemented in this browser')); } // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise return new Promise(function(resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject); }); } } navigator.mediaDevices.getUserMedia({ audio: true, video: true }) .then(function(stream) { var video = document.querySelector('video'); // Older browsers may not have srcObject if ("srcObject" in video) { video.srcObject = stream; } else { // Avoid using this in new browsers, as it is going away. video.src = window.URL.createObjectURL(stream); } video.onloadedmetadata = function(e) { video.play(); }; }) .catch(function(err) { console.log(err.name + ": " + err.message); });
Lower frame-rates may be desirable in some cases, like WebRTC transmissions with bandwidth restrictions.
var constraints = { video: { frameRate: { ideal: 10, max: 15 } } };
On mobile phones.
var front = false; document.getElementById('flip-button').onclick = function() { front = !front; }; var constraints = { video: { facingMode: (front? "user" : "environment") } };
To use getUserMedia()
in an installable app (for example, a Firefox OS app), you need to specify one or both of the following fields inside your manifest file:
"permissions": { "audio-capture": { "description": "Required to capture audio using getUserMedia()" }, "video-capture": { "description": "Required to capture video using getUserMedia()" } }
See permission: audio-capture and permission: video-capture for more information.
Specification | Status | Comment |
---|---|---|
Media Capture and Streams The definition of 'MediaDevices.getUserMedia()' in that specification. | Editor's Draft | Initial definition |
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|---|
Basic support | 53[1][3] | (Yes) | 36 (36)[2][4] | No support | 40[1] | 11 |
Promises | 53 | (Yes) | 38 (38) | No support | ? | 11 |
Stereo audio capture | ? | ? | 55 (55)[5] | No support | ? | ? |
Feature | Android Webview | Chrome for Android | Edge | Firefox Mobile (Gecko) | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
Basic support | 53[1][3] | 53[1][3] | (Yes) | 36.0 (36) [2] | No support | 40[1] | 11 |
Promises | 53 | 53 | ? | 38.0 (38) | No support | ? | 11 |
Stereo audio capture | ? | ? | ? | No support | No support | ? | ? |
[1] Older versions of Chrome and Opera implement navigator.webkitGetUserMedia
, the prefixed version of the legacy navigator.getUserMedia
method.
From version 47 to 52, the promise-based interface was only available through the adapter.js polyfill, or using the flag chrome://flags/#enable-experimental-web-platform-features. Starting with version 53, the promise-based interface is on by default, though that interface is still not available through navigator
.
[2] Older versions of Firefox implement navigator.mozGetUserMedia()
, the prefixed version of the legacy navigator.getUserMedia
method.
The promise-based version of this method and the constraint syntax described here are available as of Firefox 38. Earlier versions (32-37) used an outdated constraint syntax, but the syntax described here, as well as the promise-based interface, is available there through the adapter.js polyfill.
Firefox 49 includes changes to bring the possible errors up to date with the specification, including the change to the meaning of SecurityError
. In addition, if both video and audio tracks are requested, getUserMedia()
now fails unable to obtain access to both. Previously, it would create a stream which had the successful portion of the media available. For example, if the user has a microphone but no camera (or denied access to the camera), previous versions of Firefox would return a stream with an audio track but no video. Now this correctly results in an error.
Opera uses an outdated constraint syntax, but the syntax described here is available through the adapter.js polyfill.
[3] Chrome throws error if the page serving the script is loaded from insecure origin (i.e. HTTP).
[4] Prior to Firefox 55, getUserMedia()
incorrectly returns NotSupportedError
when the list of constraints specified is empty, or has all constraints set to false
. Starting in Firefox 55, this situation now correctly calls the failure handler with a TypeError
.
[5] Starting in Firefox 55, if the input device supports stereo input, the resulting MediaStream
will have stereo sound; support to specifically request mono input will come in Firefox 56. The preference media.getusermedia.channels
lets you control the maximum number of channels to be captured; a value of 0, the default, tells getUserMedia()
to capture all of the available, supported, channels.
navigator.getUserMedia()
legacy API.mediaDevices.enumerateDevices()
: Learn the types and number of devices the user has available.getUserMedia()
to taking photos rather than video.
© 2005–2018 Mozilla Developer Network and individual contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia