简体   繁体   English

getUserMedia 和 NotReadableError 与 iOS Safari 13

[英]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.几个可能的问题。

  1. Safari doesn't support image/webp as a MIME type. Safari 不支持将image/webp作为 MIME 类型。 See here .这里 Use 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')
  2. Try relaxing your constraints, giving only ideal values.尝试放松你的约束,只给出ideal值。
  3. getUserMedia() in Safari is a bit like the proverbial talking donkey. Safari 中的getUserMedia()有点像众所周知的会说话的驴。 It's not astounding it works badly, it's astounding it works at all.这并不令人惊讶,它的效果很差,令人惊讶的是它完全有效。 You definitely need a catch handler on 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.

相关问题 macOS Safari 问题(getUserMedia)从 angular 中的摄像头获取视频 stream 6 - NotReadableError:I/O 读取操作失败 - macOS Safari problem with (getUserMedia) getting video stream from camera in angular 6 - NotReadableError: The I/O read operation failed 带有 Safari 12 的 WebRTC 中的 NotReadableError - NotReadableError in WebRTC with Safari 12 iOS13 getUserMedia 不适用于 chrome 和 edge - iOS13 getUserMedia not working on chrome and edge 在iOS Safari上借助getUsermedia访问麦克风 - Accessing microphone with the help of getUsermedia on iOS Safari Safari 13 中不再播放音频,除非调用 getUserMedia - Audio doesn't play anymore in Safari 13 unless getUserMedia is called navigator.mediaDevices.getUserMedia 返回 NotReadableError:无法启动视频源 - navigator.mediaDevices.getUserMedia return NotReadableError: Could not start video source 带有 getUsermedia() 的前置摄像头错误错误:“Notreadableerror:无法启动视频源” - Front camera error with getUsermedia() Error: “Notreadableerror: could not start video source” 在 iOS Safari 中,来自 getUserMedia 的权限在一分钟内超时 - In iOS Safari, permissions from getUserMedia time out in a minute 如何解决iOS 11 Safari getUserMedia“无效约束”问题 - How to resolve iOS 11 Safari getUserMedia “Invalid constraint” issue mediaDevices.getUserMedia不适用于iOs 11中的Safari 11(视频为黑色) - mediaDevices.getUserMedia not working with Safari 11 in iOs 11 (video is black)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM