[英]getUserMedia and NotReadableError with iOS Safari 13
Edit : camera access was automatically allowed when I hosted my site with https on Github.编辑:当我在 Github 上使用 https 托管我的网站时,自动允许摄像头访问。 However streaming is still not working properly, I'll make another question about that.
但是流媒体仍然无法正常工作,我将对此提出另一个问题。
I have followed a tutorial on getUserMedia API.我遵循了关于 getUserMedia API 的教程。 It works fine on my desktop Chrome and Safari.
它在我的桌面 Chrome 和 Safari 上运行良好。 I have now created a tunnel from localhost 8080 with ngrok ( https://....ngrok.io) and I'm able to see my app on my phone with Safari 13.
我现在已经使用 ngrok(https://....ngrok.io)从 localhost 8080 创建了一个隧道,并且我可以使用 Safari 13 在我的手机上看到我的应用程序。
However, it does not react when I press the "play" button that opens webcam on desktop version.但是,当我按下在桌面版本上打开网络摄像头的“播放”按钮时,它没有反应。 When I inspect the Safari console from myiPhone, it gives me this error
当我从 myiPhone 检查 Safari 控制台时,它给了我这个错误
Unhandled Promise Rejection: NotReadableError: The I/O read operation failed.
from index.js:76, which is const stream = await navigator.mediaDevices.getUserMedia(constraints);
来自 index.js:76,即
const stream = await navigator.mediaDevices.getUserMedia(constraints);
I wonder if anyone could help with this?我想知道是否有人可以帮助解决这个问题? I'll attach my index.js code below.
我将在下面附上我的 index.js 代码。 I wonder if I need to add something that asks for user's permission to use the camera?
我想知道是否需要添加一些要求用户允许使用相机的内容?
Also: I know that getUserMedia API might get tricky to use.另外:我知道 getUserMedia API 可能很难使用。 My original plan included an app that can access users rear camera and classify content with Tensorflow.js in my browser (browser because I would want to have a server connection).
我最初的计划包括一个可以访问用户后置摄像头并在我的浏览器中使用 Tensorflow.js 对内容进行分类的应用程序(浏览器,因为我想要一个服务器连接)。 If anyone has alternative tips for doing something similar I'm really happy to hear!
如果有人有做类似事情的替代技巧,我真的很高兴听到!
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();
Several possible issues.几个可能的问题。
image/webp
as a MIME type. image/webp
作为 MIME 类型。 See here .screenshotImage.src = canvas.toDataURL('image/jpeg')
or screenshotImage.src = canvas.toDataURL('image/png')
if you need lossless coding.screenshotImage.src = canvas.toDataURL('image/jpeg')
或screenshotImage.src = canvas.toDataURL('image/png')
。ideal
values.ideal
值。getUserMedia()
in Safari is a bit like the proverbial talking donkey. getUserMedia()
有点像众所周知的会说话的驴。 It's not astounding it works badly, it's astounding it works at all.getUserMedia()
something like this.getUserMedia()
上的 catch 处理程序。let devices
try {
devices = await navigator.mediaDevices.enumerateDevices();
} catch (error) {
console.error(error)
}
because gUM is likely to throw errors.因为 gUM 可能会抛出错误。 And, of course to see the console on mobile safari you have to use desktop Safari to debug it.
而且,当然要在移动 safari 上查看控制台,您必须使用桌面 Safari 进行调试。 Lots of tutorials explain this.
很多教程解释了这一点。 Here's just one.
这里只有一个。 https://appletoolbox.com/use-web-inspector-debug-mobile-safari/
https://appletoolbox.com/use-web-inspector-debug-mobile-safari/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.