[英]Fastest way to capture image from a HTML Canvas
这是我从 Canvas 播放视频中捕获图像的代码:
let drawImage = function(time) {
prevCtx.drawImage(videoPlayer, 0, 0, w, h);
requestAnimationFrame(drawImage);
}
requestAnimationFrame(drawImage);
let currIndex = 0;
setInterval(function () {
if(currIndex === 30) {
currIndex = 0;
console.log("Finishing video...");
videoWorker.postMessage({action : "finish"});
} else {
console.log("Adding frame...");
// w/o this `toDataURL` this loop runs at 30 cycle / second
// so that means, this is the hot-spot and needs optimization:
const base64img = preview.toDataURL(mimeType, 0.9);
videoWorker.postMessage({ action: "addFrame", data: base64img});
currIndex++;
}
}, 1000 / 30)
目标是在每 30 帧(应该是 1 秒)时触发对添加的帧进行转码。
这里的问题是preview.toDataURL(mimeType, 0.9);
至少增加 1 秒,没有它,日志显示currIndex === 30
每秒触发一次。 能够捕获至少大约 30 FPS 图像的最佳方法是什么。 从 HTML Canvas 捕获图像的最快方法是什么,它不会成为实时视频转码过程的瓶颈?
您可能应该修改您的项目,因为将整个视频保存为静止图像会立即炸毁大多数设备的 memory。 相反,请查看能够实时进行转码和压缩的MediaStreams和MediaRecorder API。 您可以通过其captureStream()
方法从 canvas 请求 MediaStream。
最快的可能是将ImageBitmap发送到您的 Worker 线程,从 canvas(像素缓冲区的简单副本)生成这些非常快,并且可以传输到您的工作脚本,您应该可以从那里绘制它一个 OffscreenCanvas。
主要缺点:目前仅在最新的 Chrome 和 Firefox 中支持(通过 webgl),并且不能填充...
main.js
else {
console.log("Adding frame...");
const bitmap = await createImageBitmap(preview);
videoWorker.postMessage({ action: "addFrame", data: bitmap }, [bitmap]);
currIndex++;
}
worker.js
const canvas = new OffscreenCanvas(width,height);
const ctx = canvas.getContext('2d'); // Chrome only
onmessage = async (evt) => {
// ...
ctx.drawImage( evt.data.data, 0, 0 );
const image = await canvas.convertToBlob();
storeImage(image);
};
另一种选择是传输ImageData数据。 不如 ImageBitmap 快,它仍然具有不停止压缩部分的主线程的优点,并且由于它可以传输,因此发送给 Worker 的消息也不会计算繁重。
如果您是 go 这条路,您可能希望使用 Worker 线程中的类似pako (使用 PNG 图像使用的压缩算法)之类的东西来压缩数据。
main.js
else {
console.log("Adding frame...");
const img_data = prevCtx.getImageData(0,0,width,height);
videoWorker.postMessage({ action: "addFrame", data: img_data }, [img_data.data]);
currIndex++;
}
worker.js
onmessage = (evt) => {
// ...
const image = pako.deflate(evt.data.data); // compress to store
storeImage(image);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.