使用fluent-ffmpeg转视频流为音频流失败,上传Azure Blob存空文件
解决fluent-ffmpeg转流上传Azure Blob得到空文件的问题
核心问题分析
本地保存音频正常,但转流上传得到0字节文件,主要有两个关键原因:
- 缺少输出格式指定:本地
save()时ffmpeg能通过文件名扩展名推断输出格式,但pipe()没有这个上下文,必须显式声明输出格式,否则ffmpeg无法正确编码生成数据流。 - 流生命周期未正确衔接:Azure的
uploadStream需要稳定的数据流输入,若ffmpeg的流未完全初始化就开始上传,或错误/结束事件未正确传递,会导致上传提前终止。
修正后的代码示例
const { PassThrough } = require('stream'); // 创建中转流,统一处理ffmpeg的数据流和事件 const audioTransferStream = new PassThrough(); ffmpeg(recordedVideoStrm) .outputOptions([ "-vn", // 丢弃视频轨道 "-acodec pcm_s16le", // 使用PCM 16位小端编码 "-ar 44100", // 设置44.1kHz采样率 "-ac 2", // 双声道 ]) .outputFormat('wav') // 必须显式指定输出格式,匹配编码参数 .on("error", (err) => { console.error("音频处理失败:", err.message); audioTransferStream.destroy(err); // 出错时销毁中转流,终止上传 }) .on("end", () => { console.log("音频提取完成"); audioTransferStream.end(); // 处理完成后结束中转流,触发上传完成 }) .pipe(audioTransferStream); // 配置Azure Blob上传参数,适配音频流的生成速度 const uploadConfig = { bufferSize: 4 * 1024 * 1024, // 4MB缓冲区 maxBuffers: 20 }; try { const uploadResult = await blobClient.uploadStream(audioTransferStream, uploadConfig.bufferSize, uploadConfig.maxBuffers); console.log("音频上传成功:", uploadResult); } catch (uploadErr) { console.error("上传Azure Blob失败:", uploadErr); }
关键修改说明
- 添加
outputFormat('wav'):明确告诉ffmpeg输出格式为WAV,匹配你指定的pcm_s16le编码,确保数据流正常生成。 - 使用PassThrough中转流:解决ffmpeg原生流与Azure上传流的生命周期衔接问题,确保错误和结束事件能正确传递,避免上传流程异常中断。
- 优化上传参数:调整缓冲区大小和最大缓冲数,适配音频流的生成速度,减少因数据流不连续导致的上传问题。
另外,注意你本地代码里的矛盾点:.output("mp3")和.save("output.wav")冲突,ffmpeg会优先根据文件名扩展名推断格式,所以本地代码可以去掉.output("mp3")避免混淆。
内容的提问来源于stack exchange,提问作者infodev
相关产品推荐
相关产品推荐

