getUserMedia и NotReadableError с iOS Safari 13 - PullRequest
1 голос
/ 09 июля 2020

Изменить : доступ к камере был автоматически разрешен, когда я разместил свой сайт с 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();

1 Ответ

0 голосов
/ 13 июля 2020

Несколько возможных проблем.

  1. Safari не поддерживает image/webp как тип MIME. См. здесь . Используйте screenshotImage.src = canvas.toDataURL('image/jpeg') или screenshotImage.src = canvas.toDataURL('image/png'), если вам нужно кодирование без потерь.
  2. Попробуйте ослабить ограничения, указав только ideal значений.
  3. getUserMedia() в Safari немного похоже на пресловутую речь осел. Не удивительно, что он работает плохо, просто поразительно, что он вообще работает. Вам определенно понадобится обработчик catch на getUserMedia() что-то вроде этого.
let devices
try {
  devices = await navigator.mediaDevices.enumerateDevices();
} catch (error) {
  console.error(error)
}

, потому что gUM может выдавать ошибки. И, конечно же, чтобы увидеть консоль в мобильном сафари, вы должны использовать настольный Safari для ее отладки. Это объясняется во многих обучающих материалах. Вот только один. https://appletoolbox.com/use-web-inspector-debug-mobile-safari/

...