You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中使用FFmpeg分片大音频文件时流未写入完整的问题

问题分析与解决方案

核心问题:过早终止FFmpeg进程

你的代码在读取流(fs.createReadStream)触发close事件时,立刻调用muxer.kill()杀死了FFmpeg子进程。但close事件仅代表本地文件的所有数据已经写入到FFmpeg的标准输入(stdin),FFmpeg还需要时间处理这些数据并生成所有分片文件。

对于小文件,数据量小,FFmpeg能在你杀死进程前快速处理完所有分片;但大文件数据量庞大,FFmpeg还在处理过程中就被强制终止,自然无法生成完整的分片。而命令行直接运行时,FFmpeg会处理完所有输入数据才会退出,所以能生成完整的328个分片。

修复代码

修改事件监听逻辑,等待FFmpeg子进程自行退出,而不是主动杀死它:

const muxer = child_process.spawn('ffmpeg', transformArgs, {
    cwd: `${cwd}/transforms`,
});

console.log('creating stream (read)...');

// 读取文件并传入FFmpeg
fs.createReadStream(
    `${cwd}/transforms/stream${path.extname(fileSrc.filename)}`,
)
.pipe(muxer.stdin)
.on('error', (e) => {
    console.error('读取流错误:', e);
});

// 监听FFmpeg子进程的退出事件
muxer.on('exit', (code, signal) => {
    if (code === 0) {
        console.log('FFmpeg处理完成,所有分片已生成');
        // 这里可以执行分片上传到S3的逻辑
    } else {
        console.error(`FFmpeg异常退出,退出码: ${code}, 信号: ${signal}`);
    }
});

// 监听FFmpeg的错误输出,方便排查问题
muxer.stderr.on('data', (data) => {
    console.error('FFmpeg错误输出:', data.toString());
});

关键修改点说明

  • 移除了readStream的close事件监听,不再主动调用muxer.stdin.end()和muxer.kill():当读取流结束时,pipe会自动关闭FFmpeg的stdin,FFmpeg会继续处理剩余数据直到完成。
  • 添加muxer.on('exit')监听:只有当FFmpeg正常退出(退出码为0)时,才表示所有分片生成完成,此时再执行后续的S3上传操作。
  • 添加muxer.stderr监听:可以捕获FFmpeg的错误输出,方便排查分片过程中可能出现的其他问题(比如参数错误、磁盘空间不足等)。

额外排查点

如果修复后仍有问题,可以检查:

  • FFmpeg的transformArgs参数是否正确:确认分片的时长/大小设置和命令行运行时一致。
  • 服务器磁盘空间:大文件分片可能占用较多磁盘空间,确保目标目录有足够空间。
  • Node.js的内存限制:虽然分片是FFmpeg处理,但如果读取流有异常,可以尝试调整读取流的highWaterMark参数(比如fs.createReadStream(path, { highWaterMark: 64 * 1024 }))优化流处理。

内容的提问来源于stack exchange,提问作者Israel Edoghama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:57:19