如何用Node.js将youtube-dl-exec处理后的输出流式传输到前端
解决youtube-dl-exec流式传输MP3到前端的问题
问题根源
你遇到的核心问题在于:
youtubedl.exec()返回的是Promise,resolve结果是命令执行后的输出内容(字符串/Buffer),而非子进程对象,因此无法调用stdout.pipe- 直接使用
output: "-"时,若未正确配置流式输出触发ffmpeg后处理,youtube-dl会输出原始音频流(如webm)而非转换后的MP3 - 手动
res.write大文件会导致内存溢出、文件结构损坏,无法保证流式传输的完整性
修正方案
使用youtubedl.spawn()方法直接获取子进程对象,流式传输处理后的MP3输出,并配置正确的响应头:
import youtubedl from 'youtube-dl-exec'; import type { Request, Response } from 'express'; export default async function convertAndDownload(req: Request, res: Response) { try { const { video, meta, filename } = req.body; const videoUrl = `https://youtube.com/watch?v=${video.id}`; // 配置正确的响应头,让浏览器识别MP3文件 res.header('Content-Disposition', `attachment; filename="${filename}.mp3"`); res.header('Content-Type', 'audio/mpeg'); // 使用spawn创建子进程,而非exec(exec会缓冲全部输出) const proc = youtubedl.spawn(videoUrl, { extractAudio: true, audioFormat: 'mp3', audioQuality: '10', output: '-', // 将处理后的MP3输出到stdout postprocessorArgs: [`ffmpeg: -metadata title="${meta.title}"`], addHeader: ['referer:youtube.com', 'user-agent:googlebot'], noBuffer: true, // 禁用输出缓冲,确保实时流式传输 }); // 将子进程的stdout直接pipe到响应对象,自动处理流式传输 proc.stdout.pipe(res); // 处理子进程错误 proc.stderr.on('data', (data) => { console.error(`youtube-dl 错误信息: ${data.toString()}`); }); proc.on('error', (err) => { if (!res.headersSent) { res.status(500).json({ success: false, msg: '处理请求失败', }); } }); // 子进程结束后收尾响应 proc.on('close', (code) => { if (code !== 0 && !res.headersSent) { res.status(500).json({ success: false, msg: `进程异常退出,代码: ${code}`, }); } }); } catch (err) { if (!res.headersSent) { res.status(500).json({ success: false, msg: '请求处理过程中发生错误', }); } } }
关键注意事项
- 确保服务器已安装ffmpeg:youtube-dl依赖ffmpeg完成音频格式转换,缺少时会直接输出原始音频流
- 必须设置
Content-Type: audio/mpeg:让浏览器正确识别文件类型,避免下载后无法播放 - 使用
spawn而非exec:spawn返回子进程对象,支持实时流式输出;exec会缓冲全部输出,不适合大文件传输
内容的提问来源于stack exchange,提问作者user3331344
相关产品推荐
相关产品推荐

