PHP本身不处理视频编码,转MP4本质是调用ffmpeg完成;RTMP流录制转存的关键不在PHP逻辑,而在ffmpeg命令构造、输入稳定性控制和输出封装一致性。

PHP本身不处理视频编码,转MP4本质是调用ffmpeg完成的;RTMP流录制转存的关键不在PHP逻辑,而在ffmpeg命令构造、输入稳定性控制和输出封装一致性。
RTMP流录制时为什么总生成损坏的MP4文件
直接用ffmpeg -i rtmp://... -c copy output.mp4容易失败,因为RTMP是实时流协议,没有明确的EOF信号,而MP4容器要求索引(moov atom)必须在文件开头或末尾写入完整——若进程被意外中断,moov就可能缺失或错位。
- 必须加
-movflags +faststart,让moov提前写入,否则Web播放器无法seek - 避免单纯
-c copy:RTMP源流可能含不规范时间戳或B帧顺序异常,需强制重映射时间基,加-vsync vfr -copyts - 录制中途断连时,
ffmpeg默认会退出并留下残缺文件;应配合-timeout 30和重试逻辑,或改用-reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1
PHP中安全启动ffmpeg录制进程的3个硬性条件
不能用exec()简单丢命令,否则PHP超时(默认30秒)或Worker重启会导致录制中断。必须用proc_open()接管stdin/stdout/stderr,并设置非阻塞等待。
-
timeout参数要设为0或足够大(如'timeout' => 0),禁用PHP执行时间限制 - 必须捕获
$pipes[2](stderr),实时读取ffmpeg日志,判断是否出现Connection refused或Invalid data found - 录制结束前,不能
fclose($pipes[0])(RTMP无stdin输入),而应靠信号终止:proc_terminate($process, SIGTERM),再proc_close()
如何保证录制MP4可直接用于HLS切片或Web播放
仅“能播放”不等于“可分发”。很多录制出来的MP4在FFmpeg里ffprobe报invalid duration或missing codec parameters,后续无法生成HLS索引。
立即学习“PHP免费学习笔记(深入)”;
- 强制指定关键参数:
-c:v libx264 -profile:v main -level 3.1 -c:a aac -ar 44100 -ac 2,避免编码器自适应导致兼容性问题 - 分辨率/帧率需显式固定:
-vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:-1:-1" -r 25,防止源流帧率跳变破坏MP4结构 - 输出路径必须是本地磁盘且有写权限,不要写到NFS或低性能挂载点——I/O延迟高会导致
ffmpeg写入卡顿,触发内部超时自动退出
真正难的不是启动命令,而是持续监控流状态、优雅处理断连、校验输出完整性。一个没做ffprobe二次校验的MP4文件,可能在HLS打包阶段才暴露问题,那时已无法补救。



















