I would like to find out if the user's device has an attached camera and microphone, and if so, has permissions been granted to get the audio and video stream using Javascript. I want to make this check to be made across Chrome and Firefox at the very least. What's a consistent API for this?
Live Demo:
If user didn't allow webcam and/or microphone, then media-devices will be having "NULL" value for the "label" attribute. Above page will show this message: "Please invoke getUserMedia once."
PS. You can type "DetectRTC.MediaDevices" in the Chrome Console developers tool.
Note: It works only in Chrome. Firefox isn't supporting similar API yet. (Updated: Firefox supports as well)
Updated at Dec 16, 2015
Note: Following code snippet works both in Chrome and 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>');
});
Yes it is quite possible to detect whether a microphone and a camera is available after granting the permission,
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
}
});
You can use the MediaStreamTrack which represent a media stream, then you can use its getSources method as explained here: html5rocks
If you don't get any media sources then your client hasn't a webcam. It's not supported by firefox.
Please try my simple cross browser code.
Attention!!! Use https protocol for open web page with my code! Please go to demo
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>Web camera</h1>
<video autoplay></video>
<script>
function errorMessage(message, e) {
console.error(message, typeof e == 'undefined' ? '' : e);
//alert(message);
}
if (location.protocol === 'https:') {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ audio: true, video: true }, function (stream) {
document.querySelector('video').src = window.URL.createObjectURL(stream);
var mediaStreamTrack = stream.getVideoTracks()[0];
if (typeof mediaStreamTrack != "undefined") {
mediaStreamTrack.onended = function () {//for Chrome.
errorMessage('Your webcam is busy!')
}
} else errorMessage('Permission denied!');
}, function (e) {
var message;
switch (e.name) {
case 'NotFoundError':
case 'DevicesNotFoundError':
message = 'Please setup your webcam first.';
break;
case 'SourceUnavailableError':
message = 'Your webcam is busy';
break;
case 'PermissionDeniedError':
case 'SecurityError':
message = 'Permission denied!';
break;
default: errorMessage('Reeeejected!', e);
return;
}
errorMessage(message);
});
} else errorMessage('Uncompatible browser!');
} else errorMessage('Use https protocol for open this page.')
</script>
</body>
</html>
I have tested it into follow browsers:
Windows 10
- Chrome 52
- Edge 25
- Firefox 47
- IE11 Uncompatible browser!
- Opera 39
- Safari 5 Uncompatible browser!
Android
- Chrome 52
- Firefox 48
- Opera 37
1)You should be using Media Recorder and understand promise
2)Check if browser support the API enumerateDevices
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
console.log("This browser does not support the API yet");
}
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);
});
NotAllowedError
, so for now we are only interested in this error.
If you read DOMException you can see you can acces DOMException.name
, this is the one that you should be compared, so:
let constraints={audio:true,video:true};
navigator.mediaDevices.getUserMedia(constraints)
.then((stream)=>{.....})
.catch((err)=>
{if(err.name=="NotAllowedError"){console.log("User has denied accessed")}
});
PS: About cross browser compatibility MediaRecorder as for today 09/06/2018 it is only supported in chrome and firefox, and the brothers IE and IOS don't https://caniuse.com/#search=MediaRecorder
来源:https://stackoverflow.com/questions/30047056/is-it-possible-to-check-if-the-user-has-a-camera-and-microphone-and-if-the-permi