使用 ffmpeg 冻结帧

使用 ffmpeg 冻结帧

我正在使用 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 帧。
音频保持不变。

相关内容