#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
withvideo
, иначе вы получите исключение.
Комментарии:
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();
});