Thura Aung
Thura Aung

Reputation: 93

Is there any reason why no error found in calling navigator.mediaDevices.getUserMedia

I'm writing Webrtc chrome desktop app by accessing 2 camera simultaneously using latest Chrome Windows version.

Accessing camera list by navigator.mediaDevices.enumerateDevices() is ok but accessing these device by their specific id using navigator.mediaDevices.getUserMedia not work.

It only occurs sometimes. But no error in the catch.

So, I tried navigator.mediaDevices.getUserMedia is really exists or not.

if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { }

Yes, it was.

Just not getting any log info in calling navigator.mediaDevices.getUserMedia()

getVideoSources_ = function() {
    return new Promise(function(resolve, reject) {
        if (typeof navigator.mediaDevices.enumerateDevices === 'undefined') {
            alert('Your browser does not support navigator.mediaDevices.enumerateDevices, aborting.');
            reject(Error("Your browser does not support navigator.mediaDevices.enumerateDevices, aborting."));
            return;
        }

        requestVideoSetTimeout = 500;
        navigator.mediaDevices.enumerateDevices().then((devices) => {

            // get the list first by sorting mibunsho camera in first place
            for (var i = 0; i < devices.length; i++) {
                log("devices[i]", JSON.stringify(devices[i]));
                log("devices[i].label", devices[i].label);
                if (devices[i].kind === 'videoinput' && devices[i].deviceId && devices[i].label) {
                    if (devices[i].label.indexOf("USB_Camera") > -1) {
                        deviceList[1] = devices[i];
                    } else {
                        deviceList[0] = devices[i];
                    }
                }
            }

            // request video by sorted plan
            for (var i = 0; i < deviceList.length; i++) {
                requestVideo_(deviceList[i].deviceId, deviceList[i].label, resolve, reject);
                requestVideoSetTimeout = 1000; // change requestVideoSetTimeout for next video request
            }
        }).catch((err) => {
            log("getVideoSources_:" + err.name + ": " + err.message);
            reject(Error("getVideoSources_ catch error"));
        });
    });
}
getVideoSources_().then(function(result) {
    ....
}).catch(function(err) {
    ....
});

function requestVideo_(id, label, resolve, reject) {
    if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        log("navigator.mediaDevices.getUserMedia found!");

        navigator.mediaDevices.getUserMedia({
            video: {
                deviceId: {exact: id},
                width: 640,
                height: 480,
                frameRate: {
                    ideal: 20,
                    max: 20
                }
            },
            audio: false}).then(
            (stream) => {
                log("***requestVideo_", id);
                log("***requestVideo_", label);
                log("***requestVideo_", stream);
          // USB_Camera is face camera
          if (label.indexOf("USB_Camera") > -1) {
            log("***requestVideo_001");
            myStream2 = stream;
            log("***requestVideo_myStream2", myStream2);
          } else {
            log("***requestVideo_002");
            myStream = stream;
            log("***requestVideo_myStream", myStream);
            getUserMediaOkCallback_(myStream, label);
          }
          resolve("###Video Stream got###");

          stream.getVideoTracks()[0].addEventListener('ended', function(){
            log("***Camera ended event fired. " + id + " " + label);
            endedDevice[id] = label;
          });
      },
      getUserMediaFailedCallback_
      ).catch((error) => {
        log('requestVideo_: ' + error.name);
        reject(Error("requestVideo_ catch error" + error.name));
      });
    }
}

function getUserMediaFailedCallback_(error) {
    log("getUserMediaFailedCallback_ error:", error.name);
    alert('User media request denied with error: ' + error.name);
}

Upvotes: 0

Views: 825

Answers (1)

jib
jib

Reputation: 42500

@Kaiido is right, resolve is called in a for-loop here, which is all over the place, and before all the code has finished. Any error after this point is basically lost.

This is the promise constructor anti-pattern. In short: Don't write app code inside promise constructors. Don't pass resolve and reject functions down. Instead, let functions return promises up to you, and add all app code in then callbacks on them. Then return all promises so they form a single chain. Only then do errors propagate correctly.

See Using promises on MDN for more.

Upvotes: 3

Related Questions