有没有办法使用ffmpeg
检测视频中的重复帧。
我尝试使用-vf
标记select=gt(scene\,0.xxx)
进行场景更改。但是,它对我的情况不起作用。
答案 0 :(得分:47)
使用mpdecimate过滤器,其目的是删除与前一帧没有太大差异的帧,以降低帧速率。"
这将生成一个控制台读数,显示过滤器认为哪些帧是重复的。
ffmpeg -i input.mp4 -vf mpdecimate -loglevel debug -f null -
生成删除了重复项的视频
ffmpeg -i input.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mp4
Th setpts过滤器表达式为FRAME_RATE fps的视频生成平滑的时间戳。请参阅What is video timescale, timebase, or timestamp in ffmpeg?
的时间戳说明答案 1 :(得分:12)
我也遇到了这个问题,吉安(Gyan)的出色回答让我起步,但是其结果是音频不同步,所以我不得不探索更多选择:
mpdecimate
是我在SO和互联网上找到的标准建议,但我认为它不应该是首选
frac
参数来调整检测,但这是您可能需要避免的额外工作mp4
container(source),但是我使用的是mkv
,所以此限制不适用于我的情况,但请注意decimate
可以精确删除帧,但仅对定期出现的重复有用。 ffprobe in.mkv
将输出检测到的FPS;可能看起来像这样
Stream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 1920x1080, SAR 1:1 DAR 16:9, 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
如果您在允许您一次步进一帧的媒体播放器中打开媒体in.mkv
,则可以找到实际的帧速率;然后计算将播放时间延长1秒所需的步骤,在我的情况下为 30 fps
N/FRAME_RATE/TB
除了使用FRAME_RATE
变量外,N/FRAME_RATE/TB
等同于ffmpeg文档(source)中的以下示例
将固定速率设置为每秒25帧:
setpts=N/(25*TB)
其背后的数学原理在What is video timescale, timebase, or timestamp in ffmpeg?
中得到了完美的解释TB
相乘以提高精度FRAME_RATE
变量与文字FPS值(例如25)FRAME_RATE
中使用N/FRAME_RATE/TB
变量FRAME_RATE
N/25/TB
FRAME_RATE
(并且我确实尝试过),则会检测到错误的 25 帧fps,即FRAME_RATE=25
,请通过mpdecimate
运行过滤器,该过滤器将删除第6帧,并更新为FRAME_RATE=20.833
,因此N/FRAME_RATE/TB
实际上是N/20.833/TB
这是完全错误的 这是我用来获得好的结果
的方法 ffmpeg -i in.mkv -vf mpdecimate out.mkv
ffmpeg -i in.mkv -vf decimate=cycle=6,setpts=N/25/TB out.mkv
但以下内容使我去同步的音频
ffmpeg -i in.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mkv
ffmpeg -i in.mkv -vf mpdecimate,setpts=N/25/TB out.mkv
如您所见
FRAME_RATE
变量,而应使用N/25/TB
,因为未正确检测到实际的FPS -af asetpts=N/SAMPLE_RATE/TB
SAMPLE_RATE
,但是在我看来,这是多余的工作,尤其是当我的视频开始时音频是同步的时,这样做会更好使用将保持这种状态的命令,而不是稍后再修复如果通常推荐的命令ffmpeg -i in.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mkv
对您不起作用,请尝试以下操作:
ffmpeg -i in.mkv -vf mpdecimate out.mkv
或
ffmpeg -i in.mkv -vf decimate=cycle=6,setpts=N/25/TB out.mkv
({cycle=6
,因为每第6帧都是重复的,而N/25/TB
是因为删除重复的帧后,视频将具有25 fps(避免使用FRAME_RATE
变量);请调整使用范围情况)
答案 2 :(得分:0)
我在这里尝试了解决方案,但当您需要修剪视频并保留音频时,它们似乎都不起作用。有一个 mpdecimate_trim 存储库做得很好。它基本上列出了要删除的所有帧(使用 mpdecimate
),然后创建一个复杂的过滤器,通过拆分视频并仅包含没有重复帧的部分来修剪视频中的所有这些帧(以及相应的音频)。
不过,我确实需要调整代码中的一些选项。例如,在 mpdecimate_trim.py
中,我必须更改这一行:
dframes2 = get_dframes(ffmpeg(True, "-vf", "mpdecimate=hi=576", "-loglevel", "debug", "-f", "null", "-").stderr)
我必须更积极地检测重复项,因此我将 mpdecimate
选项更改为 mpdecimate=hi=64*32:lo=64*24:frac=0.05