In my application a user can make calls if he can produce an audio stream. So, I need to require access to the microphone (audio stream). Without it the application should throw an error. Video is optional. So, I call navigator.getUserMedia
and put constraints
like this:
{ audio: true, video: false }
And it throws an error when a microphone is not present, just like I need. But a side effect from this is that if the user also has access to a camera, video is not present in stream.
But if I set both audio
and video
to true
I would have an error in cases when users have a microphone but do not have access to a camera (which is ok according to my application logic)
How I can make a video stream optional get getUserMedia
?
There now exists another way. You can now check directly whether the user has a camera and/or a microphone before calling getUserMedia
:
navigator.mediaDevices.enumerateDevices()
.then(devices => {
const cams = devices.filter(device => device.kind == "videoinput");
const mics = devices.filter(device => device.kind == "audioinput");
const constraints = { video: cams.length > 0, audio: mics.length > 0 };
return navigator.mediaDevices.getUserMedia(constraints);
})
.then(stream => video.srcObject = stream)
.catch(failed);
The other answer works as well, but this may be a bit cleaner.
Note that this is using enumerateDevices
, which returns a list of devices with information. The amount of information returned is limited for privacy reasons ahead of calling getUserMedia
, but it will still reveal whether the user has at least one camera and/or at least one microphone, which is all we need here.
A solution I have found is to call getUserMedia
with video and audio enabled, if the call fails(meaning that they either don't have a camera or a mic) then you call getUserMedia
again from the failure callback that you provide requesting access to the microphone only.
var failedLocalAudioAndVideoStreamCallBack = function (error) {
getUserMedia({ audio: true, video: false },
gotLocalAudioStreamCallBack, failedLocalAudioStreamCallBack )});
}
getUserMedia({ audio: true, video: true },
gotLocalAudioAndVideoStreamCallBack, failedLocalAudioAndVideoStreamCallBack);
Of course, you can handle successes and failures however you like.
NOTE: if there is no camera, the pop-up requesting the initial camera feed(that will fail) never occurs. So, the user will only get one request for access(which makes this solution a tad bit more palatable).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With