如何以非阻塞方式操作 Node.js 中的大型媒体文件

How to manipulate large media files in Node.js in a non-blocking way

我目前正在创建一个 Node.js 应用程序,它接收 audio/video 流,将其逐步写入磁盘,然后在流结束后使用 ffmpeg 对其进行转码,并将其发送到其他地方存储,在本地删除它。

除了我可以在写入流之前对流进行转码以简化整个过程(此功能已计划)之外,处理潜在大文件的这些操作的最佳方法是什么?

我知道生成子进程(我目前正在使用的方法),但我不确定它们实际上是如何工作的,即使经过大量阅读也是如此。我什至不确定使用 "spawn" 是否正是我想要的("fork" 是更好的选择吗?)。

本质上,我想知道如何在不阻塞的情况下转码->上传->删除文件Node.js,以便多个用户可以同时做同样的事情。另外,我正在考虑将所有 3 个操作放在一个 bash 脚本中,以便它们按顺序同步发生,这样可以吗?

处理此问题的正确方法是使用 Streams - NodeJS 中的内置 class。

streams 允许逐渐传输数据并一次处理 1 个块。这允许处理大于计算机 RAM 的文件或像您的情况一样的无穷无尽的数据流。

因此无需将数据写入磁盘,您可以即时处理它,而不会阻塞线程(可以同时转码多个流)。
您尚未共享任何代码,但这是一个通用示例。

const spawn = require('child_process').spawn;

const ffmpeg = spawn('ffmpeg -y -hide_banner -f mpegts -i pipe: -codec copy -f mpegts pipe:');
ffmpeg.stdout.on('data', chunk => {
    // upload a transcoded chunk
});

// if the source is also a stream you can pipe it directly like so
// sourceStream.pipe(ffmpeg.stdin);

function onAudioVideoChunkReceived(chunk) {
    // handle audio/video input to nodejs server
    ffmpeg.stdin.write(chunk)
}

注意使用 ffmpeg 的特殊 input/output pipe: 允许通过 stdin 和 stdout 进行管道输入和输出