Node.js - Buffer Data to Ffmpeg

◇◆丶佛笑我妖孽 提交于 2020-12-05 12:47:02

问题


I used Node.js and Ffmpeg to create animations. 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.

I found that Ffmpeg is free and open source which can do exactly it. 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).

Then I invoked Ffmpeg to convert it to mp4 file and it works very good. Animations are pretty easy to make and Ffmpeg does its job correctly.

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. 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. 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. 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).

My goal is to do the following:

  1. Open Ffmpeg process
  2. Render a frame in Node.js
  3. Output raw byte stream to Ffmpeg
  4. Wait for Ffmpeg to encode it and append to mp4 file
  5. Let Ffmpeg wait for my Node.js process to render next frame

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.

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. Therefore, Ffmpeg process should wait without time limit. 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. The only question(s) here:

  1. Which parameters to pass to Ffmpeg?
  2. Do I need to create Ffmpeg process (using child_process) with some special options?

Thank you in advance. Please, take it easy, this is my first question! :)


回答1:


As suggested by @Mulvya and @estus, the correct parameter is -i - (to enable input from 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:
result
It works for animations too.

Thanks guys for helping!



来源:https://stackoverflow.com/questions/46073876/node-js-buffer-data-to-ffmpeg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!