FFmpeg录制1.5小时视频失败问题求助
解决长时长RTSP转FLV录制及转码失败问题
问题核心原因
- 强制终止进程导致FLV文件损坏:使用
SIGKILL直接杀死ffmpeg进程,会让ffmpeg来不及写入FLV文件的关键索引信息(如时间戳索引、文件尾标识),短时长文件可能还能勉强解析,但长时长文件损坏概率极高。 - RTSP流时间戳不连续:RTSP源流的时间戳可能存在跳变或不连续,直接通过
-c:v copy复制到FLV时,长时长累积的时间戳错误会导致文件无法被后续转码工具识别。
修复步骤及代码调整
1. 优雅终止录制进程,避免文件损坏
将SIGKILL替换为向ffmpeg发送退出指令或使用SIGINT信号,让进程有时间完成文件收尾工作:
// 停止录制接口调整 ffmpegProcesses[rtsp].process.stdin.write('q'); // 发送ffmpeg标准退出指令,最优雅的方式 ffmpegProcesses[rtsp].process.on("exit", async (code, signal) => { // 处理后续转码逻辑 // ... });
如果必须用kill信号,优先选择SIGINT而非SIGKILL:
ffmpegProcesses[rtsp].process.kill("SIGINT");
2. 录制FLV时修复时间戳问题
在启动录制的ffmpeg参数中添加时间戳修复相关配置,确保FLV文件时间戳连续:
const ffmpeg = spawn("ffmpeg", [ "-i", rtsp, "-use_wallclock_as_timestamps", "1", // 用系统时间替代RTSP流的原始时间戳,避免异常 "-fflags", "+genpts", // 强制生成连续的播放时间戳 "-c:v", "copy", "-an", "-f", "flv", `${filename}.flv`, ]); ffmpegProcesses[rtsp] = { process: ffmpeg, filename }; // 监听错误输出,便于排查录制过程中的异常 ffmpeg.stderr.on('data', (data) => { console.error(`录制错误日志: ${data.toString()}`); });
3. 转码时增加容错处理
针对可能存在的FLV文件损坏情况,在转码参数中添加容错配置,提升转码成功率:
const transcodeFfmpeg = spawn("ffmpeg", [ "-i", `${filename}.flv`, "-err_detect", "ignore_err", // 忽略源文件中的非致命错误 "-c:v", "libx264", "-preset", "fast", "-crf", "30", "-an", `${filename}.mp4`, ]); transcodeFfmpeg.stderr.on('data', (data) => { console.error(`转码错误日志: ${data.toString()}`); }); transcodeFfmpeg.on("exit", async (code) => { if (code === 0) { await uploadToS3(); // 可选:转码完成后删除原FLV文件节省存储空间 // fs.unlinkSync(`${filename}.flv`); } else { console.error("转码失败,退出码:", code); } });
4. 额外优化:进程状态监控(可选)
对于超长时间录制,可定期检查ffmpeg进程状态,避免进程意外挂起未被发现:
// 启动录制后,每分钟检查一次进程状态 const checkInterval = setInterval(() => { const targetProcess = ffmpegProcesses[rtsp]?.process; if (targetProcess && targetProcess.exitCode === null) { // 进程正常运行,可记录状态 } else { clearInterval(checkInterval); console.error("录制进程意外终止"); } }, 60000);
验证测试
- 录制1.5小时以上的RTSP流,用VLC等工具检查生成的FLV文件是否可正常播放。
- 验证转码后的MP4文件播放完整性,以及上传S3后的可用性。
内容的提问来源于stack exchange,提问作者Bruno Munné
相关产品推荐
相关产品推荐

