初始拒绝后,使用getUserMedia()重新授予权限

Geu*_*uis 56 javascript webrtc getusermedia

一旦被拒绝,我们如何使用getUserMedia()请求摄像头/麦克风访问?

我正在使用getUserMedia访问用户的摄像头并将数据传输到画布.这一切都很好.

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

我们显然不希望通过在拒绝后的每个页面加载上请求相机/麦克风的权限来惹恼我们的用户.对地理位置api来说已经足够烦人了.

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

我一直在阅读有关规范和谷歌搜索一段时间,但我没有找到任何明确的问题.

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

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

用于处理getUserMedia周围权限的整个UX很糟糕.=(

jef*_*eon 16

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

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

请参阅:http://www.html5rocks.com/en/tutorials/getusermedia/intro/

  • Firefox上的HTTP不会保留此权限. (2认同)
  • 使它在Firefox中工作:`about:config`->将`media.navigator.permission.disabled`标记设置为true,[原始答案](http://stackoverflow.com/a/18230492/3074768) (2认同)

jru*_*ann 14

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
    }
   }
);
Run Code Online (Sandbox Code Playgroud)

  • 不,你不能,幸运的是!!!它将允许网站,应用程序和其他任何东西未经其同意而访问人们的媒体设备,这将构成隐私强奸。 (2认同)
  • 请注意,“navigator.getUserMedia”已弃用,应使用“navigator.mediaDevices .getUserMedia”。[此处的文档](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) (2认同)

moh*_*han 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.


Bri*_* Li 7

理想情况下,您应该能够在调用之前使用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
        }
    });
Run Code Online (Sandbox Code Playgroud)

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


Phi*_*tan 5

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);
 })
Run Code Online (Sandbox Code Playgroud)

如果成功,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);
});
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助!