FFmpeg-如何高精度修剪?

FFmpeg-如何高精度修剪?

问题描述:

我对FFmpeg修剪视频的方式非常执着,因此,如果有人可以帮助我,我将非常感激. 基本上,我想做的是:我有一个视频序列,我希望它在一秒钟后停止,将图像冻结几秒钟(如暂停),然后从相同的精确帧再次进行再现.我可以说我正在处理三个视频: A.mp4 (视频序列的第一部分),B.mp4(冻结的图像)和 C.mp4 (第二个视频)视频序列的一部分).此外,我还使用filter_complex进行覆盖.

I am pretty stucked with the way that FFmpeg trims videos, so I would be really grateful if someone could help me. Basically, what I am trying to do is: I have a video sequence and I want it to stop in a certain second, freeze the image some seconds (like a pause), and then reproduce again from the same exact frame. I could say that I am dealing with three videos: A.mp4 (first part of the video sequence), B.mp4 (frozen image) and C.mp4 (second part of the video sequence). Besides, I also perform an overlay with filter_complex.

从静态图像生成视频的部分不是问题,我主要关心的是找到精确修剪和连接视频的方法.从其他帖子和来源中,我发现FFmpeg从那些作为关键帧的帧中修剪出来,可以对其进行强制.但是,我获得的结果不合适,因为我的视频 A 以不同于 C 开头的帧结束.

The part of generating a video from a static image is not a problem, my main concern is to find the way to trim and concatenate videos accurately. From other posts and sources, I discovered that FFmpeg trims from those Frames that are Keyframes, which can be forced. However, the result I obtain is not the appropriate one, because my video A ends in a frame different from the one in the beginning of C.

我正在使用的命令如下:

The commands I am using are the following ones:

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中的所有内容都是关于Overlay的,效果很好]

[Note that everything inside Filter Complex is about an Overlay, which works fine]

据我所知,生成的视频应每15秒包含一个关键帧.现在,我想将视频分为两部分(在15秒之前"和在15秒之后"):

As far as I know, the resulting video should have a Keyframe every 15 seconds. Now, I want to cut the video into 2 parts ("before second 15" and "after second 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的结尾与C.mp4的开头匹配"(以帧精度),但是我得到的结果远非完美.

As mentioned, I expect the end of A.mp4 to "match" with the beginning of C.mp4 (at a frame precision), but the result I obtain is far from being perfect.

非常感谢您,任何帮助将不胜感激!

Thank you very much, any kind of help will be appreciated!

假设您的最终目标是我希望它在一秒钟内停止,将图像冻结几秒钟(例如暂停),然后再次再现从相同的精确帧开始.,具有多个视频世代的当前方法不必要地浪费了.

Assuming your end goal is I want it to stop in a certain second, freeze the image some seconds (like a pause), and then reproduce again from the same exact frame., the current method, with multiple video generations, is needlessly wasteful.

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

Here's the way to do it in one command, assuming the video is 25 FPS.

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

以下是过滤图中发生的情况:

Here's what is happening in the filtergraph:

首先,将视频拆分为两个相同的流.然后从第二秒的开始到第15秒的末尾修剪第一流.在环路滤波器中,从(最后一帧)#349开始的1帧循环播放75帧.然后,由于修整或环路过滤器不会这样做,因此时间戳会被规范化.将第二个分割流修剪为从第16秒开始,重置其时间戳,并使用concat将两个流合并.如果您需要在联合流的顶部叠加一些内容,请在concat之后插入overlay过滤器.

First, the video is split to two identical streams. Then the first stream is trimmed from start of 2nd to end of 15th second. In the loop filter, 1 frame starting at (the last frame) #349 is looped for 75 frames. Then the timestamps are regularized since the trim or loop filters won't do so. The 2nd split stream is trimmed to start from the 16th second, its timestamps reset and the two streams joint using concat. If you need to overlay something on top of the joint stream, insert an overlay filter after the concat.