getUserMedia differentiating between what hardware is erroring

Viewed 255

I am running a getUserMedia for camera and microphone,

navigator.mediaDevices
          .getUserMedia({audio:true, video: true)
          .then((stream) => {})
          .catch((error) => {})

Is there a way to differentiate what device is causing the promise to fail? i.e if its the camera that is unreadable or the mic, are you able to find it's the camera from the error object? I can find anything other than error.name and error.message?

2 Answers

No, unfortunately when you capture from both at the same time, they either both succeed for both fail together.

Many applications will capture the audio and video separately, and then create a new MediaStream with the tracks from the MediaStreams from each separate device. I have a hunch that this can lead to synchronization problems in the cases where the audio/video are sent a single stream from the device internally, but haven't proven this. It must not be a significant problem, at least for video conferencing, as this is what Google does for Hangouts/Meet.

What sorts of errors do you want to detect?

If your machine doesn't have the hardware (camera, mic) it needs to make your MediaStream, you can find this out by using .enumerateDevices() before you try to use .getUserMedia(). A function like this might give you the information you need for an {audio: true, video:true} MediaStream.

async function canIDoIt () { 
    const devices = await navigator.mediaDevices.enumerateDevices()
    let hasAudio = false
    let hasVideo = false
    devices.forEach(function(device) {
        if (device.kind === 'videoinput') hasVideo = true
        if (device.kind === 'audioinput') hasAudio = true
    })
    return hasAudio && hasVideo
}

Using that is a good start for a robust media app: you can tell your user they don't have the correct hardware right away before diving into to the arcana of the errors thrown by .getUserMedia().

If your user denies permission to .getUserMedia() access their media devices, it will throw an error with error.message containing the string "permission denied". Keep in mind that when the user denies permission, your program doesn't get back much descriptive information about the devices. Because cybercreeps.

If your user's devices cannot handle the constraints you present to .getUserMedia(), you'll get "constraint violation" in the error.message string. The kinds of device constraints you can violate are things like

{video: { width:{exact:1920},
         height:{exact:1080}}}

Avoiding exact in your constraints reduces the chance of constraint violations. Instead you can give something like this.

{video: { width:{min:480, ideal: 720, max: 1920},
         height:{min:270, ideal:1280, max: 1040}}}

Other errors are probably more specific to a particular machine and browser. In practically all cases the thrown error object contains an explanatory error.message.

Related