问题出现得很突然,日志倒是留得挺全。视频 25fps,用 -vf fps=2 抽帧做画面理解,回填字幕时按帧序号乘 0.5 秒算时间,结果每条字幕比实际早 0.4 秒,越往后偏移越大。

刚开始盯着「帧序号从 1 开始,公式按 0 推的」,折腾了半个多小时,排掉了。

把日志和配置对完,能解释这个现象的基本就这几处。fps 滤镜按可变帧率重采样,序号不再均分。也可能是容器 start_time 不是 0,时间轴整体前移。

少数情况下是编码时间基与秒换算没除对分母。

第一件事是看容器的起始时间与时间基

ffprobe -v error -show_entries format=start_time,duration -show_entries stream=time_base,r_frame_rate -of json in.mp4

随后改用按时间点精确抽帧

ffmpeg -y -ss 12.5 -i in.mp4 -frames:v 1 -q:v 2 shot_12_5.jpg

从帧的 pts 直接算秒数

ffmpeg -i in.mp4 -vf "fps=2,showinfo" -f null - 2>&1 | grep pts_time | head -5

等前面都确认过,再按修正后的时间轴重排字幕

python retime.py --srt in.srt --offset -0.4 --out fixed.srt

别只看报错消失,验证要多做一步。抽帧时间与 pts 对得上,字幕落在画面对应位置,最后一条的偏差不超过 40 毫秒。

容易忽略的是,按帧序号乘间隔只在恒定帧率且从零开始时成立,真实素材几乎不满足,直接读 pts 最稳。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189