我有一个 60 fps 的短视频,我想将其转换为 GIF 文件。我运行
ffmpeg -i foo.flv foo.gif
它会生成一个 GIF 文件。太棒了!
唯一的问题是生成的 GIF 视频中的运动不连贯且不均匀。如果我使用其他工具,我可以看到 FFmpeg 创建了一个视频,其中第一帧长 10 毫秒,第二帧长 20 毫秒,第三帧长 20 毫秒,然后重复这样的过程:10 毫秒、20 毫秒、20 毫秒。如果我使用其他工具将其平滑为每帧均匀的 16 毫秒(不更改帧内容),结果看起来很漂亮。
FFmpeg 为什么要这样做?我怎样才能让它编写一个每帧请求 16 毫秒的 GIF 文件,这样我就不需要使用第二个工具了?
我现在已经看到了相关问题询问 60 fps 的 GIF 视频是否存在,但它没有解决如何要求 FFmpeg 改变其行为的问题。此外,它提出了一个新问题:如果 16ms 不是 GIF 可以表示的时间,那么我正在使用的其他工具在做什么,为什么它工作得很好?
答案1
正如所讨论的60 FPS 的 GIF 真的存在吗?还是最高只有 50 FPS?,GIF 中帧时间的分辨率为 10ms,因此不可能达到每帧 16ms 的精度。因此,问题的答案依次为:
ffmpeg 为什么这样做?
因为 10+20+20 平均可获得 60fps,并且是可以在 GIF 格式的限制内表示的具有该属性的最精确的近似值。
我怎样才能要求它编写一个每帧请求 16ms 的 gif,这样我就不需要使用第二个工具了?
你不能,因为 gif 格式不能表示这一点。但我发现要求它制作 50fps 的视频——能以 GIF 格式准确呈现——产生非常平滑的效果。可以使用以下方法实现:
ffmpeg -i foo.flv -vf fps=50 foo.gif
这使用最近邻时间插值来选择要传输到输出的帧。
如果 16ms 不是 gif 可以表示的时间,那么我使用的另一个工具是做什么的,为什么它运行良好?
我使用的另一个工具是 GIMP,它的选择是将每帧舍入到最接近的可表示大小,因此它默默地将我请求的 16ms/帧更改为 20ms/帧。它可能效果很好,因为我可怜的肉眼无法分辨出所有事情都发生得太慢而不正确;只能看出动作是平稳发生的,而不是以异常间隔发生的。