You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

FFmpeg场景检测:为筛选帧叠加原始帧序号的技术疑问

解决方案:分离场景检测与帧序号叠加的独立处理分支

这个问题我刚好处理过,核心矛盾就是「场景检测不能碰原始帧,帧序号又必须来自原始帧计数」,用FFmpeg的filter_complex多分支滤镜链就能完美解决,完全避免互相干扰。

核心思路

把原始视频拆成两个完全独立的处理流:

  1. 流1:纯场景检测:只负责筛选符合条件的帧,全程不修改原始帧内容,也不重置时间戳,保留原始帧的时序信息
  2. 流2:纯序号叠加:给所有原始帧叠加原始帧序号,完全不受场景检测的影响
  3. 最后同步合并:以流1的筛选结果为依据,只保留流2中对应时序的带序号帧

具体命令

ffmpeg -i video.mp4 -filter_complex "
# 拆分输入为两个完全相同的流,分别用于场景检测和序号叠加
split [scenedetect][drawtext];

# 分支1:仅做场景检测,保留原始时序,不修改帧内容
[scenedetect]select=gt(scene\,0.003),setsar=1 [selected];

# 分支2:给所有原始帧叠加原始帧序号(%{frame_num}返回原始帧的序号,从1开始)
[drawtext]drawtext=fontfile=/Windows/Fonts/Arial.ttf:text='frame: %{frame_num}':x=(w-tw)/2:y=h-(2*lh):fontcolor=white:box=1:boxcolor=0x000000@0.5:fontsize=30,setsar=1 [labeled];

# 同步两个分支,只保留场景检测选中的、带原始序号的帧
[selected][labeled]overlay=shortest=1:format=auto,setpts=N/(30*TB) [out]
" -map "[out]" frame%d.jpg

关键细节解释

  • split拆分流:保证两个分支处理的都是完全原始的视频帧,场景检测不会受到叠加文本的干扰
  • 场景检测分支不修改时序:这里没有用setpts提前重置时间戳,而是把setpts放到最后合并后处理,这样既保证了输出帧的连续计数,又不会影响原始帧序号的获取
  • drawtext用%{frame_num}:这个变量直接读取输入帧的原始序号,完全不受后续滤镜的影响,完美得到你需要的16、42、181这类非连续的原始帧编号
  • overlay同步帧:用场景检测分支的帧作为“筛选器”,只保留和它时序匹配的序号叠加帧,shortest=1确保两个流同步结束,format=auto自动适配像素格式避免报错
  • 字体路径注意:Windows下如果/Windows/Fonts/Arial.ttf路径不对,换成C:/Windows/Fonts/arial.ttf(用正斜杠或者双反斜杠)即可

可选调整

如果不需要重置输出帧的时间戳(比如不介意输出帧的时序是原始视频的非连续时序),可以去掉最后的setpts=N/(30*TB),这样输出的帧文件名序号还是连续的,但帧内容对应的原始序号是正确的。

内容的提问来源于stack exchange,提问作者Fugi

火山引擎 最新活动