我认为问题和其他答案的问题是它们-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 偏移量。在启动时,音频需要几分之一秒的时间才能领先于视频该偏移量,在此之前视频以非常低的 FPS 播放。所以我对音频进行了编码。opus 和 pcm_s16le 都不能进入 mp4,所以我在这个例子中使用了一个 mkv 容器。
源是来自非常慢的 yadif=3:1,mcdeint=3:1:10 输出的无损 x264 编码 ( -qp 0
)(来自 NTSC DVD 的一些 BFF 隔行扫描视频,可能来自 DV 摄像机)。不是所有I
帧,而是P
具有正常关键帧间隔的帧。
将 -ss 调整 0.2 秒正是我希望的,所以 ffmpeg 必须处理解码到所需的点。这不仅仅是我想要的 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
到 remux。顺便说一句,可以在重新混合时更改视频的 fps,无需 xcoding,而不能使用 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]
)