98

在被拒绝一次后,我们如何使用 getUserMedia() 请求相机/麦克风访问权限?

我正在使用 getUserMedia 访问用户的相机并将数据传输到画布。那一点都很好。

在测试中,我点击了一次拒绝。此时在 Chrome 和 Firefox 中,任何带有 getUserMedia() 的后续请求都默认为拒绝状态。

我们显然不想在被拒绝后在每个页面加载时请求相机/麦克风的权限来惹恼我们的用户。地理定位 API 已经够烦人的了。

但是,必须有一种方法可以再次请求它。仅仅因为用户点击一次拒绝并不意味着他们想要一直拒绝网络摄像头访问。

我一直在阅读规范并在谷歌上搜索了一段时间,但我没有找到任何关于这个问题的明确信息。

编辑:进一步研究,似乎在 Chrome 中点击拒绝会将当前站点添加到阻止列表中。这可以通过 chrome://settings/content 手动访问。滚动到媒体。管理例外,删除被阻止的站点。

链接到 chrome://settings/content 不起作用(在我们想要添加有用的链接以让人们重新启用权限的情况下)。

处理 getUserMedia 权限的整个 UX 很糟糕。=(

4

6 回答 6

32

jeffreyveon 的回答将有助于减少您的用户选择拒绝的机会,因为她只需选择一次。

如果她确实单击了拒绝,您可以提供一条消息,说明您需要许可的原因以及如何更新她的选择。例如:

navigator.getUserMedia (
   // constraints
   {
      video: true,
      audio: true
   },

   // successCallback
   function(localMediaStream) {
      var video = document.querySelector('video');
      video.src = window.URL.createObjectURL(localMediaStream);
      video.onloadedmetadata = function(e) {
         // Do something with the video here.
      };
   },

   // errorCallback
   function(err) {
    if(err === PERMISSION_DENIED) {
      // Explain why you need permission and how to update the permission setting
    }
   }
);
于 2013-10-07T23:29:42.907 回答
29

Chrome 实现了Permissions APIin navigator.permissions,这也适用于cameramicrophone权限。

所以到目前为止,在调用之前getUserMedia(),您可以使用此 API 来查询您的相机和麦克风的权限状态:

 navigator.permissions.query({name: 'microphone'})
 .then((permissionObj) => {
  console.log(permissionObj.state);
 })
 .catch((error) => {
  console.log('Got error :', error);
 })

 navigator.permissions.query({name: 'camera'})
 .then((permissionObj) => {
  console.log(permissionObj.state);
 })
 .catch((error) => {
  console.log('Got error :', error);
 })

成功时,permissionObj.state将返回deniedgrantedprompt

有用的 SF 问题/答案在这里

对于跨浏览器解决方案,一种简单的方法是监控getUserMedia()Promise 被调用与被拒绝或解决之间的时间差,如下所示:

// In the Promise handlers, if Date.now() - now < 500 then we can assume this is a persisted user setting
var now = Date.now();
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(function(stream) {
  console.log('Got stream, time diff :', Date.now() - now);
})
.catch(function(err) {
  console.log('GUM failed with error, time diff: ', Date.now() - now);
});

这篇Medium 文章提供了更多详细信息。

希望这可以帮助!

于 2018-10-08T11:31:20.853 回答
21

使用 HTTPS。当用户授予一次权限时,它会被记住,并且 Chrome 不会再次请求该页面的权限,并且您可以立即访问媒体。这不会为您提供再次强制用户使用权限栏的方法,但至少可以确保一旦用户授予权限一次,您就不必继续要求它。

如果您的应用程序从 SSL (https://) 运行,则此权限将是持久的。也就是说,用户不必每次都授予/拒绝访问权限。

见:http ://www.html5rocks.com/en/tutorials/getusermedia/intro/

于 2013-04-14T14:05:17.503 回答
7

请注意以下几点。

1. Localhost: In Localhost Chrome Browser asking permission only one time and Firefox every pageload.

2. HTTPS: Both Browsers Chrome and Firefox asking permission only one time.

于 2016-10-18T12:54:22.917 回答
2

对此的更新答案是,当请求通过 HTTP 时,Chrome(目前在 73 上测试)不再持续提示相机访问。

然而,Firefox 确实如此。

于 2019-04-14T22:15:02.517 回答
2

理想情况下,您应该能够在调用之前使用Permissions APIgetUserMedia()来查明用户是否已经授予或拒绝对相机和麦克风的访问权限,但这在占用户很大一部分的Safari 上尚不可用。getUserMedia()以下任何一种情况调用都会报错:

  • 用户点击“阻止”并且不允许摄像头/麦克风访问
  • 浏览器本身没有访问摄像头或麦克风的系统权限(macOS 常见)
  • 另一个像 Zoom 这样的应用程序已经在使用视频流(在 Windows 上很常见)
  • ...和更多

在用户解决问题后,您可能希望在任何这些情况下再次提示权限。

Philippe Sultan 的使用答案getUserMedia()是在所有浏览器中提示摄像头和麦克风权限的绝佳解决方案。不幸的是,来自浏览器和操作系统的错误getUserMedia()非常不一致。Chrome 将出现“NotReadableError”和“NotAllowedError”,而 Firefox 出现“NotFoundError”或“NotAllowedError”。Firefox 是唯一带有任何类型错误文档的浏览器。

您可以使用该mic-check软件包来请求摄像头和麦克风的权限。它将检查浏览器/操作系统以将所有错误分组到更多用户可操作的错误类别中,例如 UserPermissionDenied、SystemPermissionDenied 和 CouldNotStartVideoSource。

npm i mic-check使用或安装它yarn add mic-check

将其与以下代码一起使用:

import {
  MediaPermissionsError
  MediaPermissionsErrorType,
  requestMediaPermissions
} from 'mic-check';

requestMediaPermissions()
    .then(() => {
        // can successfully access camera and microphone streams
        // DO SOMETHING HERE
    })
    .catch((err: MediaPermissionsError) => {
        const { type, name, message } = err;
        if (type === MediaPermissionsErrorType.SystemPermissionDenied) {
            // browser does not have permission to access camera or microphone
        } else if (type === MediaPermissionsErrorType.UserPermissionDenied) {
            // user didn't allow app to access camera or microphone
        } else if (type === MediaPermissionsErrorType.CouldNotStartVideoSource) {
            // camera is in use by another application (Zoom, Skype) or browser tab (Google Meet, Messenger Video)
            // (mostly Windows specific problem)
        } else {
            // not all error types are handled by this library
        }
    });

希望这可以帮助!您还可以在此处了解有关该问题的更多信息。

于 2021-09-21T00:53:30.167 回答