这类问题我又碰上了一次。用 ffmpeg 6.1 的 select='eq(pict_type,I)' 从监控视频抽关键帧,每 10 秒一张,再送视觉模型判断画面有无异常。一段 3 分钟的录像里两次闪白告警全漏了,回看原片发现那两帧落在 P 帧上,抽帧脚本一共只产出 18 张图,试过把阈值调低也没有多出来。
第一反应是「抽帧脚本按固定每秒帧数重采样,把短事件稀释掉了」,验证下来不成立。
这类报错背后常见的原因有几处,逐个排除就行。I 帧间隔由编码器的 GOP 决定,跟画面内容变化无关;闪白只持续 0.5 秒,正好落在两个关键帧之间;场景切换检测阈值设得太高,没有触发新的关键帧。
上来先看视频的 GOP 结构与帧类型分布
ffprobe -v error -select_streams v:0 -show_entries frame=pict_type,pkt_pts_time -of csv input.mp4
再往下改用场景切换检测抽帧
ffmpeg -i input.mp4 -vf "select='gt(scene,0.25)',showinfo" -vsync vfr out_%04d.jpg
接着按每秒两帧全抽一遍留作兜底
ffmpeg -i input.mp4 -vf fps=2,scale=640:-1 frames/%05d.jpg
等前面都确认过,再对比两种抽法的帧数差异
python -c "import glob;print(len(glob.glob('frames/*.jpg')), len(glob.glob('out_*.jpg')))"
怎么算真的好了,看的是同一批现象。两次闪白所在时间点都出现在抽出的帧里,人工回看能对上,抽帧总量从 18 张增加到 360 张仍在可接受范围。
补一句。关键帧是编码概念不是内容概念,做画面异常检测要用场景切换或者固定帧率抽帧,只靠 I 帧等于把检测精度交给了编码器的 GOP 设置。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
