Изменить : доступ к камере был автоматически разрешен, когда я разместил свой сайт с https на Github. Однако потоковая передача по-прежнему не работает должным образом, я задам еще один вопрос по этому поводу.
Я следил за учебником по getUserMedia API. Он отлично работает на моем рабочем столе Chrome и Safari. Теперь я создал туннель от localhost 8080 с помощью ngrok (https://....ngrok.io), и я могу видеть свое приложение на своем телефоне с помощью Safari 13.
Однако оно не реагирует, когда я нажимаю кнопку «play "кнопка, открывающая веб-камеру в настольной версии. Когда я проверяю консоль Safari из своего iPhone, я получаю эту ошибку
Unhandled Promise Rejection: NotReadableError: The I/O read operation failed.
из индекса. js: 76, что составляет const stream = await navigator.mediaDevices.getUserMedia(constraints);
Интересно, есть ли у кого-нибудь может помочь с этим? Прикреплю свой index. js код ниже. Интересно, нужно ли мне добавить что-то, что запрашивает разрешение пользователя на использование камеры?
Также: я знаю, что использовать getUserMedia API может быть сложно. В мой первоначальный план входило приложение, которое может получать доступ к задней камере пользователей и классифицировать контент с помощью Tensorflow. js в моем браузере (браузер, потому что я хотел бы иметь соединение с сервером). Если у кого-то есть альтернативные советы, как сделать что-то подобное, я очень рад слышать!
const controls = document.querySelector('.controls');
const cameraOptions = document.querySelector('.video-options>select');
const video = document.querySelector('video');
const canvas = document.querySelector('canvas');
const screenshotImage = document.querySelector('img');
const buttons = [...controls.querySelectorAll('button')];
let streamStarted = false; // was false
const [play, pause, screenshot] = buttons;
const constraints = {
video: {
width: {
min: 224,
ideal: 224,
max: 224,
},
height: {
min: 224,
ideal: 224,
max: 224
},
}
};
cameraOptions.onchange = () => {
const updatedConstraints = {
...constraints,
deviceId: {
exact: cameraOptions.value
}
};
startStream(updatedConstraints);
};
play.onclick = () => {
if (streamStarted) {
video.play();
play.classList.add('d-none');
pause.classList.remove('d-none');
return;
}
if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
const updatedConstraints = {
...constraints,
deviceId: {
exact: cameraOptions.value
}
};
startStream(updatedConstraints);
console.log("Camera available")
}
};
const pauseStream = () => {
video.pause();
play.classList.remove('d-none');
pause.classList.add('d-none');
};
const doScreenshot = () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
screenshotImage.src = canvas.toDataURL('image/webp');
screenshotImage.classList.remove('d-none');
};
pause.onclick = pauseStream;
screenshot.onclick = doScreenshot;
const startStream = async (constraints) => {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleStream(stream);
};
const handleStream = (stream) => {
video.srcObject = stream;
play.classList.add('d-none');
pause.classList.remove('d-none');
screenshot.classList.remove('d-none');
};
const getCameraSelection = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(device => device.kind === 'videoinput');
const options = videoDevices.map(videoDevice => {
return `<option value="${videoDevice.deviceId}">${videoDevice.label}</option>`;
});
cameraOptions.innerHTML = options.join('');
};
getCameraSelection();