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

Jim*_*ler 36 video ffmpeg video-editing

这不是一个特别新的问题区域,但我已经尝试过没有太多运气的建议.那么,我的故事:

我有一段15秒的直--from-the-camera.mov视频,其中我想提取一个特定的块,我可以通过开始时间和停止时间,以秒为单位识别.我开始尝试做我称之为"复制提取"的事情:得到秒9到12,

ffmpeg -i test.mov -vcodec copy -acodec copy -ss 9 -to 12 test-copy.mov
Run Code Online (Sandbox Code Playgroud)

这是一个不错的开始,但在剪辑的开头和结尾有一些黑框,我不能 - 它必须是原始的干净编辑.所以,我尝试将原始内容重新编码为一个新的剪裁剪辑:

ffmpeg -i test.mov -ss 00:00:09 -t 00:00:03 test-out.mov
Run Code Online (Sandbox Code Playgroud)

这样更好,但并不完全:剪辑开头不再有任何黑框,但它们最后仍然存在.

经过一些浏览和阅读后,我怀疑问题是由于原始视频中缺少关键帧,ffmpeg无法找到合适的点.因此,我将原始视频重新编码为(可能)以几种不同的方式添加关键帧.由于我希望能够在一秒钟的界限内选择视频("从9秒到12秒"),我尝试在网络上复制各种建议,

ffmpeg -i test.mov -force_key_frames "expr:gte(t, n_forced)" test-forced.mp4
Run Code Online (Sandbox Code Playgroud)

ffmpeg -i test.mov -g 1 test-g-inserted.mp4
Run Code Online (Sandbox Code Playgroud)

(我建这些基于自己被需要支持关键帧搜索MP4容器一些意见MP4的,但我说实话只是黑客在这里.)然后我像以前那样试图提取,但这些新的影片,想必现在有关键帧在他们中.没有运气 - 两者似乎差不多; 开始没问题,但最后仍有黑框.(FWIW,test-forced.mp4和test-g-inserted.mp4也有尾随黑帧.)

所以:我仍然被卡住,并且不愿意.关于我做错了什么的任何见解?我觉得我很亲密,但我真的需要摆脱那些拖尾的黑框....

Blu*_*ord 35

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

ffmpeg -i a.mp4 -force_key_frames 00:00:09,00:00:12 out.mp4
Run Code Online (Sandbox Code Playgroud)

大多数情况下,您可以直接完美地剪切视频,但在您的情况下,它对您没有帮助; 所以我们通过上面的命令照顾它.这里要小心不要添加太多关键帧,因为根据Ffmpeg Docs进行编码时可能会出现问题.

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

ffmpeg -ss 00:00:09 -i out.mp4 -t 00:00:03 -vcodec copy -acodec copy -y final.mp4
Run Code Online (Sandbox Code Playgroud)

这将解决问题,因为我们在剪切的起点和终点处手动添加了关键帧.它对我有用.

干杯.:)

  • 谢谢指点!这似乎在时间方面运行良好,虽然它确实需要我想避免的重新编码,并且我仍然在修剪视频的末尾获得黑色帧.一些更多的实验表明,我的第一次无重新编码"复制"尝试只是略微偏离了这一次的时间,虽然它在开始时让我留下了黑色帧,但事实证明我用修剪过的视频做的事情(遗漏的长篇故事)忽略那些框架 - 也许它们是玩家的神器?所以,再次感谢,即使我最终坚持使用复制方法. (2认同)

Pet*_*des 10

我认为问题和其他答案存在的问题是它们在-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一起使用.它可能从包含开头的音频帧的开头抓取音频,然后必须在容器中使用aa/v offset.在启动时,音频通过该偏移在视频之前需要几分之一秒,直到那时视频以非常低的FPS播放.所以我对音频进行了编码.opus和pcm_s16le都不能进入mp4,所以我在这个例子中使用了一个mkv容器.

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

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

另一个可能相关的选择是-seek2any,但它说"在解复用器级别上寻找非关键帧",听起来它会让你以一种会产生乱码输出的方式寻找.(即开始解码而不实际生成当前帧所需的引用,只需使用全灰色?)

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

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

ffmpeg -ss 120.2 -t 0.75 -i ../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv -an -shortest -aspect 16:9 -c:v libx264 -preset veryslow -x264-params nr=250:ref=6 -crf 22 -filter:v "setpts=3.0*PTS" -movflags +faststart -r 20 clip.mp4

请注意,这-r 20很重要,因为与mkv不同,ffmpeg的MP4输出仅为恒定帧速率(编辑:因为-vsync vfr不是mp4复用器的默认值).在不说明它的情况下,它会设置输出FPS =输入FPS,并在需要时重复帧以实现这一点.x264和动画gif(具有透明度)可以非常有效地编码重复帧,但它仍然很愚蠢.

在做这个烹饪之前,我做了两个步骤,一个输出到mkv,然后再ffmpeg -i clip.mkv -c:v copy -movflags +faststart -r 20 clip.mp4重新启动.顺便说一句,有可能在没有xcoding的情况下更改视频的fps,而不是使用ffmpeg. https://superuser.com/questions/740196/reducing-video-size-with-avconv-why-does-the-size-increase.但无论如何,ffmpeg在制作mkv时只向libx264发送了45帧,尽管它认为它以60fps制作了2.2秒的视频.不要将ffmpeg与mp4一起使用来处理可变FPS内容.

编辑:结果ffmpeg默认-vsync vfr为mkv输出,但不适用于mp4.有了-vsync vfr,ffmpeg可以将VFR写入mp4输出就好了.

再次为gif输出,以防我决定不用HTML5视频(<video controls autoplay loop> <source src="clip.mp4" type="video/mp4"> </video>)

ffmpeg -ss 120.2 -t 0.75 -i ../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv -an -shortest -aspect 16:9 -filter:v "setpts=3.0*PTS,scale=854x480" -r 20 clip.gif

我不得不使用,scale=因为gif容器不存储宽高比,因此无法在播放时自动缩放.(我的720x480像素16:9视频在播放时缩放到854x480.实际上应该是853.333,但是它会四舍五入,然后ffmpeg将853x480存储在mkv容器中,因此一直使用-aspect 16:9,所以我的mp4将会存储适当的宽高比[SAR 32:27 DAR 16:9],而不是[SAR 186:157 DAR 279:157])


Ada*_*ers 6

无需添加关键帧; 正如彼得所说,这只是一个以正确的顺序获得选项的问题.但请参阅https://trac.ffmpeg.org/wiki/查看有关如何正确操作的权威官方指南.

  • 我可以猜测是因为答案不是独立的。只是说:“其他答案是对的,检查其他事情”。 (7认同)
  • 问题标题说“时间准确”,OP 正在使用编解码器副本。如果您阅读有关 Seeking 的链接指南的“在进行编解码器副本时进行查找”部分,您会发现它明确指出 -ss 作为带有编解码器副本的输入选项“可能不准确,因为 ffmpeg 被迫仅使用/在 i 帧上分割”。该文档基本上说它不准确,这也是我的经验,并且使这个答案无效。 (2认同)

ipa*_*tch 6

在树林里戳一只沉睡的熊???。我没有看到-to这个线程中提到的标志的任何提及,我发现它比-t标志更有用。一个对我很有效的示例命令,

ffmpeg -y -i [INPUT.file] -ss 00:42:42 -to 00:84:84 -codec copy [OUTPUT.file]
Run Code Online (Sandbox Code Playgroud)