How to resolve iOS 11 Safari getUserMedia “Invalid

2019-02-06 20:31发布

问题:

I'm attempting to run the following code in Safari in iOS 11. It should prompt the user to give access to their devices camera and then display it in my <video autoplay id="video"></video> element. However, when running in iOS 11, it results in an OverconstrainedError to be thrown:

{message: "Invalid constraint", constraint: ""}
  • The code runs fine in Android and successfully opens the camera.
  • I've attempted multiple valid configurations with no luck.

I know iOS 11 just came out so it may be a bug, but any thoughts? Has anyone else run into this?

Code:

var video = document.getElementById('video');
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
     navigator.mediaDevices.getUserMedia({video: true})
         .then(function(stream) {
             video.src = window.URL.createObjectURL(stream);
             video.play();
         })
         .catch(function(err) {
             console.log(err);
         });
}

Edit 1

I've run navigator.mediaDevices.getSupportedConstraints() and it returns the following:

{
    aspectRatio: true,
    deviceid: true,
    echoCancellation: false,
    facingMode: true,
    frameRate: true,
    groupId: true,
    height: true,
    sampleRate: false,
    sampleSize: false,
    volume: true,
    width: true
}

I've tried configurations omitting the video property, but had no luck.

回答1:

The invalid constraint error in safari is because the browser expects that you pass a correct width, one of:

  • 320
  • 640
  • 1280

the height is auto calculate in an aspect ratio of 4:3 for 320 or 640, and 16:9 for 1280, then if you pass a width of 320, you video stream is set in:

  • 320x240

if you set a width of 640, you video stream is set in:

  • 640x480

And if you set a width of 1280, then you video stream is set in:

  • 1280x720

In any other case you got a error "InvalidConstrain" for width value.

Also you can use a min, max, exact or ideal constrains for width, please check the MDN documentation

Here an example in this codepen

var config = { video: { width: 320/*320-640-1280*/ } };
var start = () => navigator.mediaDevices.getUserMedia(config)
  .then(stream => v.srcObject = stream)
  .then(() => new Promise(resolve => v.onloadedmetadata = resolve))
  .then(() => log("Success: " + v.videoWidth + "x" + v.videoHeight))
  .catch(log);

var log = msg => div.innerHTML += "<p>" + msg + "</p>";

PD: In chrome you can set a width of height and the video stream is set in these sizes, Firefox do a fitness distance, and Safari expect a exact match.



回答2:

It appears to have been a bug that was corrected, because I just tried it again and the error message no longer appears.

Note that while the error message went away, I did have to make one more change for it to work, which was adding video.srcObject = stream; in the then callback.



回答3:

Remember that the iOS Simulator that comes with Xcode does not support webcam or microphone, which is why you may get the OverconstrainedError (as per https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia docs, that means no device fits the passed options, even if you're not putting specifics)