如何使用ffmpeg简单地从视频中删除重复的帧 [英] How to Simply Remove Duplicate Frames from a Video using ffmpeg

查看:451
本文介绍了如何使用ffmpeg简单地从视频中删除重复的帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我会以说我不是视频操作专家的身份作为开头,尽管我多年来一直在尝试ffmpeg(以相当有限的方式).因此,我对所有经常使用的 language 不太熟悉...以及它如何影响我在操作中尝试做的事情...但我会继续无论如何...

First of all, I'd preface this by saying I'm NO EXPERT with video manipulation, although I've been fiddling with ffmpeg for years (in a fairly limited way). Hence, I'm not too flash with all the language folk often use... and how it affects what I'm trying to do in my manipulations... but I'll have a go with this anyway...

我在这里检查了一些链接,例如: ffmpeg-依次删除重复的帧

I've checked a few links here, for example: ffmpeg - remove sequentially duplicate frames

...但是内容并没有真正帮助我.

...but the content didn't really help me.

我有几百个使用ffmpeg和其他类似应用程序在Windows和Linux下创建的视频剪辑.但是,它们在视频显示不动的情况下会出现一些时间问题.

I have some hundreds of video clips that have been created under both Windows and Linux using both ffmpeg and other similar applications. However, they have some problems with times in the video where the display is 'motionless'.

例如,假设我们有一个网站,该网站将实时视频流式传输到Web浏览器中的Flash视频播放器/插件中.例如,在这种情况下,我们谈论的是交通摄像头视频流.

As an example, let's say we have some web site that streams a live video into, say, a Flash video player/plugin in a web browser. In this case, we're talking about a traffic camera video stream, for example.

有一个正在运行的ffmpeg实例,正在将(Windows)桌面的某个区域捕获到视频文件中,即:-

There's an instance of ffmpeg running that is capturing a region of the (Windows) desktop into a video file, viz:-

ffmpeg -hide_banner -y -f dshow ^
      -i video="screen-capture-recorder" ^
      -vf "setpts=1.00*PTS,crop=448:336:620:360" ^
      -an -r 25 -vcodec libx264 -crf 0 -qp 0 ^
      -preset ultrafast SAMPLE.flv

比方说,正在捕获的实际显示"看起来像这样:-

Let's say the actual 'display' that is being captured looks like this:-

123456789 XXXXX 1234567 XXXXXXXXXXX 123456789 XXXXXXX
^---a---^ ^-P-^ ^--b--^ ^----Q----^ ^---c---^ ^--R--^ 

...其中每个字符位置代表一个(一个或多个)帧.由于互联网连接状况不佳,可以长时间显示单个框架"("X"字符是前一个框架的(几乎)完全相同的副本).因此,这意味着我们捕获的视频片段中的图像根本没有改变(无论如何用肉眼也看不到).

...where each character position represents a (sequence of) frame(s). Owing to a poor internet connection, a "single frame" can be displayed for an extended period (the 'X' characters being an (almost) exact copy of the immediately previous frame). So this means we have segments of the captured video where the image doesn't change at all (to the naked eye, anyway).

我们如何处理重复的帧?...并且如果ffmpeg的重复项"与ffmpeg不同,而LOOK观察者几乎相同,我们的方法又将如何改变?

How can we deal with the duplicate frames?... and how does our approach change if the 'duplicates' are NOT the same to ffmpeg but LOOK more-or-less the same to the viewer?

如果我们简单地删除重复的帧,视频的步调"就会丢失,而过去可能要花5秒钟才能显示的视频现在只需要几分之一秒的时间,就会出现非常生涩,不自然的运动,尽管视频中没有重复的图像.使用带有mp_decimate选项的ffmpeg似乎可以实现,即:-

If we simply remove the duplicate frames, the 'pacing' of the video is lost, and what used to take, maybe, 5 seconds to display, now takes a fraction of a second, giving a very jerky, unnatural motion, although there are no duplicate images in the video. This seems to be achievable using ffmpeg with an 'mp_decimate' option, viz:-

     ffmpeg -i SAMPLE.flv ^                      ... (i)
        -r 25 ^
        -vf mpdecimate,setpts=N/FRAME_RATE/TB DEC_SAMPLE.mp4

我引用的参考使用一条命令,该命令显示当"mp_decimate"被认为是相同"时将删除哪些帧,即:-

That reference I quoted uses a command that shows which frames 'mp_decimate' will remove when it considers them to be 'the same', viz:-

     ffmpeg -i SAMPLE.flv ^                      ... (ii)
        -vf mpdecimate ^
        -loglevel debug -f null -

...但是知道了(复杂格式)信息后,如何在不执行多次ffmpeg提取视频片段"以供以后重新组合的情况下重新组织视频呢?

...but knowing that (complicated formatted) information, how can we re-organize the video without executing multiple runs of ffmpeg to extract 'slices' of video for re-combining later?

在这种情况下,我猜我们将不得不运行类似以下内容:-

In that case, I'm guessing we'd have to run something like:-

  • 用户为重复项指定阈值持续时间"(可能只运行1秒钟)
  • 确定和确定保存主要视频信息(fps等)-假设恒定帧速率)
  • 映射(重复开始的帧/时间)->否.的重复帧数/持续时间
  • 如果重复的持续时间小于用户阈值,不要将此时期视为一系列重复帧"继续前进
  • 提取非重复"视频段(上图)
  • 使用原始视频的规范创建新视频"(空)
  • 每个视频段的
  • 提取片段的最后一帧创建具有重复帧的简短视频剪辑刚刚提取(持续时间=用户规格= 1秒)将(当前视频片段+短片)附加到新视频"并重复

...但是对于我来说,很多捕获的视频可能长达30分钟,并且有数百个10秒的暂停时间,因此使用此方法重建"视频会花费很长时间.

...but in my case, a lot of the captured videos might be 30 minutes long and have hundreds of 10 sec long pauses, so the 'rebuilding' of the videos will take a long time using this method.

这就是为什么我希望有一些可靠"和更智能"的使用方式ffmepg(带有/不带有"mp_decimate"过滤器)仅需几遍就可以执行"decimate"功能……也许有一种方法甚至可以指定所需的段(例如,在文本文件中)并随着ffmpeg运行它将在指定的时间/帧号停止/重新启动它的转码?

This is why I'm hoping there's some "reliable" and "more intelligent" way to use ffmepg (with/without the 'mp_decimate' filter) to do the 'decimate' function in only a couple of passes or so... Maybe there's a way that the required segments could even be specified (in a text file, for example) and as ffmpeg runs it will stop/restart it's transcoding at specified times/frame numbers?

简短的说,是否有另一个应用程序(可在Windows或Linux上使用)可以完成我想要的操作,而无需手动设置起点/终点,手动提取/合并视频片段...?

Short of this, is there another application (for use on Windows or Linux) that could do what I'm looking for, without having to manually set start/stop points, extracting/combining video segments manually...?

我一直在尝试使用Win7-SP1下的ffmpeg N-79824-gcaee88d和Puppy Linux Slacko 5.6.4下的(我目前不记得的其他版本)来完成所有这些工作.

I've been trying to do all this with ffmpeg N-79824-gcaee88d under Win7-SP1 and (a different version I don't currently remember) under Puppy Linux Slacko 5.6.4.

感谢任何线索.

推荐答案

我假设您要做的是保持运动的帧和最多1秒钟的重复帧,而丢弃其余的帧.

I assume what you want to do is to keep frames with motion and upto 1 second of duplicate frames but discard the rest.

ffmpeg -i in.mp4 -vf
"select='if(gt(scene,0.01),st(1,t),lte(t-ld(1),1))',setpts=N/FRAME_RATE/TB"
trimmed.mp4

select过滤器表达式的作用是使用if-then-else运算符:

What the select filter expression does is make use of an if-then-else operator:

gt(scene,0.01)检查当前帧是否检测到相对于前一帧的运动.该值将必须基于手动观察进行校准,方法是查看与框架中的传感器/压缩噪声或视觉噪声相比,哪个值可以准确捕获实际活动.有关如何获取所有场景更改值的列表,请参见此处.

gt(scene,0.01) checks if the current frame has detected motion relative to the previous frame. The value will have to be calibrated based on manual observation by seeing which value accurately captures actual activity as compared to sensor/compression noise or visual noise in the frame. See here on how to get a list of all scene change values.

如果评估框架具有运动性,则 then 子句评估 st(1,t).函数 st(val,expr) expr 的值存储在编号为 val 的变量中,并且还返回该表达式值作为结果.因此,保留帧的时间戳将在该变量中继续更新,直到遇到静态帧为止.

If the frame is evaluated to have motion, the then clause evaluates st(1,t). The function st(val,expr) stores the value of expr in a variable numbered val and it also returns that expression value as its result. So, the timestamp of the kept frames will keep on being updated in that variable until a static frame is encountered.

else 子句检查当前帧时间戳和存储值的时间戳之间的差异.如果差异小于1秒,则保留该帧,否则丢弃该帧.

The else clause checks the difference between the current frame timestamp and the timestamp of the stored value. If the difference is less than 1 second, the frame is kept, else discarded.

setpts 清除所有选定帧的时间戳.

The setpts sanitizes the timestamps of all selected frames.

编辑:我使用合成的视频输入对命令进行了测试,并且可以正常工作.

Edit: I tested my command with a video input I synthesized and it worked.

这篇关于如何使用ffmpeg简单地从视频中删除重复的帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆