如何解决 iOS 11 Safari getUserMedia "Invalid constraint" 问题

How to resolve iOS 11 Safari getUserMedia "Invalid constraint" issue

我正在尝试 运行 在 iOS 11 中的 Safari 中使用以下代码。它应该提示用户授予访问其设备摄像头的权限,然后将其显示在我的 <video autoplay id="video"></video> 元素。但是,当 运行ning in iOS 11 时,会导致抛出 OverconstrainedError

{message: "Invalid constraint", constraint: ""}

我知道 iOS 11 刚出来所以它可能是一个错误,但有什么想法吗?还有其他人 运行 参与其中吗?

代码:

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);
         });
}

编辑 1

我 运行 navigator.mediaDevices.getSupportedConstraints() 它 returns 以下内容:

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

我试过省略 video 属性 的配置,但没有成功。

貌似是bug,已经改正了,因为我刚刚又试了一遍,错误信息不再出现了。

请注意,虽然错误消息消失了,但我必须再做一项更改才能使其正常工作,即在 then 回调中添加 video.srcObject = stream;

请记住 Xcode 附带的 iOS 模拟器不支持网络摄像头或麦克风,这就是为什么您可能会收到 OverconstrainedError(根据 https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia 文档,这意味着不支持设备符合传递的选项,即使您没有提供细节)

safari 中的无效约束错误是因为浏览器希望您传递正确的宽度,其中之一:

  • 320
  • 640
  • 1280

320 或 640 的宽高比 4:3 和 1280 的宽高比 16:9 自动计算高度,然后如果您传递 320 的宽度,则视频流设置为:

  • 320x240

如果您将宽度设置为 640,则您的视频流设置为:

  • 640x480

如果您将宽度设置为 1280,则您的视频流设置为:

  • 1280x720

在任何其他情况下,您收到宽度值错误 "InvalidConstrain"。

您还可以使用最小、最大、精确或理想的宽度约束,请检查 MDN documentation

这里有一个例子 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:在 chrome 中,您可以设置宽度和高度,视频流设置为这些尺寸,Firefox 执行 fitness distance,Safari 期望完全匹配。