Node.js中fluent-ffmpeg命令未等待前序Promise完成问题排查
问题原因与解决方案
核心问题分析
- Promise未正确绑定ffmpeg完成事件:如果你的
convertMP4ToMP3函数没有在ffmpeg的end回调里调用resolve,而是在启动转码后直接resolve,会导致Promise提前完成,trimFile拿到的是还未生成的MP3文件,触发"Invalid argument"错误。 - 未传递生成的MP3路径:resolve时需要把转码后的MP3文件路径作为参数传递,否则
trimFile无法获取正确的输入文件。
正确实现代码
const ffmpeg = require('fluent-ffmpeg'); const path = require('path'); // 转MP4到MP3的Promise封装 function convertMP4ToMP3(mp4Path) { return new Promise((resolve, reject) => { const mp3Path = path.join(path.dirname(mp4Path), `${path.basename(mp4Path, '.mp4')}.mp3`); ffmpeg(mp4Path) .output(mp3Path) .audioCodec('libmp3lame') .on('end', () => { console.log('转码完成'); resolve(mp3Path); // 转码完成后传递生成的MP3路径 }) .on('error', (err) => { console.error('转码失败:', err); reject(err); }) .run(); }); } // 修剪MP3的Promise封装 function trimFile(mp3Path, startTime, endTime) { return new Promise((resolve, reject) => { const trimmedPath = path.join(path.dirname(mp3Path), `${path.basename(mp3Path, '.mp3')}_trimmed.mp3`); ffmpeg(mp3Path) .setStartTime(startTime) .setEndTime(endTime) .output(trimmedPath) .on('end', () => { console.log('修剪完成'); resolve(trimmedPath); }) .on('error', (err) => { console.error('修剪失败:', err); reject(err); }) .run(); }); } // 串联执行流程 async function processMedia(mp4InputPath) { try { const mp3Path = await convertMP4ToMP3(mp4InputPath); // 截取0:12到0:48片段 const trimmedPath = await trimFile(mp3Path, '00:00:12', '00:00:48'); console.log('全部处理完成,输出文件:', trimmedPath); } catch (err) { console.error('处理失败:', err); } } // 调用示例 processMedia('./input.mp4');
关键注意点
- 事件绑定逻辑:必须在ffmpeg的
end事件中调用resolve,确保转码/修剪操作真正完成后才让Promise进入resolved状态。 - 路径传递:转码函数resolve时返回生成的MP3路径,修剪函数接收该路径作为输入,避免硬编码或路径错误。
- 时间格式:ffmpeg支持
'00:00:12'(时分秒)或12(秒)格式的时间参数,确保格式正确,否则也会触发参数错误。 - 错误处理:每个Promise都要绑定
error事件并调用reject,避免未捕获的Promise异常。
内容的提问来源于stack exchange,提问作者Kollegah der Boss
相关产品推荐
相关产品推荐

