【发布时间】:2021-05-09 14:33:05
【问题描述】:
我有一个 nodejs 程序,它生成原始 (rgb24) 图像,然后我将其通过管道传输到 ffmpeg,以便将其保存为 png 或 mp4。我的代码如下所示:
const fs = require("fs");
// ...
const outputBuffer = Buffer.alloc(outputPngWidth * 3 * outputPngHeight);
// ... write data into outputBuffer
fs.writeSync(process.stdout.fd, outputBuffer);
然后我在 CLI 中执行以下操作:
node generate | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1000x1000 -i - test.png
或者,如果我从我的程序中生成大量图像,我会这样做来生成视频文件:
node generate | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1000x1000 -r 60 -i - -codec:v libx265 test.mp4
在 Windows 上,这可以完美运行。在 linux 上(无论是在 Ubuntu 20 VM 上,还是直接安装在物理机上的 Ubuntu 20),它始终失败并显示:
pipe:: corrupt input packet in stream 0
[rawvideo @ 0x55f5256c8040] Invalid buffer size, packet size 65536 < expected frame_size 3000000
Error while decoding stream #0:0: Invalid argument
如果我像这样将它分成两个阶段,那么它也可以在 linux 上完美运行:
node generate > test.raw
cat test.raw | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1000x1000 -i - test.png
通过查看错误“数据包大小 65536 fs.writeSync 一次只发送 65536 个字节,但 ffmpeg 期望 3000000 个字节(即 1000 宽度 * 1000 高度 * 3 个通道)。
如果我将图像尺寸缩小到较小的尺寸,例如 50x50 或 100x100,那么它可以工作。只要x * y * 3 超过 65536,它就会失败(例如,160x160 失败,“数据包大小 65536
到目前为止我为解决这个问题所做的尝试没有运气:
- 强制节点一次吐出整个缓冲区:
fs.writeSync(process.stdout.fd, outputBuffer, 0, outputBuffer.length);
-
Add a big buffer to a pipe between two commands 的所有建议使用各种 linux 命令在
node和ffmpeg之间进行缓冲。 - 使用 Ubuntu 18 而不是 20。
- 使用节点 12 而不是 15。
- 想办法改变https://nodejs.org/api/fs.html中的块大小
有没有办法克服这个问题?
【问题讨论】:
-
node generate | cat | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1000x1000 -i - test.png呢? -
@DaBler:谢谢。它具有完全相同的行为:100x100 成功,160x160 失败并显示相同的消息。
-
node generate | pv --buffer-size 1G | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1000x1000 -i - test.png也可以工作。 -
@DaBler:同样的行为。我已经尝试过,以及stackoverflow.com/q/8554568/72478 中列出的所有其他解决方案
-
最后一次尝试:
stdbuf -o1G node generate | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1000x1000 -i - test.png.