Не удается сменить камеру в мобильном Chrome или Safari во время вызова WebRTC

#android #webrtc

#Android #webrtc

Вопрос:

Я использую navigator.mediaDevices.enumerateDevices для получения списка всех видеоустройств ( element.kind === 'videoinput' ), а затем вызываю navigator.mediaDevices.getUserMedia(constraints) call для поворота видеоустройств (используя DeviceID в качестве ограничения). В Windows Chrome / Firefox все работает нормально, но на телефоне Android (пробовал Samsung, Asus, Huawei с Android 8/9) этот вызов не выполняется для задней камеры с NotReadableError / Не удалось запустить источник видео (для Chrome) или сбой прерывания / Сбой запуска видео (для Firefox). Как ни странно, тот же код работает нормально в iOS / Safari. Также это происходит только тогда, когда вызов WebRTC присутствует в браузере. Если нет вызова, я могу выбрать любое видеоустройство. Также, если я сначала выберу заднюю камеру и попытаюсь установить вызов, это не сработает, я получаю аналогичную ошибку. Я знаю, что это надуманно, но, может быть, у кого-то была такая же / похожая проблема? Все версии браузера обновлены.

[ОБНОВЛЕНИЕ — фрагмент кода и журнал]

 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 amp;amp; s.track.kind === videoTrack.kind;
      });
      const audioSender = pc.getSenders().find(s => {
        return s.track amp;amp; 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 remote device debug:

введите описание изображения здесь

Ошибка «NotReadableError», «Не удалось запустить источник видео», что означает, что Chrome не удалось получить дескриптор базового устройства. Опять же, safari / ios работает нормально.

Ответ №1:

Для мобильных устройств существует специальный способ выбора между передней и задней камерами.

VideoFacingMode https://www.w3.org/TR/mediacapture-streams/#dom-videofacingmodeenum

TL; DR

 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))
    }   
})
  

Это работает для мобильных Safari, Chrome и FF.

ПРИМЕЧАНИЕ

Не забудьте остановить предыдущую видеодорожку перед повторным вызовом getUserMedia with video , иначе вы получите исключение.

Комментарии:

1. Мариуш, спасибо за ответ, но ты на самом деле пробовал это во время вызова WebRTC ? Я пробовал использовать ‘facingMode’, но в моем случае не имеет значения, как я указываю ограничения камеры заднего вида (с помощью DeviceID или facingMode) Я все еще получаю ту же ошибку. Да, я останавливаю треки. Опять же, все в порядке, когда нет вызова WebRTC.

2. Да, у меня это работает. Не могли бы вы вставить свой фрагмент кода, чтобы воспроизвести проблему? Каково описание ошибки? Какой метод выдает исключение?

3. Мариуш, я добавил код и журнал из Chrome remote debug. Ошибка выдается в строке «navigator.mediaDevices.getUserMedia (constraints)» и обрабатывается в предложении promise «catch (e = > …»). Спасибо.

Ответ №2:

Хорошо, итак, я сузил круг поисков до вызова navigator.mediaDevices.getUserMedia() in ngInit() (это приложение Angular). Даже если я удалю весь код в .then() функции-обработчике, эффект будет тот же. Только удаление этого вызова решает проблему. На данный момент не уверен, почему такое поведение, изучит его более тщательно и обновит.

Комментарии:

1. вы нашли что-нибудь еще по этому поводу? Я также сталкиваюсь с той же проблемой

Ответ №3:

Чтобы переключаться между передней и задней камерами на мобильном устройстве, вам необходимо остановить предыдущий поток, прежде чем открывать новый поток.

 if (videoIn.srcObject) {
  videoIn.srcObject.getTracks().forEach((track) => {
  track.stop();
});