使用 ffmpeg 选择过滤器按精确帧剪切视频

使用 ffmpeg 选择过滤器按精确帧剪切视频

除了使用-ss-to寻找似乎不太准确的参数外,我可以根据给定的帧数剪切视频吗?例如;

ffmpeg -i video.webm -startingframe 80 -endingframe 560 output.webm

[包括第 80 帧和第 560 帧。因此,总共是 (560 - 80 +1) 帧]

经过回答和一番搜索后,我尝试了一些命令。但到目前为止,我找不到可接受的方法。

如果有人想剪切第 250 帧和第 750 帧之间的视频流,可以采用以下方法。它将输出 501 帧:

笔记:movie.mp4 的帧率为 25 fps,音频采样率为 48k

ffmpeg -i movie.mp4 -an -vf "select=between(n\,250\,750),setpts=PTS-STARTPTS" v_stream.webm

正如预期的那样,输出正好是 20 秒长。

对音频使用相同的方法:

ffmpeg -i movie.mp4 -vn -af "aselect=between(n\,480\,1440),setpts=PTS-STARTPTS" a_stream.webm

出乎意料的是,这个的准确率很差。它应该给我 960001(960k+1)个样本,相当于 20 秒的音频。但输出却是 20.505 秒长,有 984240 个样本。此外,如果我增加持续时间,误差也会增加。

然后我尝试使用 -ss -to 参数来剪切音频流:

ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm

传统的方法效果更好。输出时长为 20.003 秒,有 960144 个样本。此外,增加持续时间不会增加误差,误差是恒定的,该输入文件始终有 144 个样本剩余。

总结: select过滤器在大多数情况下效果很好,但aselect事实并非如此。经典-ss参数更适合音频,但样本不准确。此外,不能同时使用-vf select-ss参数,因为-ss会影响音频和视频流,而我们希望它只影响音频。

因此,为了精确剪切媒体文件,我必须执行以下 3 个步骤:

ffmpeg -i movie.mp4 -an -vf "select=between(n\,250\,750),setpts=PTS-STARTPTS" v_stream.webm 
ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm 
ffmpeg -i v_stream.webm -i a_stream.webm -c:v copy -c:a copy  movie-between_10th_and 20th_seconds.webm

这给出了最准确的结果。视频时长 20,000 秒,帧精确音频时长 20.003 秒,有 960144 个样本。与视频流不完全匹配,但还可以。只有 144 个样本剩余。最大的缺点是,每当我想剪切文件时,我必须为一个简单的任务发送 3 个命令,它会创建两个不必要的文件:a_stream.webmv_stream.webm。而且select过滤器对我尝试过的一些输入文件不起作用。它成功完成了任务(?)但从不停止编码过程,所以我每次都必须关闭命令提示符。

答案1

音频以秒为单位,而不是以帧为单位,因此,如果要剪切视频,则必须计算视频 fps × 20 秒,如下所示:20 秒,23.97 fps = 479.4

帧剪切并不准确,因为您无法在最后一秒获得完整的 fps,因此音频将获得更多秒数或仅半秒或多一点或少一点!也许您应该使用秒而不是帧来获得精确的剪切,您告诉 ffmpeg 为您完成此操作。如果您得到 1 个额外的帧,那么将第 250 和第 750 帧更改为第 250 和第 749 帧怎么样?!在那里使用减 1 始终可以获得您要求的帧数!

答案2

无法根据帧号进行搜索。从特定帧开始的唯一方法是将帧数转换为 ss.ms 语法,或 hh:mm:ss.ms。因此,如果您的视频为 25 fps,并且您希望从 250 帧开始,在 750 帧结束,则需要先计算时间戳:

250/25 = 10

750/25 = 30

您可以使用调整过滤器随着setpts,asetpts 过滤器在精确的位置剪切视频,例如

ffmpeg -i movie.mp4 \
 -filter_complex '[0:v]setpts=(PTS-STARTPTS),trim=10:30 \
  [0:a]asetpts=(PTS-STARTPTS),atrim=10:30' \
 movie-between_10th_and 20th_seconds.webm

请确保在修剪过滤器之前添加setpts=(PTS-STARTPTS)和,asetpts=(PTS-STARTPTS)以确保 pts 的计数从 开始0,以便产生帧精确的输出

相关内容