我正在通过使用最新的Chrome Windows版本同时访问2个摄像头来编写Webrtc chrome桌面应用程序。
可以通过navigator.mediaDevices.enumerateDevices()访问摄像机列表,但是无法使用navigator.mediaDevices.getUserMedia通过其特定ID访问这些设备。
它仅在某些时候发生。但在捕获中没有错误。
因此,我尝试了navigator.mediaDevices.getUserMedia是否确实存在。
if(navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia){ }
是的。
只是在调用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);
}
答案 0 :(得分:2)
@Kaiido是正确的,resolve
在此处的for循环中被调用,该循环遍地都是,并且在所有代码完成之前。此点之后的任何错误基本上都会丢失。
这是promise constructor anti-pattern。简而言之:不要在promise构造函数中编写应用程序代码。不要向下传递resolve
和reject
函数。相反,让函数将承诺返回给您,并在所有then
回调中添加所有应用程序代码。然后返回所有诺言,使它们形成一条链。只有这样,错误才能正确传播。
有关更多信息,请参见Using promises on MDN。