Video 如何使用ffmpeg提取时间精确的视频片段?

Video 如何使用ffmpeg提取时间精确的视频片段?,video,ffmpeg,video-editing,Video,Ffmpeg,Video Editing,这不是一个特别新的问题领域,但我尝试了那里的建议,但运气不好。所以,我的故事: 我有一块15秒长的直接从camera.mov视频,我想从中提取一个特定的块,我可以通过开始时间和停止时间来识别,以秒为单位。我开始尝试做一个我称之为“拷贝提取”的事情:从9秒到12秒 ffmpeg -i test.mov -vcodec copy -acodec copy -ss 9 -to 12 test-copy.mov 这是一个不错的开始,但在片段的开头和结尾都有一些黑色的框架,我不能有这些框架——它必须是对

这不是一个特别新的问题领域,但我尝试了那里的建议,但运气不好。所以,我的故事:

我有一块15秒长的直接从camera.mov视频,我想从中提取一个特定的块,我可以通过开始时间和停止时间来识别,以秒为单位。我开始尝试做一个我称之为“拷贝提取”的事情:从9秒到12秒

ffmpeg -i test.mov -vcodec copy -acodec copy -ss 9 -to 12 test-copy.mov
这是一个不错的开始,但在片段的开头和结尾都有一些黑色的框架,我不能有这些框架——它必须是对原始片段的干净编辑。因此,我尝试将原作重新编码为一个新的修剪过的剪辑:

ffmpeg -i test.mov -ss 00:00:09 -t 00:00:03 test-out.mov
这样更好,但不完全是这样:在剪辑的开头不再有任何黑色帧,但在结尾它们仍然存在

经过更多的浏览和阅读,我怀疑问题在于ffmpeg由于原始视频中缺少关键帧而难以找到合适的点。因此,我对原始视频进行了重新编码(大概)添加关键帧,采用了两种不同的方式。由于我希望能够在一秒钟内(从9秒到12秒)挑选视频,我尝试了,在网上复制各种建议

ffmpeg -i test.mov -force_key_frames "expr:gte(t, n_forced)" test-forced.mp4

(我根据一些关于需要mp4容器来支持关键帧搜索的评论,将其构建为mp4,但老实说,我只是在这里进行黑客攻击。)然后,我像以前一样尝试提取,但在这些新视频上,可能现在已经有关键帧了。没有运气——两者似乎差不多;开始时还可以,但结尾仍有黑色边框。(FWIW,test-forced.mp4和test-g-inserted.mp4也都有黑色的尾随帧。)


所以:我还是被卡住了,我不想这样。有没有关于我做错了什么的见解?我觉得我很接近了,但我真的需要摆脱那些拖尾的黑框……

我也想知道。到目前为止,我已经无损转换了我的视频,提取了一段视频,并在编辑后对其重新编码:

ffmpeg -i input -ss 9.48 -t 3.52 -c:v libx264 -crf 0 -g 1 -c:a copy TempIframe.mp4
但这是一个耗时且有损的过程

我尝试了以下但没有成功:

ffmpeg -i source.mp4 -ss 1 -c:v copy -seek2any 1 -avoid_negative_ts 1 -safe 1 -c:a copy segment.mp4

好的,首先假设你知道开始和停止的持续时间;我们将在此期间添加关键帧

ffmpeg -i a.mp4 -force_key_frames 00:00:09,00:00:12 out.mp4
大多数情况下,你可以直接完美地剪切视频,但对你来说,这并没有帮助;所以我们已经按照上面的命令处理了它。这里要小心不要添加太多的关键帧,因为在按照进行编码时可能会出现问题

现在,您可以再次尝试从特定时间剪切视频

ffmpeg -ss 00:00:09 -i out.mp4 -t 00:00:03 -vcodec copy -acodec copy -y final.mp4
这将解决问题,因为我们已经在切割的起点和终点手动添加了关键帧。这对我有用


干杯。

我认为问题和其他答案的问题在于,他们在输出文件上使用了
-ss
选项,而不是在输入文件上。大多数ffmpeg选项不是全局的,而是只应用于它们前面的文件。选择的方向往往不明显,因此有时需要反复试验

正确使用,在输入文件之前,
-ss
-t
对我来说效果很好。当在输出中包含音频时,我必须使用
-shortest
作为输出文件的选项,否则我将获得2分钟的音频和2秒的视频

ffmpeg版本N-67413-g2a88c74(基本上是2014年12月14日的git源代码)

这是我最近用来制作剪辑的命令行。(事实上,这是一个更好的例子,因为我在音频中留下了这段视频,但并没有将其删除。)

ffmpeg-ss 120.2-t 0.75-i../mcdeint.60p.lossless264.slow.mkv-c:a libopus-shortest-aspect 16:9-preset veryslow-x264 params nr=250:ref=6-crf 22-movflags+faststart clip2.mkv

使用
-c:a copy
(源代码有AC3音频),mplayer会启动不稳定的播放。它可能从包含开始的音频帧的开始处获取音频,然后必须在容器中使用a/v偏移。在启动时,音频需要几分之一秒的时间才能超过视频的偏移量,在此之前,视频以非常低的FPS播放。所以我对音频进行了预编码。opus和PCMs16le都不能放在mp4中,因此我在本例中使用了一个mkv容器

源是一个无损x264编码(
-qp 0
),它来自一个非常慢的yadif=3:1,mcdeint=3:1:10(在一些来自NTSC DVD的BFF隔行视频上,可能来自DV摄像机)的输出。它不是所有的
I
帧,而是
P
帧,具有正常的关键帧间隔

将-ss调整0.2秒完全符合我的期望,因此ffmpeg必须将解码处理到所需的程度。这不仅仅是我想要的I帧的巧合。也许默认值是
-精确搜索
?我还得到了与使用ffvhuff无损源作为输入时相同的结果(逐字节相同的gif输出)。(但它运行得更快,因为它不必解码到请求的点。)

另一个可能相关的选项是
-seek2any
,但它说的是“在解复用器级别上查找非关键帧”,这听起来好像可以让您以产生乱码输出的方式进行查找。(即,在不实际生成当前帧所需的引用的情况下开始解码,仅使用全灰色?)

我还没有尝试过使用
-c:v copy
,因为我正在剪切一个非常短的循环剪辑,所以我知道在我需要它们的地方不会有
I

这是我实际使用的命令行,用于制作没有声音的短slo mo剪辑

ffmpeg-ss 120.2-t0.75-i../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv-最短-纵横比16:9-c:v libx264-预设veryslow-x264参数nr=250:ref=6-crf 22-过滤器:v“setpts=3.0*PTS”-movflags+faststart-r20 clip.mp4

请注意,
-r20
很重要,因为与mkv不同,ffmpeg的MP4输出是恒定的
ffmpeg -ss 00:00:09 -i out.mp4 -t 00:00:03 -vcodec copy -acodec copy -y final.mp4