【发布时间】:2016-09-02 11:30:45
【问题描述】:
有没有办法使用ffmpeg 检测视频中的重复帧?
我尝试使用-vf 标志和select=gt(scene\,0.xxx) 进行场景更改。但是,它不适用于我的情况。
【问题讨论】:
标签: ffmpeg duplicates
有没有办法使用ffmpeg 检测视频中的重复帧?
我尝试使用-vf 标志和select=gt(scene\,0.xxx) 进行场景更改。但是,它不适用于我的情况。
【问题讨论】:
标签: ffmpeg duplicates
我在这里尝试了解决方案,但当您需要修剪视频并保留音频时,它们似乎都不起作用。有一个 mpdecimate_trim repo 做得很好。它基本上列出了所有要丢弃的帧(使用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
【讨论】:
我也遇到了这个问题,上面 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, <strong>25 fps</strong>, 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)N/FRAME_RATE/TB 中使用 FRAME_RATE 变量
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 这是完全错误的
这是我使用的效果很好
@987654330@ -i in.mkv -vf @987654331@ out.mkv
@987654332@ -i in.mkv -vf @987654333@=cycle=6,@987654334@=N/25/TB out.mkv
但以下给了我去同步的音频
@987654335@ -i in.mkv -vf @987654336@,@987654337@=N/FRAME_RATE/TB out.mkv
@987654338@ -i in.mkv -vf @987654339@,@987654340@=N/25/TB out.mkv
@987654341@ -i in.mkv -vf @987654342@=cycle=6 out.mkv
如你所见
FRAME_RATE 变量并改用N/25/TB,因为没有正确检测到实际的FPS-af @987654351@=N/SAMPLE_RATE/TB 的东西
SAMPLE_RATE,但在我看来,这似乎是额外的不必要的工作,尤其是当我的视频在开始时音频同步时,所以最好使用命令将保持这种状态,而不是稍后修复它如果通常推荐的命令 @987654352@ -i in.mkv -vf @987654353@,@987654354@=N/FRAME_RATE/TB out.mkv 对您不起作用,请尝试以下操作:
@987654355@ -i in.mkv -vf @987654356@ out.mkv
或
@987654357@ -i in.mkv -vf @987654358@=cycle=6,@987654359@=N/25/TB out.mkv
(cycle=6 因为每 6 帧都是重复的,N/25/TB 因为删除重复后视频将有 25 fps(避免使用 FRAME_RATE 变量);根据您的用例进行调整)
【讨论】:
-vsync vfr 并删除 setpts 以在保存到 mp4 时保持具有相同时间戳的去重帧
Add -vsync vfr and remove setpts in my command @Gyan --- 这正是我为mpdecimate 的用例所做的,特别是我删除了setpts 过滤器,我什至不需要-vsync vfr。都在tl;dr 部分。
The setpts is needed with mp4 because it is a constant frame rate muxer @Gyan --- 这很有趣,但也请注意,虽然我能够从 mpdecimate 过滤器用例中删除 setpts 过滤器(如您所建议的那样),但我 对于decimate 用例,必须 使用setpts。两者都是mkv。猜对了吗?!
ffmpeg -i in.mkv -vf [mpdecimate][] out.mkv 时,我得到[AVFilterGraph @ ...] Bad (empty?) label found in the following: "[]". Error reinitializing filters! Failed to inject frame into filter network: Invalid argument. Error while processing the decoded data for stream #0:0 错误。
ffmpeg -i in.mkv -vf [mpdecimate][] out.mkv 有缺陷,正确的命令是ffmpeg -i in.mkv -vf mpdecimate out.mkv(注意没有方括号)。现在都修好了。
使用mpdecimate 过滤器,其目的是“丢弃与前一帧差别不大的帧以降低帧速率。”
这将生成一个控制台读数,显示过滤器认为哪些帧是重复的。
ffmpeg -i input.mp4 -vf mpdecimate -loglevel debug -f null -
生成删除重复项的视频
ffmpeg -i input.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB out.mp4
setpts 过滤器表达式为FRAME_RATE FPS 的视频生成平滑的时间戳。在What is video timescale, timebase, or timestamp in ffmpeg?查看时间戳的解释
【讨论】:
FRAME_RATE要换成帧率吗?
-vsync vfr