FFmpeg - 如何高精度修剪?

时间:2016-10-11 14:34:14

标签: ffmpeg

我非常喜欢FFmpeg修剪视频的方式,所以如果有人能帮助我,我会非常感激。 基本上,我想要做的是:我有一个视频序列,我希望它在某一秒内停止,冻结图像几秒钟(如暂停),然后再从同一帧完全再现。我可以说我正在处理三个视频: A.mp4 (视频序列的第一部分),B.mp4(冻结图像)和 C.mp4 (第二部分)部分视频序列)。此外,我还使用filter_complex执行叠加。

从静态图像生成视频的部分不是问题,我主要关注的是找到准确修剪和连接视频的方法。从其他帖子和来源,我发现FFmpeg修剪来自那些可以被强制的关键帧框架。但是,我获得的结果不合适,因为我的视频 A 的结尾与 C 开头不同。

我使用的命令如下:

ffmpeg -y -i VideoSequence.mp4 -c:v libx264 -pix_fmt yuv420p \
-force_key_frames "expr: gte(t,n_forced * 15)" -t 30 VideoOut.mp4

[请注意,Filter Complex中的所有内容都是关于叠加的,这样可以正常工作]

据我所知,生成的视频应该每隔15秒就有一个关键帧。现在,我想将视频分为两部分(#34;第二部分15""第二部分15")

ffmpeg -y -ss 00:00:01 -i VideoOut.mp4 -t 14 -c copy A.mp4

ffmpeg -y -ss 00:00:15 -i VideoOut.mp4 -t 5 -c copy C.mp4 

如前所述,我希望A.mp4的结束与#34;匹配"以C.mp4的开头(以帧精度),但我得到的结果远非完美。

非常感谢,任何形式的帮助都将不胜感激!

2 个答案:

答案 0 :(得分:5)

假设你的最终目标是我希望它在某一秒内停止,将图像冻结几秒钟(如暂停),然后从相同的确切帧再次重现。,当前的方法多代视频,不必浪费。

这是在一个命令中执行此操作的方法,假设视频为25 FPS。

Mysql

这里是过滤器图中发生的事情:

首先,视频被分成两个相同的流。然后从第2个开始到第15秒结束修剪第一个流。在环路滤波器中,从(最后一帧)#ffmpeg -i original.mp4 -filter_complex "[0]split[a][b]; [a]trim=1:15,loop=75:1:349,setpts=N/FRAME_RATE/TB[pre]; [b]trim=15,setpts=N/FRAME_RATE/TB[post]; [0]atrim=1:15,asetpts=N/SR/TB[apre]; [0]atrim=15,asetpts=N/SR/TB[apost]; [pre][apre][post][apost]concat=a=1[v][a]" -map "[v]" -map "[a]" paused.mp4 开始的1帧循环75帧。然后时间戳被正规化,因为修剪或循环过滤器不会这样做。第二个分割流被修剪为从第16秒开始,其时间戳重置,两个流使用concat联合。如果您需要在联合流的顶部叠加某些内容,请在concat之后插入349过滤器。

答案 1 :(得分:0)

由于您没有定义帧率,我认为问题可能是您的关键帧没有准确插入到您想要的位置。而不是每15帧强制一个,只需插入你需要的两个:

-force_key_frames 00:00:01,00:00:15

或者如果你只关心拆分是干净的而不是拆分的确切位置,你可以使用段复用器:

-f segment -segment_time 14 out%03d.mp4

有关此documentation的另一个想法:

  

-ss 位置(输入/输出)
  当用作输入选项(-i之前)时,在此输入文件中寻找位置。请注意,在大多数格式中,无法精确搜索,因此ffm​​peg将在位置之前寻找最接近的搜索点。当转码和-accurate_seek启用(默认值)时,搜索点和位置之间的这个额外段将被解码并丢弃。在进行流复制或使用-noaccurate_seek时,它将被保留。

     

当用作输出选项(在输出文件名之前)时,解码但丢弃输入,直到时间戳到达位置。

所以移动-ss不应该有任何区别,但值得一试,特别是对于没有准确搜索的旧版本。