Navigator.mediaDevices.getUserMedia在iOS 12 Safari上无法工作。

30

iOS 12中,navigator.mediaDevices.getUserMedia()在Safari中返回错误。

要重现此问题,请打开iPhone Web Inspector,然后在控制台中运行以下代码片段:

var constraints = { audio: true, video: { width: 1280, height: 720 } }; 

navigator.mediaDevices.getUserMedia(constraints)
  .then(function() {
    console.log('getUserMedia completed successfully.');
  })
  .catch(function(error) {
    console.log(error.name + ": " + error.message);
  });

您会发现在桌面浏览器和iOS 11 Safari中可以成功运行,但在iOS 12 Safari中失败了。

NotAllowedError:由于用户拒绝权限,请求未被用户代理或当前上下文中的平台允许。

有任何想法吗?

注意:这是在用户被问及其相机是否可以被访问之前发生的,排除了因为用户拒绝权限而导致的可能性。


Severisth,如果你使用“/show”打开这个jsfiddle链接,它就可以正常工作了:https://jsfiddle.net/jib1/og6up9d4/show - Искрен Станиславов
@ИскренСтаниславов 在 iOS 12.0、Safari 12 上链接无法使用(我正在使用 CrossBrowserTesting iPhone XS Max)。 - patrick
3个回答

32

在调用getUserMedia之前设置这三个属性对我解决了问题:

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

因为某些原因,video.setAttribute()可以工作,但是尝试直接将值分配给video对象,例如video.muted = ''则不行。此外,似乎不必调用video.play()。只需将video.srcObject设置为由getUserMedia返回的流即可。这篇中等帖子有一个链接到一个工作演示和源代码的链接。

1
这为我解决了问题!不过,为了让桌面版继续工作,我必须保留 await video.play()(在 Firefox 上,尚未尝试 Chrome)。 - Tomáš Hübelbauer
1
这个建议在2020年5月中仍然有效。它不适用于iOS 13,只适用于11和12。谢谢。 - O. Jones
1
这在2020年8月仍然有效。 playsinline 似乎是使其正常工作的参数。 - Pavithra Kodmad
1
仍然有效于2021年8月,仅在iOS Safari中需要,而非桌面版Safari。 - Hoffmann
同时使用video.play().catch((err) => function(){ alert(err)})来捕获和查看错误。 - Vinnie Amir

26

目前立即出现NotAllowedError的可能有两个原因:

1. getUserMedia需要https

Safari似乎要求在iOS和OSX中使用相机和麦克风访问时必须使用https

对于一个https链接,iOS Safari 12适用于我; 相同的http链接会出现NotAllowedError

Chrome也有同样的要求。这与规范的方向一致,该规范最近已将getUserMedia限制为安全上下文。尚未更新的浏览器仍然在http中公开navigator.mediaDevices,但getUserMedia始终会拒绝并显示NotAllowedError

未来,预计浏览器将完全删除http中的mediaDevices,以符合规范。

2.在跨源iframes中,getUserMedia需要功能策略。

这似乎是Safari 12的新功能。在iframes中,默认情况下关闭跨源内容的getUserMedia功能策略。

这对我有用

<iframe
  allow="camera;microphone"
  src="https://webrtc.github.io/samples/src/content/getusermedia/gum/">
</iframe>

这个不起作用

<iframe src="https://webrtc.github.io/samples/src/content/getusermedia/gum/">
</iframe>

...除了出现NotAllowedError错误外,Safari还会在Web控制台中发出警告:

The top-level frame has prevented a document with a different security origin to
call getUserMedia.

这也是规范的最新更新。


8
即使使用https和iframe代码片段,我在iOS 12的Safari上也无法使用此功能。事实上,直接点击该链接也无法起作用:https://webrtc.github.io/samples/src/content/getusermedia/gum/在这两种情况下,错误信息均为:“NotAllowedError:请求由于当前上下文中用户代理或平台不允许,可能是因为用户拒绝了权限而被拒绝。” - Severisth
1
HTTPS是我的问题。谢谢! - Kevin Curry
3
我理解这句话的含义是,尽管我了解这样做的安全隐患,但对于在本地主机或本地内网IP地址上进行开发/测试来说,这实在太麻烦了。如果有一个开发标志可以启用它,那该多好啊! - scunliffe

2
原来我的问题是12.01版本的一个漏洞。每个使用这个版本的设备都会遇到这个问题,只要将它们更新到新版本,问题就会消失。

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