是否可以检查用户是否有摄像头和麦克风以及是否已使用Javascript授予权限?

Ama*_*ony 16 javascript html5 html5-video html5-audio webrtc

我想知道用户的设备是否有连接的摄像头和麦克风,如果是,则授予权限以使用Javascript获取音频和视频流.我想至少在Chrome和Firefox上进行此项检查.什么是一致的API?

Mua*_*han 38

现场演示:

如果用户不允许网络摄像头和/或麦克风,则媒体设备将具有"标签"属性的"空"值.上面的页面将显示以下消息:"请调用getUserMedia一次."

PS.您可以在Chrome控制台开发人员工具中输入"DetectRTC.MediaDevices".

注意:它仅适用于Chrome. Firefox尚未支持类似的API.(更新: Firefox也支持)

2015年12月16日更新

注意:以下代码段适用于Chrome和Firefox.

if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
    // Firefox 38+ seems having support of enumerateDevicesx
    navigator.enumerateDevices = function(callback) {
        navigator.mediaDevices.enumerateDevices().then(callback);
    };
}

var MediaDevices = [];
var isHTTPs = location.protocol === 'https:';
var canEnumerate = false;

if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) {
    canEnumerate = true;
} else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) {
    canEnumerate = true;
}

var hasMicrophone = false;
var hasSpeakers = false;
var hasWebcam = false;

var isMicrophoneAlreadyCaptured = false;
var isWebcamAlreadyCaptured = false;

function checkDeviceSupport(callback) {
    if (!canEnumerate) {
        return;
    }

    if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) {
        navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack);
    }

    if (!navigator.enumerateDevices && navigator.enumerateDevices) {
        navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator);
    }

    if (!navigator.enumerateDevices) {
        if (callback) {
            callback();
        }
        return;
    }

    MediaDevices = [];
    navigator.enumerateDevices(function(devices) {
        devices.forEach(function(_device) {
            var device = {};
            for (var d in _device) {
                device[d] = _device[d];
            }

            if (device.kind === 'audio') {
                device.kind = 'audioinput';
            }

            if (device.kind === 'video') {
                device.kind = 'videoinput';
            }

            var skip;
            MediaDevices.forEach(function(d) {
                if (d.id === device.id && d.kind === device.kind) {
                    skip = true;
                }
            });

            if (skip) {
                return;
            }

            if (!device.deviceId) {
                device.deviceId = device.id;
            }

            if (!device.id) {
                device.id = device.deviceId;
            }

            if (!device.label) {
                device.label = 'Please invoke getUserMedia once.';
                if (!isHTTPs) {
                    device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.';
                }
            } else {
                if (device.kind === 'videoinput' && !isWebcamAlreadyCaptured) {
                    isWebcamAlreadyCaptured = true;
                }

                if (device.kind === 'audioinput' && !isMicrophoneAlreadyCaptured) {
                    isMicrophoneAlreadyCaptured = true;
                }
            }

            if (device.kind === 'audioinput') {
                hasMicrophone = true;
            }

            if (device.kind === 'audiooutput') {
                hasSpeakers = true;
            }

            if (device.kind === 'videoinput') {
                hasWebcam = true;
            }

            // there is no 'videoouput' in the spec.

            MediaDevices.push(device);
        });

        if (callback) {
            callback();
        }
    });
}

// check for microphone/camera support!
checkDeviceSupport(function() {
    document.write('hasWebCam: ', hasWebcam, '<br>');
    document.write('hasMicrophone: ', hasMicrophone, '<br>');
    document.write('isMicrophoneAlreadyCaptured: ', isMicrophoneAlreadyCaptured, '<br>');
    document.write('isWebcamAlreadyCaptured: ', isWebcamAlreadyCaptured, '<br>');
});
Run Code Online (Sandbox Code Playgroud)

  • Firefox 38+具有用于枚举工作不同的设备的API,但在未授予权限时仍会为设备标签返回空值.请参阅此处以获取使用我的帮助程序库来包装不同api的示例:https://www.xdumaine.com/enumerateDevices/test/ (3认同)
  • Firefox尚未支持enumerateDevices或getMediaDevices或MediaStreamTrack.getSources API; 这意味着我们无法检测Firefox是否可以访问麦克风/网络摄像头而无需手动发出getUserMedia请求.每当我们在Firefox中发出getUserMedia请求时,它都会显示权限弹出/下拉,这对现实生活用例来说并不好. (2认同)
  • @MuazKhan 为什么要检查 `!navigator.enumerateDevices &amp;&amp; navigator.enumerateDevices` 呢?不是每次都报错吗? (2认同)

Joh*_*ias 7

1)您应该使用Media Recorder并了解承诺

2) 检查浏览器是否支持enumerateDevices API

if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
  console.log("This browser does not support the API yet");
}
Run Code Online (Sandbox Code Playgroud)
3) 检查用户是否连接了音频和摄像头,唯一的值是“videoinput”、“audioinput”或“audiooutput” DeviceInfo.kind

let checking=["audioinput","videoinput"];
let onlyHas=[];
navigator.mediaDevices.enumerateDevices()
.then((devices)=> {
  let haveAllDevices=true;
  devices.forEach((device)=>{
    onlyHas.push(device.kind);
    if(!(device.kind==checking[0] || device.kind==checking[1])){
    haveAllDevices=false;
    }
   });
   //do something about ...
  
  
  
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});
Run Code Online (Sandbox Code Playgroud)
4)权限被重用,这意味着如果用户已经拒绝了权限,那么当您调用getUserMedia 时,bowser 将不会提示任何内容并拒绝承诺承诺,并抛出DOMException类型的错误,否则它将解决承诺。当承诺拒绝时,可能有多种原因read,其中之一是当用户拒绝访问时,当发生这种情况时,它会抛出一个DOMException 类型NotAllowedError,所以现在我们只对这个错误感兴趣。

如果你阅读DOMException你可以看到你可以访问DOMException.name,这是你应该比较的,所以:

let constraints={audio:true,video:true};
navigator.mediaDevices.getUserMedia(constraints)
  .then((stream)=>{.....})
  .catch((err)=>
    {if(err.name=="NotAllowedError"){console.log("User has denied accessed")}
    });
Run Code Online (Sandbox Code Playgroud)

PS:关于跨浏览器兼容性MediaRecorder至今天09/06/2018只支持chrome和firefox,IE和IOS兄弟不支持 https://caniuse.com/#search=MediaRecorder


ima*_*era 6

是的,很有可能在授予许可后检测麦克风和相机是否可用,

navigator.getUserMedia({ audio: true, video: true},function (stream) {
     if(stream.getVideoTracks().length > 0 && stream.getAudioTracks().length > 0){
         //code for when none of the devices are available                       
     }else{
        // code for when both devices are available
     }
});
Run Code Online (Sandbox Code Playgroud)

  • 替换为 navigator.mediaDevices.getUserMedia (2认同)

Abh*_*gal 6

现在您也可以使用navigator.permissions来检查权限是否已经存在

navigator.permissions.query({ name: "camera" }).then(res => {
    if(res.state == "granted"){
        // has permission
    }
});
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅 MDN。

但请注意,截至 2021 年 1 月,支持尚不完善:

  • Chrome 支持navigator.permissions.queryChrome 43+,支持查询cameramicrophone权限,至少支持Chrome 87+。
  • Firefox 支持navigator.permissions.queryFirefox 46+,但不支持Firefox 84 的查询cameramicrophone权限。
  • Safari 甚至不支持navigator.permissions.query.

  • 不幸的是,这也不适用于 Safari (3认同)