我正在使用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)上。例如,要为每个单独的框架生成调色板,请使用singlepalettegen=stats_mode=single
paletteuse=new=1(paletteuse)。选择抖动算法。有三种主要类型:确定性(dither),误差扩散(所有其他类型,包括默认的bayer)和无。使用特定的抖动算法或完全不抖动,您的GIF可能看起来更好。如果您想尝试使用sierra2_4a,请确保也测试bayer选项。 >另请参阅palettegen和paletteuse文档以获取所有可用的选项和值。


ImageMagick bayer_scale示例

227k

另一个命令行方法是将ImageMagick的convertffmpeg(或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都可能会被忽略。

视频提供美国鱼类和野生动物服务国家保护培训中心。

评论


添加了一些示例结果(尽管只是静止帧)。在这里,第一个文件是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

#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-frameoptimize-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