Node.js 合并音频和视频流并将其通过管道传输到客户端

Posted

技术标签:

【中文标题】Node.js 合并音频和视频流并将其通过管道传输到客户端【英文标题】:Node.js merge audio and video streams and pipe it to the client 【发布时间】:2020-11-28 08:26:52 【问题描述】:

我正在使用 ytdl-core 库,它无法下载包含音频的高质量视频,因为 youtube 将它们放在单独的文件中。因此,我需要分别下载音频和视频,然后使用ffmpeg 合并它们。这方面的一个例子可以看到here。但是,使用这种方式我需要在合并文件之前下载文件,我想知道是否有一种方法可以合并音频和视频流并将结果直接发送到客户端?

如果您认为有更有效的方法可以实现这一目标,我想听听您的方法。

提前致谢。

【问题讨论】:

ffmpeg ,在输入端,可能允许 1 个输入成为流( STDIN ),但我很确定你必须下载到音频 trk 或视频 trk 的 blob / 文件。只需下载到 /tmp 并从 /tmp 运行 ffmpeg 输入即可保持简单 【参考方案1】:

我认为您在问题中引用的示例足以满足您的需要。无需保存 stdio 管道的输出,它可以直接通过管道传输到响应以供用户下载。我附上了一个示例代码sn-p。

app.get('/download', async (req, res)=>
        res.header("Content-Disposition", `attachment;  filename=$videoName.mkv`);
        const video = ytdl(url, filter: 'videoonly');
        const audio = ytdl(url,  filter: 'audioonly', highWaterMark: 1<<25);
        // Start the ffmpeg child process
                        const ffmpegProcess = cp.spawn(ffmpeg, [
                            // Remove ffmpeg's console spamming
                            '-loglevel', '0', '-hide_banner',
                            '-i', 'pipe:4',
                            '-i', 'pipe:5',
                            '-reconnect', '1',
                            '-reconnect_streamed', '1',
                            '-reconnect_delay_max', '4',
                            // Rescale the video
                            '-vf', 'scale=1980:1080',
                            // Choose some fancy codes
                            '-c:v', 'libx265', '-x265-params', 'log-level=0',
                            '-c:a', 'flac',
                            // Define output container
                            '-f', 'matroska', 'pipe:6',
                        ], 
                            windowsHide: true,
                            stdio: [
                            /* Standard: stdin, stdout, stderr */
                            'inherit', 'inherit', 'inherit',
                            /* Custom: pipe:4, pipe:5, pipe:6 */
                             'pipe', 'pipe', 'pipe',
                            ],
                        );
    
                        audio.pipe(ffmpegProcess.stdio[4]);
                        video.pipe(ffmpegProcess.stdio[5]);
                        ffmpegProcess.stdio[6].pipe(res); // Combining and piping the streams for download directly to the response
   

【讨论】:

我在 ```` ffmpegProcess.stdio[6].pipe(res); 上得到一个错误;```` 它说它未定义 您是否导入了子进程和ffmpeg模块,请导入模块 const cp = require('child_process'); const ffmpeg = 要求('ffmpeg-static');如果可能的话,也发布完整的错误

以上是关于Node.js 合并音频和视频流并将其通过管道传输到客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Node.js 通过 ffmpeg 流式传输 MP4 文件?

通过套接字连接将 https 代理请求传递到命名管道(node.js)

node.js:并排合并 2 个图像并将其保存回来

在 node.js 中使用 socket.io 通过 webrtc 广播实时音频

如何检测 Node 的 process.stdout 是不是正在通过管道传输?

使用 node-request 和 fs Promisified 下载图像,在 Node.js 中没有管道