Android 在WebRTC呼叫期间,无法在mobile Chrome或Safari中更换摄像头

Android 在WebRTC呼叫期间,无法在mobile Chrome或Safari中更换摄像头,android,webrtc,Android,Webrtc,我使用navigator.mediaDevices.enumerateDevices检索所有视频设备的列表(element.kind==“videoinput”),然后调用navigator.mediaDevices.getUserMedia(约束)调用旋转视频设备(使用deviceId作为约束)。在Windows Chrome/Firefox上一切正常,但在android手机上(试用三星、华硕、华为android 8/9)此呼叫在后置摄像头上失败,出现NotReadable错误/无法启动视频源

我使用
navigator.mediaDevices.enumerateDevices
检索所有视频设备的列表(
element.kind==“videoinput”
),然后调用
navigator.mediaDevices.getUserMedia(约束)
调用旋转视频设备(使用deviceId作为约束)。在Windows Chrome/Firefox上一切正常,但在android手机上(试用三星、华硕、华为android 8/9)此呼叫在后置摄像头上失败,出现NotReadable错误/无法启动视频源(对于Chrome)或中止恐怖/启动视频失败(对于Firefox)。 奇怪的是,同样的代码在iOS/Safari中工作正常。 而且,这仅在浏览器中存在WebRTC调用时发生。如果没有呼叫,我可以选择任何视频设备。 另外,如果我先选择back camera并尝试建立呼叫,则它不起作用,我会得到类似的错误。 我知道这很牵强,但也许有人有相同/类似的问题? 所有浏览器版本都是最新的

[更新-代码段和日志]

switchCamera() {
try {
  if (this.localStream) {
    const tracks = this.localStream.getTracks();
    console.log('switchCamera stopping this.localStream tracks', tracks);
    tracks.forEach((track: MediaStreamTrack) => {
      console.log('switchCamera stopping track', track);
      track.stop();
    });
    console.log('switchCamera stop stream');
  }

  const constraints = {
    audio: true,
    video: { facingMode: this.faceCamera ? 'environment' : 'face' }
  };
  this.faceCamera = !this.faceCamera;
  console.log('switchCamera constraints: ', constraints);
  navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
      console.log('getUserMedia:', stream);
      this.logText('got stream');

      this.localVideo.srcObject = stream;

      const videoTracks = stream.getVideoTracks();
      const audioTracks = stream.getAudioTracks();
      console.log('videoTracks', videoTracks);
      if (videoTracks.length > 0) {
        console.log(`Using video device: ${videoTracks[0].label}`);
      }

      const videoTrack = videoTracks[0];
      const audioTrack = audioTracks[0];

      console.log('Replacing track for pc', videoTrack, audioTrack);

      const pc = this.session.sessionDescriptionHandler.peerConnection;

      const videoSender = pc.getSenders().find(s => {
        return s.track && s.track.kind === videoTrack.kind;
      });
      const audioSender = pc.getSenders().find(s => {
        return s.track && s.track.kind === audioTrack.kind;
      });

      if (videoSender) {
        console.log('videoSender.replaceTrack', videoTrack);
        videoSender.replaceTrack(videoTrack);
      }
      if (audioSender) {
        console.log('audioSender.replaceTrack', audioTrack);
        audioSender.replaceTrack(audioTrack);
      }
    })
    .catch(e => {
      console.log('getUserMedia error:', e.name, e.code, e.message);
    });
} catch (e) {
  window.alert(e);
}
}

这是chrome远程设备调试的日志:

错误为“NotReadableError”,“无法启动视频源”,这意味着chrome无法获取底层设备句柄。。。
同样,safari/ios工作正常…

对于移动设备,有一种专门的方法可以在前后摄像头之间进行选择

VideoFacingMode
-

TL;博士

它适用于移动Safari、Chrome和FF

请记住,在调用前停止上一个视频曲目 再次使用
视频
获取用户媒体
,否则,您将获得 例外


好的,我把范围缩小到调用
ngInit()
(这是Angular应用程序)中的
navigator.mediaDevices.getUserMedia()
。 即使我删除
.then()
处理程序函数中的所有代码,效果也是一样的。 只有删除此呼叫才能解决此问题。
目前还不清楚为什么会有这样的行为,将对其进行更彻底的调查和更新

Mariusz,谢谢你的回答,但你真的在WebRTC通话中试过吗?我确实尝试过“facingMode”,但在我的例子中,无论我如何指定后置摄像头约束(使用deviceId或facingMode),我仍然会得到相同的错误。是的,我会停下来。同样,当没有WebRTC调用时,一切都正常。是的,它对我有效。你能粘贴你的代码片段来重现这个问题吗?错误描述是什么?哪种方法引发异常?Mariusz,我已经添加了来自chrome远程调试的代码和日志。错误被抛出到“navigator.mediaDevices.getUserMedia(constraints)”行,并在promise“catch(e=>…”)子句中处理。谢谢
window.navigator.mediaDevices.enumerateDevices().then(devices => {
    if (devices.filter(device => device.kind === 'videoinput').length > 1) {
        navigator.mediaDevices.getUserMedia({video: {facingMode: 'user' /*'environment'*/}}).then(console.log.bind(this))
    }   
})