ImageCapture API 的替代品以获得更好的浏览器支持
Alternative for the ImageCapture API for better browser support
我使用 OCR 来识别图像中的文本。我使用 ImageCapture API from a MediaStream 从用户的 camera/video 输入中获取 photos/snapshots。这是负责的代码:
function getBlobFromMediaStream() {
const videoTrack = mediaStream.getVideoTracks()[0]
const imageCapture = new ImageCapture(videoTrack);
return imageCapture.takePhoto().then(blob => {
if (!blob) throw "Photo could not be taken";
return blob;
})
}
太糟糕了,这个 API 不适用于许多浏览器(Firefox、IE、Safari)。有没有可以使用的替代品?
您可以使用 HTMLVideoElement
和 HTMLCanvasElement
进行后备。
首先通过检查 window 对象中是否存在构造函数来检查您的浏览器是否支持 MediaStream Image Capture API。
if ('ImageCapture' in window) {
// Has support for API.
} else {
// No support, use fallback.
}
然后基于此使用 API 或使用您的后备。
在回退中创建一个视频元素、canvas 元素和一个 canvas 上下文。将 MediaStreamTrack
设置为视频元素的 srcObject
。该视频能够解码数据并制作实际图片。
使用视频的图像通过CanvasRenderingContext2D.drawImage()
方法将图像绘制到canvas元素。这样,canvas 元素将绘制视频中当前帧的图像。
现在您可以提取在 canvas 上绘制的数据,并使用 HTMLCanvasElement.toBlob()
方法将其转换为 Blob
。
将函数调用包装在 Promise
中有两个原因:
- 您需要从回调中提取 blob,Promise 包装器可以帮助您完成此操作。
ImageCapture.takePhoto()
方法也是 returns 一个 Promise。因此,您将拥有与支持 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) => {
video.addEventListener('loadeddata', async () => {
const { videoWidth, videoHeight } = video;
canvas.width = videoWidth;
canvas.height = videoHeight;
try {
await video.play();
context.drawImage(video, 0, 0, videoWidth, videoHeight);
canvas.toBlob(resolve, 'image/png');
} catch (error) {
reject(error);
}
});
});
}
}
像下面的例子一样调用你的函数。我已经放弃了 throw
语句,这样当您调用 getBlobFromMediaStream
函数时,所有 rejected 状态都将在同一点被捕获。
根据 ImageCapture.takePhoto()
的文档,您要么在承诺已履行时得到一个 Blob
,而在它被拒绝时得到一个错误。
回退也是如此。唯一的区别是,如果 canvas 的位图不是原点干净的,HTMLCanvasElement.toBlob()
函数会抛出 SecurityError
。
getBlobFromMediaStream(mediaStream).then(blob => {
// Work with your blob.
}).catch(error => {
console.log(`Photo could not be taken. ${error}`);
})
我使用 OCR 来识别图像中的文本。我使用 ImageCapture API from a MediaStream 从用户的 camera/video 输入中获取 photos/snapshots。这是负责的代码:
function getBlobFromMediaStream() {
const videoTrack = mediaStream.getVideoTracks()[0]
const imageCapture = new ImageCapture(videoTrack);
return imageCapture.takePhoto().then(blob => {
if (!blob) throw "Photo could not be taken";
return blob;
})
}
太糟糕了,这个 API 不适用于许多浏览器(Firefox、IE、Safari)。有没有可以使用的替代品?
您可以使用 HTMLVideoElement
和 HTMLCanvasElement
进行后备。
首先通过检查 window 对象中是否存在构造函数来检查您的浏览器是否支持 MediaStream Image Capture API。
if ('ImageCapture' in window) {
// Has support for API.
} else {
// No support, use fallback.
}
然后基于此使用 API 或使用您的后备。
在回退中创建一个视频元素、canvas 元素和一个 canvas 上下文。将 MediaStreamTrack
设置为视频元素的 srcObject
。该视频能够解码数据并制作实际图片。
使用视频的图像通过CanvasRenderingContext2D.drawImage()
方法将图像绘制到canvas元素。这样,canvas 元素将绘制视频中当前帧的图像。
现在您可以提取在 canvas 上绘制的数据,并使用 HTMLCanvasElement.toBlob()
方法将其转换为 Blob
。
将函数调用包装在 Promise
中有两个原因:
- 您需要从回调中提取 blob,Promise 包装器可以帮助您完成此操作。
ImageCapture.takePhoto()
方法也是 returns 一个 Promise。因此,您将拥有与支持 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) => {
video.addEventListener('loadeddata', async () => {
const { videoWidth, videoHeight } = video;
canvas.width = videoWidth;
canvas.height = videoHeight;
try {
await video.play();
context.drawImage(video, 0, 0, videoWidth, videoHeight);
canvas.toBlob(resolve, 'image/png');
} catch (error) {
reject(error);
}
});
});
}
}
像下面的例子一样调用你的函数。我已经放弃了 throw
语句,这样当您调用 getBlobFromMediaStream
函数时,所有 rejected 状态都将在同一点被捕获。
根据 ImageCapture.takePhoto()
的文档,您要么在承诺已履行时得到一个 Blob
,而在它被拒绝时得到一个错误。
回退也是如此。唯一的区别是,如果 canvas 的位图不是原点干净的,HTMLCanvasElement.toBlob()
函数会抛出 SecurityError
。
getBlobFromMediaStream(mediaStream).then(blob => {
// Work with your blob.
}).catch(error => {
console.log(`Photo could not be taken. ${error}`);
})