当从节点生成时,ffmpeg会缓冲stdin。

问题描述 投票:0回答:1

我试图使用node.js将png数据写入ffmpeg来创建视频。我已经验证了以下代码的工作。

let ffmpeg = spawn(
  "ffmpeg",
  [
    "-y",
    "-loglevel", "info",
    "-f", "image2pipe",
    "-c:v", "png",
    "-r", `${this.fps}`,
    "-i", "-",

    "-an",
    "-vcodec", "libx264",
    "-pix_fmt", "yuv420p",
    "output.mp4",
  ],
);
ffmpeg.stdout.on('data', data => {
  console.log(`ffmpeg stdout: ${data}`);
});
ffmpeg.stderr.on('data', data => {
  console.log(`ffmpeg stderr: ${data}`);
});

let bufs = [];
let p = Promise.resolve();
for (let i = 0; i < this.frameData.length; i++) {
  p = p.then(_ => new Promise(resolve => {
    this.renderFrame(i);
    this.renderer.domElement.toBlob(blob => {
      blob.arrayBuffer().then(arr => {
        console.log('writing...');
        let uInt8Arr = new Uint8Array(arr);
        // ffmpeg.stdin.write(uInt8Arr);
        bufs.push(uInt8Arr);
        resolve();
      });
    });
  }));
}
p = p.then(_ => {
  for (let buf of bufs) {
    ffmpeg.stdin.write(buf);
  }
  ffmpeg.stdin.end();
});

很抱歉,如果它看起来很复杂, 承诺是用来作为一个变通的方法,因为事实上 toBlob() 异步运行,但帧必须按顺序写入。

这段代码的工作原理是正确的,但它的效率太低了,因为它把帧数据写入一个数组,然后再写入ffmpeg。然而如果我取消了 ffmpeg.stdin.write(uInt8Arr); 并注释数组数据被复制到 ffmpeg 的循环,ffmpeg 就会在最后挂起而不生成任何视频。如果我执行一个 "足够大 "的动作,比如保存文件或生成一个新的进程,ffmpeg会正确地生成视频。

我怀疑是某种缓冲问题造成的,但我并不完全理解,也不知道如何解决。我已经试过用以下方法向ffmpeg发送各种信号,包括 ffmpeg.kill() 并将其贯穿 stdbuf 所谓 此处 但无济于事。有什么变通的办法吗?

javascript node.js ffmpeg stdin
1个回答
0
投票

对于偶然遇到这种情况的人来说,解决方法是将调用的 ffmpeg.stdin.close()ffmpeg.stdin.destroy().

© www.soinside.com 2019 - 2024. All rights reserved.