如何通过FFmpeg将降采样音频流输出到stdout获取WAV Buffer
解决FFmpeg流输出到stdout的问题
要实现FFmpeg将降采样后的音频直接通过stdout输出,核心是给FFmpeg明确指定输出格式(管道没有文件扩展名,FFmpeg无法自动推断格式),同时调整代码逻辑来收集stdout的数据流,无需临时文件。
修改后的完整代码
const { spawn } = require('child_process'); const { PassThrough } = require('stream'); function downsampleAudio(pcmBuffer) { return new Promise((resolve, reject) => { const inputStream = new PassThrough(); inputStream.end(pcmBuffer); // 调整FFmpeg参数:指定输出格式,输出到stdout管道 const ffmpeg = spawn("ffmpeg", [ "-f", "s16le", "-ar", "48000", "-ac", "1", "-i", "pipe:0", "-ar", "16000", "-ac", "1", "-c:a", "pcm_s16le", "-f", "wav", // 必须显式指定输出格式,管道无扩展名无法自动推断 "pipe:1" // 输出到stdout ]); // 收集stdout的音频数据块 const outputChunks = []; ffmpeg.stdout.on('data', (chunk) => { outputChunks.push(chunk); }); // 数据流结束后合并成完整Buffer返回 ffmpeg.stdout.on('end', () => { const waveBuffer = Buffer.concat(outputChunks); resolve(waveBuffer); }); // 收集FFmpeg的错误输出,用于调试排查 let stderrLogs = ''; ffmpeg.stderr.on('data', (data) => { stderrLogs += data.toString(); }); ffmpeg.stdin.on('error', (error) => { reject(new Error('FFmpeg stdin流错误: ' + error.message)); }); ffmpeg.on('close', (code) => { if (code !== 0) { reject(new Error(`FFmpeg进程退出码 ${code},错误信息:${stderrLogs}`)); } }); inputStream.pipe(ffmpeg.stdin); }); }
关键改动说明
- 显式指定输出格式:添加
-f wav参数,这是管道输出必须的——FFmpeg没法从pipe:1推断输出格式,必须明确声明。如果你的热词API接受原始PCM(而非WAV容器),把-f wav改成-f s16le即可。 - 取消临时文件操作:通过监听
stdout的data事件收集音频数据块,最后用Buffer.concat合并成完整Buffer直接返回,省去了文件读写和删除的步骤。 - 捕获stderr日志:FFmpeg的错误信息都会输出到stderr,收集这些日志能快速定位参数错误、输入格式不匹配等问题,调试更高效。
内容的提问来源于stack exchange,提问作者KxAy
相关产品推荐
相关产品推荐

