[英]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.