我正在尝试使用 ffmpeg 在精确的时间剪切视频文件。ffmpeg 帮助显示了一个选项 -timecode_frame_start 来指定起始帧,但我无法让此命令工作。生成的视频总是从原始视频的开头开始。以下是我正在运行的命令的示例:
ffmpeg -i input.mpg -acodec copy -vcodec copy -timecode_frame_start 200 -vframes 210 -n ouput.mpg
我已将 timecode_frame_start 选项移至其他选项之前和之后,结果没有变化。我是否需要指定其他选项?我尝试了各种文件格式,mkv、avi、mp4,但问题似乎与编解码器无关。这是我尝试过的一个文件:
http://www.seaotter.com/marine/movies/hermit-long-01.mpg
我是否遗漏了什么?
答案1
timecode_frame_start
不像这样工作。
根据帧号进行搜索是不可能的。从特定帧开始的唯一方法是将帧数转换为ss.ms
语法,或hh:mm:ss.ms
。因此,如果您的视频为 25 fps,并且您想从 133 帧开始,则需要先计算时间戳:
133/25=5.32
然后运行:
ffmpeg -ss 5.32 -i input.mp4 -c:v libx264 -c:a aac out.mp4
请注意,无法使用比特流复制 ( ) 剪切精确帧-c:v copy
,因为并非所有帧都是帧内编码(“关键帧”)。视频必须以关键帧开始才能正确解码。因此,您必须重新编码视频,例如使用如上-c:v libx264
所示的 H.264。您还可以选择无损编解码器,这样-c:v ffv1
可以保留输入视频的质量。
总而言之,-ss
执行重新编码时始终是帧精确的。
如果您还想编码特定数量的帧,请使用-frames:v
,例如:
ffmpeg -ss 5.32 -i input.mp4 -c:v libx264 -c:a aac -frames:v 60 out.mp4
请注意,您也可以选择使用select
/aselect
过滤器选择帧/音频样本。
ffmpeg -i input.mp4 -vf 'select=gte(n\,100)' -c:v libx264 -c:a aac out.mp4
然而,这比上面显示的选项慢-ss
,因为整个视频都将被解码。
答案2
选项
-vf select="between(n\,start_frame_num\,end_frame_num),setpts=PTS-STARTPTS"
例如,
-vf select="between(n\,200\,300),setpts=PTS-STARTPTS"
将视频从第 200 帧(含)剪切至第 300 帧(含),序列计数从 0 开始。
答案3
无损剪辑是一款跨平台 GUI 工具,使用 FFmpeg 作为后端,可无损剪切视频。您可以选择在关键帧或任意帧处剪切。
答案4
我有一个解决方案,但我不知道如何使用当前的 ffmpeg 命令来做到这一点(我在关键帧处复制的尝试也不准确。我想知道 ffmpeg 如何决定切点)。
我建议采用这种算法,将我们要复制的段(t1,t2)分为 3 个部分:
- 部分 (t1-x, t1+y),这是一个完整的编码块,应该重新编码才能精确复制部分 (t1, y)。
- 部分 (t2-z, t3+w),这是一个完整的编码块,应该重新编码才能精确复制部分 (z, t2)。
- 中间部分(y,z)包含完整的编码块,可以按原样复制。
- 将上述步骤得到的 3 个部分连接起来。
请注意,前两部分预计会很小(其中一个或两个部分的长度可以为零),因此重新编码过程会很快。这将使我们能够以稍慢的操作进行精确的剪切,但仍然比重新编码整个视频快得多。如果我们可以用一个命令进行多次剪切,速度会更快,因此我们只需遍历帧一次。我希望有人可以应用这一点,并告诉我们如何应用,或者提及一些 ffmpeg 团队,或者无论如何将其交给他们。