使用libx265时ffmpeg生成随机时长视频的问题排查
问题:FFmpeg转码RTSP流后分段时长异常
原脚本通过直接复制编码的方式,将户外摄像头RTSP流分割为1小时/段的视频,体积约1GB:
ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:password@1.1.1.1/stream1 -vcodec copy -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log
为压缩体积改用libx265编码后,生成的视频时长随机(5-10分钟),无法保持1小时分段:
ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:password@1.1.1.1/stream1 -c:v libx265 -crf 28 -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log
原因分析
转码性能瓶颈导致时间戳混乱
原脚本的-vcodec copy是直接封装流,无需解码编码,能严格遵循RTSP流的时间戳和分段指令。改用libx265后,FFmpeg需要实时解码原流、编码为H.265,若CPU处理速度跟不上摄像头流的推送速度(比如画面变化剧烈时编码压力陡增),会导致缓冲区溢出、时间戳错位,触发FFmpeg提前结束分段。-segment_atclocktime与转码的同步冲突-segment_atclocktime 1基于系统时钟触发分段,但转码过程中,编码延迟会打乱帧的时间戳——原流的时间戳来自摄像头,转码后的帧时间戳可能与系统时钟不同步,导致FFmpeg误判分段时机,提前切割视频。直接复制编码时无时间戳修改,不会出现此问题。关键帧间隔未匹配分段时长
FFmpeg分段默认需要在关键帧(I帧)处切割,否则分段视频可能无法正常播放。原流的关键帧间隔适配1小时分段,但转码时未强制设置关键帧间隔,若编码自动生成的关键帧间隔过短(比如5-10分钟),FFmpeg会在每个关键帧处触发分段,导致时长缩短。
解决办法
- 添加编码预设提升转码速度
根据CPU性能选择合适的-preset参数(从快到慢:ultrafast→superfast→veryfast→fast→medium),降低编码耗时,确保FFmpeg能跟上RTSP流速度:
ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:password@1.1.1.1/stream1 -c:v libx265 -crf 28 -preset fast -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log
- 强制设置关键帧间隔
用-g参数设置与分段时长匹配的关键帧间隔(假设帧率为25fps,1小时对应25*3600=90000),确保分段仅在1小时节点的关键帧处触发:
ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:password@1.1.1.1/stream1 -c:v libx265 -crf 28 -preset fast -g 90000 -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log
- 关闭系统时钟对齐(可选)
若无需严格按系统时钟分段,将-segment_atclocktime 1改为-segment_atclocktime 0,让FFmpeg基于流的时间戳分段,避免时钟同步问题。
内容的提问来源于stack exchange,提问作者new2cpp
相关产品推荐
相关产品推荐

