简体   繁体   English

Node.js - 将数据缓冲到Ffmpeg

[英]Node.js - Buffer Data to Ffmpeg

I used Node.js and Ffmpeg to create animations. 我使用Node.js和Ffmpeg来创建动画。 Because I was trying to avoid third-party avi/mp4 parsers, I decided to output the animation as raw rgb24 data file and then use some program to convert it to mp4 file. 因为我试图避免使用第三方avi / mp4解析器,所以我决定将动画输出为原始的rgb24数据文件,然后使用某些程序将其转换为mp4文件。

I found that Ffmpeg is free and open source which can do exactly it. 我发现Ffmpeg是免费的开源软件,它可以做到这一点。 So, I made a Node.js application which allocates a Buffer of size 1920 x 1080 x 3 (width times height times number of bytes per pixel), then I created a rendering context library, and finally I animated frame by frame and saved each frame consecutivelly in a binary file (using fs module). 所以,我创建了一个Node.js应用程序,它分配一个大小为1920 x 1080 x 3Buffer (宽度乘以高度乘以每个像素的字节数),然后我创建了一个渲染上下文库,最后我逐帧动画并保存每个连续帧在二进制文件中(使用fs模块)。

Then I invoked Ffmpeg to convert it to mp4 file and it works very good. 然后我调用Ffmpeg将其转换为mp4文件,它的效果非常好。 Animations are pretty easy to make and Ffmpeg does its job correctly. 动画很容易制作,Ffmpeg正确地完成它的工作。

However, the only problem is because it is very slow and eats space on hard disk. 但是,唯一的问题是因为它非常慢并且在硬盘上占用空间。 I want to create very long animations (more than a hour). 我想创建很长的动画(超过一个小时)。 The final mp4 file is relativelly small, but raw video file is extremelly big. 最终的mp4文件相对较小,但原始视频文件非常大。 About ninety percents of each frame are black pixels, so Ffmpeg comress it very good, but raw file cannot be compressed and it takes sometimes mor ethan 100 Gigabytes. 每帧大约百分之九十是黑色像素,因此Ffmpeg非常好,但原始文件无法压缩,有时需要100兆字节。 Also, there is very unnecessary double processing same data. 此外,还有非常不必要的双重处理相同的数据。 Firstly I process it in Node.js to save data to file, and then Ffmpeg reads it to convert it to mp4. 首先,我在Node.js中处理它以将数据保存到文件,然后Ffmpeg读取它以将其转换为mp4。 There is a lot of unnecessary work. 有很多不必要的工作。

So, I'm looking for a way (and I'm pretty sure it is possible, but I didn't find a way to do it yet) to output raw video data (one frame at a time) to Ffmpeg process (without saving anything to the hard disk). 所以,我正在寻找一种方法(而且我很确定它有可能,但我还没有办法做到这一点)将原始视频数据(一次一帧)输出到Ffmpeg过程(没有将任何东西保存到硬盘上。

My goal is to do the following: 我的目标是做到以下几点:

  1. Open Ffmpeg process 打开Ffmpeg进程
  2. Render a frame in Node.js 在Node.js中渲染一个帧
  3. Output raw byte stream to Ffmpeg 将原始字节流输出到Ffmpeg
  4. Wait for Ffmpeg to encode it and append to mp4 file 等待Ffmpeg对其进行编码并附加到mp4文件
  5. Let Ffmpeg wait for my Node.js process to render next frame 让Ffmpeg等待我的Node.js进程渲染下一帧

Is there a way to achieve it? 有没有办法实现它? I really don't see a reason to post code, because my current code has nothing to do with the question I'm asking here. 我真的没有理由发布代码,因为我当前的代码与我在这里问的问题无关。 I don't struggle with syntax errors or implementation problems . 我不会遇到语法错误或实现问题 No, instead I just don't know which parameters to pass to Ffmpeg process in order to achieve what I've already explained. 不,我只是不知道哪些参数传递给Ffmpeg进程以实现我已经解释过的内容。

I've searched in documentation to find out which parameters I need to pass to Ffmpeg process in order to let it read raw data from stdin instead from file, and also to wait until my Node.js process render next frame (so to disable time limit) because rendering a frame may take more than 24 hours. 我在文档中搜索了一下我需要传递给Ffmpeg进程的参数,以便让它从stdin而不是从文件中读取原始数据,并等到我的Node.js进程渲染下一帧(所以要禁用时间)限制)因为渲染帧可能需要超过24小时。 Therefore, Ffmpeg process should wait without time limit. 因此,Ffmpeg进程应该没有时间限制。 However, I didn't find anything about it in documentation. 但是,我在文档中没有找到任何相关内容。

I know how to write to stdin from Node.js and similar technical stuff, so no need to explain it. 我知道如何从Node.js和类似的技术内容写入stdin,所以不需要解释它。 The only question(s) here: 这里唯一的问题是:

  1. Which parameters to pass to Ffmpeg? 哪些参数传递给Ffmpeg?
  2. Do I need to create Ffmpeg process (using child_process ) with some special options? 我是否需要使用一些特殊选项创建Ffmpeg进程(使用child_process )?

Thank you in advance. 先感谢您。 Please, take it easy, this is my first question! 请放轻松,这是我的第一个问题! :) :)

As suggested by @Mulvya and @estus, the correct parameter is -i - (to enable input from stdin): 正如@Mulvya和@estus所建议的那样,正确的参数是-i - (从stdin启用输入):

'use strict';

var cp = require('child_process');

var proc = cp.spawn('ffmpeg', [
  '-hide_banner',
  '-f', 'rawvideo',
  '-pix_fmt', 'rgb24',
  '-s', '2x2',
  '-i', '-',
  '1.png'
]);

proc.stdin.write(Buffer.from([
  255, 0, 0,
  0, 255, 0,
  0, 255, 255,
  255, 0, 255
]));

proc.stdin.end();

proc.stderr.pipe(process.stdout);

It produces this image: 它产生这个图像:
结果
It works for animations too. 它也适用于动画。

Thanks guys for helping! 谢谢你的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM