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

时间:2020-08-08 02:34:39

标签: node.js express ffmpeg ytdl

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

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

谢谢。

1 个答案:

答案 0 :(得分:0)

我认为您在问题中引用的示例足以满足您的需求。代替保存stdio管道的输出,可以将其直接管道传递给响应以供用户下载。我已经附上了一个示例代码片段。

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
   }