NodeJS 将视频帧从ffmpeg传输到canvas,而无需将整个视频加载到内存中

xqk2d5yq  于 5个月前  发布在  Node.js
关注(0)|答案(1)|浏览(65)

我正在做一个涉及帧操作的项目,我决定为此选择节点画布API。我曾经使用OpenCV Python,有一个cv2.VideoCapture类,它将视频作为输入,并准备读取视频的帧,我们可以一次循环一个帧,而无需将所有帧同时加载到内存中。现在我尝试了很多方法来复制相同的帧使用FFMPEG,即试图以有序但“按需”的方式从视频加载帧。
我尝试使用ffmpeg作为子进程来处理帧并突出帧。

const spawnProcess = require('child_process').spawn,
    ffmpeg = spawnProcess('ffmpeg', [
        '-i', 'test.mp4',
        '-vcodec', 'png',
        '-f', 'rawvideo',
        '-s', '1920*1080', // size of one frame
        'pipe:1'
    ]);
ffmpeg.stdout.on('data', (data) => {
    try {
        // console.log(tf.node.decodeImage(data).shape)
        console.log(`${++i} frames read`)
        //context.drawImage(data, 0, 0, width, height)
        
        
    } catch(e) {
        console.log(e)
    } 
})

字符串
控制台中的值显示了大约4000 +控制台日志,但视频只有150帧,经过大量调查和控制台记录数据,我发现这是缓冲区数据,它并没有为每帧处理它。on-data函数以非结构化的方式返回缓冲区数据我想从视频中读取帧并在内存中一次处理每一帧,我不想一次在内存或文件系统中保存所有的帧。
x1c 0d1x的数据
我还希望以一种可以使用drawImage在画布上渲染的格式来管道这些帧

d8tt03nd

d8tt03nd1#

我发现这是缓冲区数据,它没有处理它的每一帧。
正确.
on-data函数以非结构化的方式返回缓冲区数据。我希望从视频中读取帧,并在内存中一次处理一个帧
您不能依赖STDIO进行 Dataframe 处理。您所在的系统控制着应用程序之间的缓冲工作方式。因此,您获取的数据量及其计时应被视为未定义。您必须在应用程序中缓冲数据。
现在,您不需要太多的缓冲区,也不需要太复杂的方案。只需缓冲到足够的字节数等于或大于原始帧所需的字节数即可。然后,对该帧执行任何需要的操作,将其从缓冲区中删除,并继续缓冲下一帧。
由于您使用的是JavaScript,因此可以考虑使用streams API来实现这一点,这样可以更容易地处理反压力等问题。(毕竟,您的应用程序实际上可能比FFmpeg的处理速度慢,您可能希望在应用程序运行时降低该流的速度,这样就不会耗尽内存。)

  • TransformStream-在浏览器和Node.js中工作,但需要一些设置才能与Node.js ChildProcess STDIO流一起工作。
  • node:stream/Transform -内置的Node.js流。很容易使用,但是不能在浏览器中使用,所以如果你要构建一个库供其他人使用,请记住这一点。

相关问题