我正在使用ffmpeg
将视频转换为GIF文件:
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
示例183k
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
本示例将跳过以下版本的前30秒(
-ss 30
)输入并创建一个3秒的输出(-t 3
)。比例滤镜会将输出的大小调整为320像素宽,并自动确定高度,同时保留宽高比。本示例中使用lanczos缩放算法。
palettegen和paletteuse过滤器将生成并使用从输入生成的自定义调色板。这些过滤器有很多选项,因此请参考链接以获取所有可用选项和值的列表。另请参阅下面的“高级选项”部分。
分割过滤器将允许在一个命令中完成所有操作,并避免了创建调色板的临时PNG文件。但是这些值令人困惑。
-loop
的值是无限循环,0
的值是无循环,而-1
将循环一次,这意味着它将播放两次。因此,值为10会使GIF播放11次。高级选项
palettegen和paletteuse过滤器还有许多其他选项。最重要的是:
1
(palettegen)。您可以强制滤镜将调色板聚焦在一般图片(默认为stats_mode
),仅活动部分(full
)或每个单独的帧(diff
)上。例如,要为每个单独的框架生成调色板,请使用single
和palettegen=stats_mode=single
。paletteuse=new=1
(paletteuse)。选择抖动算法。有三种主要类型:确定性(dither
),误差扩散(所有其他类型,包括默认的bayer
)和无。使用特定的抖动算法或完全不抖动,您的GIF可能看起来更好。如果您想尝试使用sierra2_4a
,请确保也测试bayer
选项。 >另请参阅palettegen和paletteuse文档以获取所有可用的选项和值。ImageMagick
bayer_scale
示例227k
另一个命令行方法是将ImageMagick的
convert
从ffmpeg
(或convert
)输送到管道。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
magick
选项:使用fps和scale过滤器的filtergraph。 fps将帧速率设置为10,缩放将大小设置为320像素宽,并自动确定高度并使用保留宽高比的值。本示例中使用lanczos缩放算法。ffmpeg
选择pam图像编码器。该示例输出PAM(便携式AnyMap)图像格式,这是一种简单,无损的RGB格式,支持透明(alpha)并受-vf "fps=10,scale=320:-1:flags=lanczos"
支持。编码比PNG更快。-c:v pam
选择image2pipe多路复用器,因为当输出到管道时,需要告知convert
使用哪个多路复用器。 /> -f image2pipe
请参阅下面的设置帧速率部分。ffmpeg
产生无限循环。convert
将启用通用GIF优化器。有关更多详细信息,请参见ImageMagick动画优化。不保证会产生较小的输出,因此不使用-delay
并比较结果是值得尝试的。设置帧频
通过结合使用
-loop 0
中的fps过滤器和-layers optimize
中的-layers optimize
来设置帧频。这可能会变得很复杂,因为ffmpeg
只会获取原始图像流,因此不会保留fps。其次,-delay
中的convert
值以刻度(每秒100个刻度)为单位,而不是以每秒帧数为单位。例如,当convert
= 100 / 12.5 = 8 = -delay
时。在所有帧上设置统一延迟时可以支持速率(可以为每帧设置特定延迟,但这超出了此答案)。convert
如果用作输出选项,则似乎被忽略了,因此如示例所示,必须在fps=12.5
之前使用。最后,浏览器和图像查看器可能会实现最小延迟,因此无论如何您的
-delay 8
都可能会被忽略。视频提供美国鱼类和野生动物服务国家保护培训中心。
#2 楼
如果您希望避免使用中间图像文件,则可以在ffmpeg
和ImageMagick的convert
之间通过管道传输LordNeckBeard提供的命令,这样就不需要中间文件:ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 5 -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 5 -loop 0 - gif:- | convert -layers Optimize - output.gif
gif:-
告诉convert
将其输出作为gif格式的数据进行管道传输,-layers Optimize
告诉第二个convert
执行optimize-frame
和optimize-transparancy
方法(请参见ImageMagick动画优化简介)。请注意,-layers Optimize
的输出可能并不总是提供较小的文件大小,因此您可能需要尝试先转换为gif而不进行优化,以确保没有问题。内存,因此如果图像很大,可能需要足够的内存。评论
这组命令还可以与avconv一起使用
–拉斐尔
2015年12月9日下午2:00
您应该合并最后两个转换命令:convert -delay 5 -loop 0 -layers Optimize-output.gif
–Clément
16年7月5日在5:50
gif的运行速度似乎是源视频的2倍?
–泰坦
16-10-10在13:28
@Titan相信它是第一个命令中的-r 10和第二个命令中的-delay 5。我也将延迟时间更改为10,现在看来正常播放了。
–黄even
17年1月8日在4:28
您还可以通过使用ffmpeg中的分割过滤器来避免中间图像文件。根本不需要传递任何内容:ffmpeg -ss 30 -t 3 -i“ input.flv fps = 10,scale = 320:-1:flags = lanczos,split [x] [z]; [z] palettegen [y ]; [x] [y] paletteuse“ output.gif
– Ajedi32
17年1月8日在23:26
#3 楼
从ffmpeg 2.6开始,我们可以做得更好: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
HT
#4 楼
我制作了自己的脚本版本,该脚本还参数化了输出分辨率和帧频。您可能需要对文件执行./gifenc.sh input.mov output.gif 720 10
。#!/bin/sh palette="/tmp/palette.png" filters="fps=,scale=:-1:flags=lanczos" ffmpeg -v warning -i "" -vf "$filters,palettegen" -y "$palette" ffmpeg -v warning -i "" -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y ""
您可以阅读我在Github上的详细信息
假设:已安装ffmpeg,
,该脚本与其他文件位于同一文件夹中。
评论
非常感谢您的脚本。我刚刚测试了它,效果很好!
–orschiro
16-2-5在9:32
该脚本正是我想要的-一种将OBS屏幕捕获转换为gif以便进行错误报告的超级简单方法
–杰姆
5月8日21:30
#5 楼
@Stephane的答案非常好。但是对于某些视频,它将收到类似Buffer queue overflow, dropping.
的警告,并且生成的gif
丢了一些帧。这是带有
fifo
过滤器的更好版本,可以避免在使用Buffer queue overflow
过滤器时使用paletteuse
。通过使用split
过滤器来避免创建中间调色板PNG文件。ffmpeg -i input.mp4 -filter_complex 'fps=10,scale=320:-1:flags=lanczos,split [o1] [o2];[o1] palettegen [p]; [o2] fifo [o3];[o3] [p] paletteuse' out.gif
评论
如果我正确理解,则将输入分为o1和o2,然后将o2复制到o3。那么为什么需要o3?为什么不直接使用o2?
– Chloe
18-09-28在23:26
@Chloe您看到o2和o3之间的fifo过滤器操作了吗?为了避免缓冲区队列溢出警告。
– Alijandro
18-10-23在1:45
+1对我来说确实很好(并解决了所提到的问题)。
–伊恩·柯林斯
18/12/17在13:56
我绝对喜欢这种解决方案。荣誉!
–莱昂尼德·乌索夫(Leonid Usov)
19年7月27日在10:18
#6 楼
具有调色板方法的ffmpeg
可以在单个命令中运行,而无需中间的.png
文件。#7 楼
Linux / Unix / macOS使用@LordNeckbeard方法执行
ffmpeg
命令后,请找到以下有用的Bash函数,可以将其添加到您的~/.bash_profile
文件中:# Convert video to gif file. # Usage: video2gif video_file (scale) (fps) video2gif() { ffmpeg -y -i "" -vf fps=${3:-10},scale=${2:-320}:-1:flags=lanczos,palettegen ".png" ffmpeg -i "" -i ".png" -filter_complex "fps=${3:-10},scale=${2:-320}:-1:flags=lanczos[x];[x][1:v]paletteuse" "".gif rm ".png" }
一旦函数被加载(手动或从
. ~/.bash_profile
),您应该有新的video2gif
命令。示例用法: > or:
video2gif input.flv
以每秒10帧的比例缩放到320宽度。
您还可以指定其他视频格式(例如mp4 )。
macOS
您可以尝试使用GIF Brewery应用程序,该应用程序可以从视频文件创建GIF。
有几个网站免费在线转换。
评论
您的脚本为我引发了一个错误,大约没有png文件,也没有gif输出,但是.mp4输入文件保持不变
–lacostenycoder
19 Mar 8 '19在15:49
谢谢。对我来说,1500和40的参数会生成完美的gif图像。
–悉达多
3月19日下午2:51
#8 楼
所选答案假定您希望缩放源视频并在生成的gif中更改其fps。如果您不需要这样做,则可以使用以下作品: br />#9 楼
制作了脚本,进行了测试,并且可以正常工作。用法:
./avi2gif.sh ./vokoscreen-2015-05-28_12-41-56.avi
有电话:)
sh
#!/bin/sh INPUT= # default settings, modify if you want. START_AT_SECOND=0; # in seconds, if you want to skip the first 30 seconds put 30 here LENGTH_OF_GIF_VIDEO=9999999; # in seconds, how long the gif animation should be echo "Generate a palette:" ffmpeg -y -ss $START_AT_SECOND -t $LENGTH_OF_GIF_VIDEO -i $INPUT -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png echo "Output the GIF using the palette:" ffmpeg -ss $START_AT_SECOND -t $LENGTH_OF_GIF_VIDEO -i $INPUT -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" $INPUT.gif
btw:vokoscreen是适用于Linux的出色屏幕捕获工具:)
非常感谢Michael Kohaupt :)稳定的摇滚。
某些文件大小统计:
5.3M = vokoscreen-2015-04-28_15-43-17.avi
->
vokoscreen-2015-05 -28_12-41-56.avi.gif = 1013K
在此处查看结果。
#10 楼
对于Windows用户:在Windows目录中创建具有以下内容的
video2gif.bat
文件: > @echo off set arg1=%1 set arg2=%arg1:~0,-4% ffmpeg -y -i %arg1% -vf fps=10,scale=-1:-1:flags=lanczos,palettegen %TEMP%\palette.png ffmpeg -i %arg1% -i %TEMP%\palette.png -filter_complex "fps=10,scale=-1:-1:flags=lanczos[x];[x][1:v]paletteuse" %arg2%.gif del /f %TEMP%\palette.png
然后在当前目录中有
myvideo.gif
。如果存在
myvideo.gif
,请询问您是否覆盖它。 br /> 我建议使用此批处理脚本:
https://github.com/NabiKAZ/video2gif
评论
我看到您在这里做了两件事:(1)将命令编写为Windows(.BAT)命令脚本,以及(2)提供过滤器的不同组合(其他答案均未使用fps = 10和scale = -1:-1)。 Sun的答案已经给了我们一个批处理文件,并且该文件(如pje的答案和thevangelist的答案中的shell脚本一样)具有将过滤器列表分配给变量(一次)的优点,...(续)
–斯科特
17年4月21日在19:09
(续)…,因此无需两次拼出列表(就像批处理文件一样)。 (我假设这会带来风险,如果用户编辑脚本以更改列表之一而不更改列表,则不一致会引起问题。)您能否至少说明选择的过滤器(fps = 10,缩放= -1:-1)? (有关命令各部分的解释示例,请参见值得注意的答案。)
–斯科特
17年4月21日在19:09
@Scott您说的没错,所以我在这里写了一个新的有用的脚本:github.com/NabiKAZ/video2gif
–纳比K.A.Z.
17年4月23日在6:46
#11 楼
如何添加Windows 7/10“右键单击”上下文菜单项以将视频文件转换为gif。我使用的其他一些答案提到了video2gif脚本。但是,您可以使用任何脚本。要创建上下文菜单选项,您需要编辑注册表。打开一个Powershell命令提示符,运行带有admin privs的命令。执行以下命令:
$key = "Registry::HKEY_CLASSES_ROOT\`*\shell\Run Video2Gif" New-Item -Path $key"\Command" -Value "C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat `"%1`"" -Force
现在右键单击文件时,您将具有“运行Video2Gif”选项!
btw我将ffmpeg安装到
C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\
并将video2gif.bat
脚本放入bin目录就在ffmpeg.exe
旁边。我还在Windows C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin
中添加了PATH
,但是我认为您不需要这样做。 video2gif-prompt.bat
,并使用注册表而不是video2gif.bat
来引用它:@echo off set /p inp=Enter extrta args, if desired: C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat %* %inp%
您仍然可以按Enter快速获取默认值。
#12 楼
以下是Windows用户的批处理文件:gifenc.bat:
set start_time=0 set duration=60 set palette="c:\temp\palette.png" set filters="fps=15,scale=-1:-1:flags=lanczos" ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -vf "%filters%,palettegen" -y %palette% ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y %2
来源:带有FFmpeg的高质量GIF:仅提取示例
如果您只想使用一个输入变量,并且输出名称仅具有GIF(发音为JIF)扩展名,请改为使用此扩展名:
#13 楼
ffmpeg命令:运行此命令,以便ffmpeg可以找出一个好的调色板:
ffmpeg -y -i foo.mp4 -vf fps=30,scale=320:-1:flags=lanczos,palettegen palette.png
运行以下命令将mp4文件转换为gif:
ffmpeg -y -i foo.mp4 -i palette.png -filter_complex "fps=30,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" foo.gif
您可能想要调整fps和缩放比例。两者中的任一个都较小将导致文件大小更好。
创建简单的别名函数
您也可以创建这样的别名函数。我将其添加到我的
.bashrc
或.bash_profile
中:function makegif { ffmpeg -y -i -vf fps=30,scale=320:-1:flags=lanczos,palettegen palette.png ffmpeg -y -i -i palette.png -filter_complex "fps=30,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" .gif }
,然后只需
makegif foo
注意:当然,您需要ffmpeg。在此处获取它https://www.ffmpeg.org/download.html或
brew install ffmpeg
评论
感谢您的别名功能。非常方便
–巴拉哈卡·卡西(Prabhakar Kasi)
7月29日下午2:14
评论
添加了一些示例结果(尽管只是静止帧)。在这里,第一个文件是4.1 MB,第二个文件是8 MB。
–slhck
13年2月22日在21:44
@LordNeckbeard,您真棒!非常感谢-vf scale = 320:-1,format = rgb8,format = rgb24
–卡米尔(Kamil Hismatullin)
13年2月22日在21:53
顺便说一句,对于从PNG帧进行转换的转换命令,我最终使用convert -delay 5 -loop 0 -dither None -colors 80“ frames / ffout * .png” -fuzz“ 40%” -layers OptimizeFrame“输出.gif”,从而大大减少了文件总大小
–野生
2014年7月24日13:58
好的,我知道了,我使用了scale = 0:-1,所以当您将scale设置为0时,它将采用视频的比例。
– Mousa Alfhaily
17年9月16日在12:20
必须将此Q&A永久编码在书本中(或暂时仅固定在此书中),因为从现在开始的一百年内,所有通信都将通过模因进行。我认为仅此帖子上的活动就说明了这一点。
–乔纳森·诺伊费尔德
18-10-7在8:15