我正在使用以下命令将视频转换为 GIF 文件ffmpeg
:
ffmpeg \
-i input.flv \
-ss 00:00:00.000 \
-pix_fmt rgb24 \
-r 10 \
-s 320x240 \
-t 00:00:10.000 \
output.gif
效果很好,但是输出的 gif 文件质量很低。
有什么想法可以提高转换后的 gif 的质量吗?
答案1
ffmpeg
例子
ffmpeg
可以输出高质量的 GIF。在开始之前,始终建议使用最新版本:下载或者编译。
ffmpeg -ss 30 -t 3 -i input.mp4 \
-vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
-loop 0 output.gif
-ss 30
此示例将跳过输入的前 30 秒( )并创建 3 秒的输出(-t 3
)。- 每秒帧数过滤器设置帧速率。示例中使用的速率为每秒 10 帧。
- 规模过滤器将调整输出宽度为 320 像素,并自动确定高度,同时保持纵横比。lanczos缩放算法在此示例中使用。
- 调色板和调色板使用过滤器将生成并使用根据您的输入生成的自定义调色板。这些过滤器有很多选项,因此请参阅链接以获取所有可用选项和值的列表。另请参阅高级选项部分。
- 分裂过滤器将允许所有操作在一个命令中完成,避免创建调色板的临时 PNG 文件。
- 使用输出选项控制循环
-loop
,但值令人困惑。值为0
表示无限循环,-1
为不循环,1
为循环一次表示播放两次。因此,值为 10 将导致 GIF 播放 11 次。
高级选项
stats_mode
(palettegen)。您可以强制过滤器将调色板集中在整个图片上(full
这是默认设置)、仅移动部分(diff
)或每个单独的帧(single
)。例如,要为每个单独的帧生成调色板,请使用palettegen=stats_mode=single
&paletteuse=new=1
。dither
(调色板)。选择抖动算法。主要有三种类型:确定性(bayer
)、误差扩散(包括默认的所有其他算法sierra2_4a
)和无。使用特定的抖动算法或根本不使用抖动,您的 GIF 可能会看起来更好。如果您想尝试,bayer
请务必也测试该bayer_scale
选项。
看使用 FFmpeg 制作高质量 GIF以获得解释、示例图像以及高级用法的更多详细信息。
ImageMagickconvert
示例
另一个命令行方法是通过管道从 ImageMagick传输ffmpeg
到convert
(或)。magick
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v pam \
-f image2pipe - | \
convert -delay 10 - -loop 0 -layers optimize output.gif
ffmpeg
选项:
-vf "fps=10,scale=320:-1:flags=lanczos"
A过滤图使用每秒帧数和规模过滤器。fps 将帧速率设置为 10,scale 将大小设置为 320 像素宽,高度自动确定并使用保留纵横比的值。lanczos缩放算法在此示例中使用。-c:v pam
选择 pam 图像编码器。示例输出 PAM (Portable AnyMap) 图像格式,这是一种简单、无损的 RGB 格式,支持透明度 (alpha),并受 支持convert
。它的编码速度比 PNG 更快。-f image2pipe
选择 image2pipe 多路复用器,因为当输出到管道时ffmpeg
需要告知使用哪个多路复用器。
convert
选项:
-delay
看设置帧速率部分。-loop 0
陷入无限循环。-layers optimize
将启用通用 GIF 优化器。请参阅ImageMagick 动画优化了解更多详情。它不能保证产生较小的输出,因此值得尝试-layers optimize
并比较结果。
设置帧速率
使用以下组合设置帧速率每秒帧数过滤ffmpeg
并-delay
在 中convert
。这可能会变得复杂,因为convert
只获取原始图像流,因此不会保留任何 fps。其次,-delay
中的值convert
在蜱虫(每秒有 100 个刻度),而不是每秒帧数。例如,fps=12.5
= 100/12.5 = 8 = -delay 8
。
convert
将值四舍五入-delay
为整数,因此 8.4 的结果为 8,而 8.5 的结果为 9。这实际上意味着仅支持部分帧速率在所有帧上设置统一的延迟时(可以为每个帧设置特定的延迟,但这超出了这个答案的范围)。
-delay
如果用作输出选项,它似乎会被忽略,因此必须-
像示例中所示的那样先使用它。
最后,浏览器和图像查看器可能会实现最小延迟,因此-delay
无论如何您都可能会被忽略。
视频由美国鱼类和野生动物管理局国家保护培训中心提供。
答案2
如果您希望避免使用中间图像文件,LordNeckBeard 提供的命令可以在ffmpeg
和 ImageMagick 之间进行传输convert
,这样就不需要中间文件了:
ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -loop 0 - output.gif
告诉-f image2pipe
ffmpeg 将视频分割成图像并使其适合通过管道输出,并-vcodec ppm
指定输出格式为 ppm(出于某种原因,如果格式为 png,则convert
不会从管道读取所有图像,或者 ffmpeg 不会输出所有图像)。这-
两个命令的 指定管道将分别用于输出和输入。
为了在不保存文件的情况下优化结果,您可以将输出通过管道传输convert
到第二个convert
命令:
ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -loop 0 - gif:- | convert -layers Optimize - output.gif
指示gif:-
将convert
其输出作为 gif 格式的数据进行管道传输,并-layers Optimize
指示第二个convert
执行optimize-frame
和optimize-transparancy
方法(请参阅 ImageMagick动画优化简介)。请注意,输出-layers Optimize
可能并不总是提供较小的文件大小,因此您可能需要先尝试转换为未经过优化的 gif 以确保万无一失。
请记住,在整个过程中,所有内容都位于内存中,因此如果图像很大,则可能需要足够的内存。
答案3
从 ffmpeg 2.6 开始,我们可以做得更好。基于使用 FFmpeg 制作高质量 GIF:
palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos"
ffmpeg -i input.flv -vf "$filters,palettegen" -y $palette
ffmpeg -i input.flv -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y output.gif
答案4
我做了自己的版本这个脚本,它也参数化了输出分辨率和帧速率。
运行./gifenc.sh input.mov output.gif 720 10
将从您提供的电影中输出 720p 宽 10fps GIF。您可能需要chmod +x gifenc.sh
对文件执行此操作。
#!/bin/sh
palette="/tmp/palette.png"
filters="fps=$4,scale=$3:-1:flags=lanczos"
ffmpeg -v warning -i "$1" -vf "$filters,palettegen" -y "$palette"
ffmpeg -v warning -i "$1" -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y "$2"
您可以在我的Github
假设:ffmpeg 已安装,并且脚本与其他文件位于同一文件夹中。