我正在使用 ffmpeg 过滤器命令处理视频-vf
。我想在特定时间偏移处冻结一帧(基本上我想用 00:19:59 处的帧替换从 00:20:00 开始的所有视频帧)。是否可以通过向我的命令添加另一个过滤器来实现?
我知道如何通过运行多个 ffmpeg 命令来实现这一点,但我正在寻找一个使用过滤器将我的管道简化为仅一个 ffmpeg 命令的简单解决方案:) 我看到一些建议,可以使用覆盖/tpad 过滤器来实现这一点,但到目前为止,我还在努力寻找一个好的命令。
谢谢你!
答案1
假设我们提前知道输入的持续时间,我们可以将trim
过滤器与tpad
过滤器链接起来。
例如,假设输入时长为 50 秒,我们希望保留前 20 秒,并在剩余的 30 秒重复最后一帧:
ffmpeg -y -i in.mp4 -vf "trim=duration=20,tpad=stop_mode=clone:stop_duration=30" out.mp4
将trim=duration=20
输入视频剪辑至 20 秒,并 tpad=stop_mode=clone:stop_duration=30
克隆最后一帧(前 20 秒)另外 30 秒。
为了使该过程自动化,我们可以使用 FFprobe 来获取持续时间,并使用 shell 脚本(或 Python 脚本)准备 FFmpeg 命令。
假设我们不知道输入的持续时间,并且我们不想要任何类型的编程,我们可以使用overlay
过滤器来保持输入的持续时间:
ffmpeg -y -i in.mp4 -filter_complex "[0:v]trim=duration=20,tpad=stop_mode=clone:stop_duration=1000000[v1];[0:v][v1]overlay=shortest=1" -c:a copy out.mp4
[0:v]trim=duration=20,tpad=stop_mode=clone:stop_duration=1000000[v1]
- 将输入缩短至 20 秒,并将最后一帧克隆很长时间。
结果存储在临时名称中[v1]
。[0:v][v1]overlay=shortest=1
- 覆盖[v1]
在输入视频上。
由于使用了,总时长由输入视频的时长决定shortest=1
。
请注意,overlay
过滤器仅用于保持时长(覆盖时[v1]
隐藏)。[0:v]
-c:a copy
- 复制音频流而不重新编码。
为了测试,我们可以使用合成视频文件(使用 FFmpeg 生成):
ffmpeg -y -f lavfi -i testsrc=s=192x108:r=1:d=50 -f lavfi -i sine=frequency=400 -shortest -c:a copy in.mp4
然后执行:
ffmpeg -y -i in.mp4 -filter_complex "[0:v]trim=duration=20,tpad=stop_mode=clone:stop_duration=1000000[v1];[0:v][v1]overlay=shortest=1" -c:a copy out.mp4
。
最后 30 秒重复播放第 20 帧。
音频保持不变。