iOS 13在Chrome和Edge上无法使用getUserMedia

3
我和我的朋友正在构建一个需要使用相机的应用程序,我们在与iOS合作时遇到了一些问题(我们正在使用iOS13):
Safari在获取相机内容后会冻结,Chrome和Edge根本无法获得相机访问权限。我们的代码如下:
let windowWidth=window.innerWidth;
let windowHeight=window.innerHeight;

function isMobile() {
    const isAndroid = /Android/i.test(navigator.userAgent);
    const isiOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
    return isAndroid || isiOS;
}

async function setupCamera() {
    video = document.getElementById('video');
    console.log("a")

    video.setAttribute('autoplay', '');
    video.setAttribute('muted', '');
    video.setAttribute('playsinline', '');

    const stream = await navigator.mediaDevices.getUserMedia({
        'audio': false,
        'video': {
            facingMode: 'user',
            width: mobile ? undefined : windowWidth,
            height: mobile ? undefined : windowHeight
        },
    });
    console.log("b")
    video.srcObject = stream;

    return new Promise((resolve) => {
        video.onloadedmetadata = () => {
            resolve(video);
        };
    });
}

根据控制台,总是打印 'a' 但从未打印 'b'。如有线索,请不吝赐教!
1个回答

9

更新 - 2020年11月19日

iOS 14.3 beta 1中的WKWebView可以使用getUserMedia。

浏览器兼容性

我已经通过其他帖子(例如NotReadableError:Could not start source)关注此问题多年。截至本文,除Safari独立视图(webapp)或iOS Safari应用程序外,没有访问getUserMedia的权限。

iOS上的任何非Safari浏览器都无法访问getUserMedia。这是因为在幕后它们使用的是WKWebView。

已经为WKWebView提交了一个错误报告,但不提供支持。 https://bugs.webkit.org/show_bug.cgi?id=208667

独立模式获得getUserMedia访问权限的更新在iOS 13.4中发布。 https://bugs.webkit.org/show_bug.cgi?id=185448#c6

Safari冻结

您正在传递无效的约束(例如窗口宽度和高度)。您需要使用标准相机分辨率,例如640x480、1280x720等。当您使用非典型的分辨率时,WebRTC规范指出浏览器将尝试模拟您想要的数据流,但这往往会导致相机冻结或外观扭曲。

如果您正在尝试捕获前置摄像头并使其全屏,可以查看:getUserMedia(自拍)移动设备上的全屏显示

还有可能存在1或2个关于async/await使用的错误。以下是一个应该工作的演示文稿(在stackoverflow中由于安全权限而出错,但在本地或托管环境中应该可以工作)。如果需要进一步帮助,请告诉我。

function isMobile() {
  const isAndroid = /Android/i.test(navigator.userAgent);
  const isiOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
  return isAndroid || isiOS;
}

async function setupCamera() {
  const isPortrait = true; // do logic here

  let video = document.getElementById('video');

  console.log("Getting video");

  video.setAttribute('autoplay', '');
  video.setAttribute('muted', '');
  video.setAttribute('playsinline', '');

  console.log("Calling getUserMedia");

  return new Promise((resolve) => {
    (async() => {
      await navigator.mediaDevices.getUserMedia({
          'audio': false,
          'video': {
            facingMode: 'user',
            width: isPortrait ? 480 : 640,
            height: isPortrait ? 640 : 480,
          },
        })
        .then((stream) => {
          console.log("Got getUserMedia stream");
          video.srcObject = stream;
          video.play();
          resolve(true);
        })
        .catch((err) => {
          console.log("Encountered getUserMedia error", err);
          resolve(false);
        });
    })();
  });

}

(async() => {
  const ret = await setupCamera();
  console.log(`Initialised camera: ${ret}`)
})();
html,
body {
  height: 100%;
  margin: 0;
}

div {
  position: relative;
  min-height: 100%;
  min-width: 100%;
  overflow: hidden;
  object-fit: cover;
}

video {
  width: 480px;
  height: 640px;
  background-color: black;
}
<div><video id="video"></video></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接