首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从HTML画布中获取图像的最快方法

从HTML画布中获取图像的最快方法
EN

Stack Overflow用户
提问于 2020-04-12 23:25:19
回答 1查看 1.3K关注 0票数 1

下面是我的代码,用于从播放视频的画布中捕获图像:

代码语言:javascript
复制
    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 中获取图像的最快方法是什么,它不会成为实时视频转码过程的瓶颈?

EN

回答 1

Stack Overflow用户

发布于 2020-04-13 01:04:19

您可能应该修改您的项目,因为保存整个视频作为静止图像将吹灭大部分设备的内存在短期内。相反,请看一下MediaStreamsMediaRecorder API,它们能够实时地进行代码转换和压缩。您可以通过画布的MediaStream方法请求它。

最快的可能是将一个ImageBitmap发送到您的工作线程,这些线程非常快地从画布(像素缓冲区的简单副本)生成,并且可以传输到您的辅助脚本,在那里您应该能够在OffscreenCanvas上绘制它。

主要缺点:它目前只支持在最新的Chrome和火狐(通过webgl),这不能被多填充.

main.js

代码语言:javascript
复制
else {
  console.log("Adding frame...");
  const bitmap = await createImageBitmap(preview);
  videoWorker.postMessage({ action: "addFrame", data: bitmap }, [bitmap]);
  currIndex++;
}

worker.js

代码语言:javascript
复制
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,它的优点仍然是不停止使用压缩部分的主线程,而且由于它可以传输,所以给工作人员的消息也不会计算太重。

如果您走这条路,您可能希望使用工作线程中的帕科 (它使用PNG图像使用的压缩算法)来压缩数据。

main.js

代码语言:javascript
复制
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

代码语言:javascript
复制
onmessage = (evt) => {
 // ...
 const image = pako.deflate(evt.data.data); // compress to store
 storeImage(image);
};
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61179508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档