使用 ffmpeg 选择过滤器以精确的帧切割视频

des*_*tor 17 ffmpeg

不是使用-ss-to寻找看起来不太准确的参数,我可以根据给定的帧数剪切视频吗?例如;

ffmpeg -i video.webm -startingframe 80 -endingframe 560 output.webm
Run Code Online (Sandbox Code Playgroud)

[包括第 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
Run Code Online (Sandbox Code Playgroud)

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

对音频使用相同的方法:

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

出乎意料的是,这个精度很差。它应该给了我 960001 (960k+1) 个等于 20 秒音频的样本。但是,输出的长度为 20.505 秒,并且有 984240 个样本。此外,如果我增加持续时间,错误也会增加。

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

ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm
Run Code Online (Sandbox Code Playgroud)

旧的经典方式效果更好。输出长度为 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
Run Code Online (Sandbox Code Playgroud)

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

小智 2

音频来自秒,而不是帧,因此如果您想剪切视频,您必须像这样计算视频 fps × 20 秒:\n23.97\xe2\x80\xaffps = 479.4 的 20 秒

\n\n

帧剪切不准确,因为您无法获得最后一秒的完整 fps,因此音频将获得更多秒或仅半秒或多一点或少一点!\xc2\xa0\n也许您应该使用秒而不是帧要获得精确的剪切,您可以告诉 ffmpeg 为您执行此操作。\xc2\xa0\n如果您获得 1 个额外帧,如何将第 250 和 750 帧更改为第 250 和 749 帧?!\xc2\xa0\n使用负 1总能获得您想要的帧数!

\n

  • 实际上音频来自样本,而不是秒...... (2认同)