![如何使用 ffmpeg 快速生成低质量动画 GIF?](https://linux22.com/image/1567475/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20ffmpeg%20%E5%BF%AB%E9%80%9F%E7%94%9F%E6%88%90%E4%BD%8E%E8%B4%A8%E9%87%8F%E5%8A%A8%E7%94%BB%20GIF%EF%BC%9F.png)
我们生成了很多缩略图 GIF,它们的质量并不重要,重要的是生成它们所需的时间。使用 ffmpeg 生成高质量 GIF 的介绍非常详尽,但我不太清楚如何尽快生成低质量的 GIF。
调色板计算占用了大部分执行时间,使用以下命令(取自此处的多链过滤器图答案:如何高效地从网络上的视频片段创建最佳调色板 gif):
ffmpeg -y -threads 8 -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter_complex "fps=24,scale=150:-1:flags=fast_bilinear,split=2 [a][b]; [a] palettegen [pal] fifo [b]; [b] [pal] paletteuse" output.gif
该命令的执行时间约为 72 秒,包含 1000 帧。其中约 67 秒用于调色板处理,然后约 5 秒内完成实际的 GIF 生成。我希望尽可能缩短整个执行时间,并愿意牺牲大量图像质量来提高速度。
答案1
您使用palettegen
/paletteuse
过滤器会使命令运行得更慢。实现低质量 GIF 的简单方法是:
ffmpeg -f image2 -i "frames.%04d.jpg" output.gif
附加缩放比例:
ffmpeg -f image2 -i "frames.%04d.jpg" -vf scale=150:-1 output.gif
您还可以在输出 GIF 中删除帧,即对帧进行采样,这样就不会处理所有帧。例如,使用过滤器仅输出 1 FPS fps
:
ffmpeg -i "frames.%04d.jpg" -vf "fps=fps=1,scale=150:-1" output.gif
答案2
我的任务是将生成动画 GIF 所需的时间缩短到尽可能接近 30 帧长、150 像素宽。我们生成的大多数序列都在 1000 帧以下。我们有一个 15,000 帧的序列,我们的渲染节点正在17 分钟生成这个约 30 帧的 GIF,速度慢得令人无法接受。
我们使用 ffmpeg 作为解复用器并通过管道传输到 imagemagick。经过几个小时的实验,我得出以下结论:
您要求 ffmpeg 处理的输入帧数是到目前为止执行速度方面影响最大的输入。如果使用 concat demuxer 跳过输入帧是一种选择,那么这将带来最大的性能差异。通过每 5 帧进行一次,我能够将总计算时间减少到1 分 45 秒具有高质量 Lanczos 重新缩放和每帧调色板计算。生成 30 帧预览缩略图现在只需不到 1 秒。
重新缩放算法是第二大性能影响因素(但远远落后于第二位)。使用 fast_bilinear 代替 lanczos 在所有 15,000 帧中节省了 150 秒的计算时间。
影响最小的变量是调色板计算,这因重新缩放算法而异。使用 lanczos 的 15,000 帧中,如果我们消除调色板计算,我们节省了大约 17 秒的执行时间。使用 fast_bilinear,我们节省了大约 75 秒的执行时间。
由于重新缩放算法和调色板计算可以忽略不计,我们最终将它们保持在最高质量。我们通过告诉 ffmpeg 跳过读取输入文件,将计算时间从 17 分钟缩短到 1 秒以下。
关键要点:跳过输入帧与跳过输出帧
我们的处理耗时如此之久的原因是,使用 image2 解复用器时,丢帧对执行时间没有帮助。如果您对标志-r
和fps
过滤器进行调整,将会影响最终 GIF 中出现的帧数,但 ffmpeg 似乎仍会对全部 15,000 个输入帧进行处理。
我发现让 ffmpeg 跳过输入帧的唯一方法是使用concat
解复用器。
以下是我现在通过跳过输入帧在 1 秒内在我的开发机器上生成高质量动画 GIF 缩略图的方法:
# create text file which describes the ~30 input frames we want ffmpeg to process
seq -f "file 'left_frames.%04g.jpg'" 10000 500 25000 > tmp.txt
# generate the animated gif using ffmpeg only
ffmpeg -f concat -i tmp.txt -filter_complex "scale=150:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" output.gif