Вы можете сделать откат с HTMLVideoElement
и HTMLCanvasElement
.
Сначала проверьте, поддерживает ли ваш браузер API захвата изображений MediaStream, проверив, существует ли конструктор в объекте окна.
if ('ImageCapture' in window) {
// Has support for API.
} else {
// No support, use fallback.
}
Затем в зависимости от этого либо используйте API, либо используйте резервный вариант.
В резервном варианте создайте элемент видео, элемент холста и контекст холста. Установите MediaStreamTrack
как srcObject
видеоэлемента. Видео может декодировать данные и создавать реальное изображение.
Затем используйте изображение видео, чтобы нарисовать изображение на элементе холста с помощью метода CanvasRenderingContext2D.drawImage()
. Теперь текущий кадр видео был нарисован на элементе холста.
Теперь вы можете извлечь данные, которые были нарисованы на холсте, и превратить их в большой двоичный объект с помощью HTMLCanvasElement.toBlob()
метод получения Blob
из холста. Оберните вызов функции в Promise
по двум причинам:
- Вам нужно будет извлечь большой двоичный объект из обратного вызова, в этом вам может помочь оболочка Promise.
ImageCapture.takePhoto()
метод также возвращает обещание. Таким образом, у вас будет такое же поведение, как и при поддержке API.
Все вместе это будет выглядеть так.
function getBlobFromMediaStream(stream) {
if ('ImageCapture' in window) {
const videoTrack = stream.getVideoTracks()[0];
const imageCapture = new ImageCapture(videoTrack);
return imageCapture.takePhoto();
} else {
const video = document.createElement('video');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
video.srcObject = stream;
return new Promise((resolve, reject) => {
try {
video.addEventListener('loadeddata', event => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
video.play().then(() => {
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
canvas.toBlob(resolve, 'image/png');
});
});
} catch(error) {
reject(error);
}
});
}
}
Затем вызовите свою функцию как Ниже. Я отказался от оператора throw
, чтобы все отклоненные состояния были пойманы в один и тот же момент, когда вы вызываете функцию getBlobFromMediaStream
. Кроме того, согласно документации, вы получаете либо Blob
, когда обещание выполнено, либо ошибку, когда оно отклонено.
То же самое касается и отката. Единственная разница в том, что функция HTMLCanvasElement.toBlob()
выдает SecurityError
, если растровое изображение холста не является чистым.
getBlobFromMediaStream(mediaStream).then(blob => {
// Work with your blob.
}).catch(error => {
console.log(`Photo could not be taken. ${error}`);
})