在初始拒绝之后用 getUserMedia()提示获取权限

在被拒绝一次之后,如何使用 getUserMedia ()请求摄像头/麦克风访问?

我正在使用 getUserMedia 访问用户的摄像头并将数据导入画布。这一点都没问题。

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

很明显,我们不想因为在每次页面加载时请求摄像头/麦克风的权限被拒绝而惹恼我们的用户。地理定位应用程序已经够烦人了。

然而,一定有办法再次请求它。仅仅因为用户点击拒绝一次并不意味着他们要拒绝摄像头访问所有的时间。

我一直在阅读规格和谷歌周围一段时间,但我没有找到任何明确的关于这个问题。

编辑: 进一步研究表明,在 Chrome 中点击 Deny 会将当前网站添加到一个阻止列表中。这可以通过 chrome 手动访问://设置/内容。滚动到媒体。管理异常,删除被屏蔽的站点。

链接到 chrome://设置/内容不起作用(在这种情况下,我们希望添加一个有用的链接,让人们重新启用权限)。

处理 getUserMedia 权限的整个用户体验都很糟糕。 = (

107582 次浏览

Use HTTPS. When the user gives permission once, it's remembered and Chrome does not ask for permission for that page again and you get access to the media immediately. This does not provide you a way to force the permission bar on the user again, but atleast makes sure you don't have to keep asking for it once the user grants the permission once.

If your app is running from SSL (https://), this permission will be persistent. That is, users won't have to grant/deny access every time.

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

jeffreyveon's answer will help reduce the chance that your user will choose deny, since she will only have to choose once.

In case she does click deny, you can provide a message that explains why you need the permission and how to update her choice. For example:

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

Please be aware of below points.

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.

Chrome implements the Permissions API in navigator.permissions, and that applies to both camera and microphone permissions too.

So as of now, before calling getUserMedia(), you could use this API to query the permission state for your camera and microphone :

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

On success, permissionObj.state would return denied, granted or prompt.

Useful SF question/answer here

For a cross browser solution, one simple approach can be to monitor the time difference between when the getUserMedia() Promise is called, and when it is rejected or resolved, like so :

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

This Medium article gives more details.

Hope this helps!

The updated answer to this is that Chrome (currently testing on 73) no longer continuously prompts for camera access when the request is over HTTP.

Firefox however, does.

Ideally, you should be able to use the Permissions API before calling getUserMedia() to find out if the user has already granted or denied access to the camera and microphone, but this isn't yet available on Safari which accounts for a significant portion of users. Calling getUserMedia() will have an error in any one of the following cases:

  • user clicks "Block" and does not allow camera/microphone access
  • the browser itself does not have system permission to access the camera or microphone (common on macOS)
  • another app like Zoom is using the video stream already (common on Windows)
  • ...and more

You would want to prompt for permissions again in any of these cases after the user has resolved the issue.

Philippe Sultan's answer for using getUserMedia() is a great solution for prompting camera and microphone permissions across all browsers. Unforunately, the errors from getUserMedia() are wildly inconsistent across browsers and OS's. Chrome will have "NotReadableError" and "NotAllowedError" while Firefox is presenting a "NotFoundError" or "NotAllowedError". And Firefox is the only browser with any kind of error documentation.

You can use the mic-check package to request permissions for the camera and microphone. It will check the browser/OS to group all of the errors into more user-actionable error categories, like UserPermissionDenied, SystemPermissionDenied, and CouldNotStartVideoSource.

Install it with npm i mic-check or yarn add mic-check.

Use it with the code below:

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

Hope this helps! You can also learn more about the problem here.