題 如何使用ffmpeg將視頻轉換為GIF,質量合理?


我正在轉換 FLV 電影到 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的質量?

輸出命令:

ffmpeg -i input.flv -ss 00:00:00.000 -pix_fmt rgb24 -r 10 -s 320x240 -t 00:00:10.000  output.gif
ffmpeg version 0.8.5-6:0.8.5-0ubuntu0.12.10.1, Copyright (c) 2000-2012 the Libav developers
  built on Jan 24 2013 14:52:53 with gcc 4.7.2
*** THIS PROGRAM IS DEPRECATED ***
This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.flv':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-02-14 04:00:07
  Duration: 00:00:18.85, start: 0.000000, bitrate: 3098 kb/s
    Stream #0.0(und): Video: h264 (High), yuv420p, 1280x720, 2905 kb/s, 25 fps, 25 tbr, 50 tbn, 50 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 192 kb/s
    Metadata:
      creation_time   : 2013-02-14 04:00:07
[buffer @ 0x92a8ea0] w:1280 h:720 pixfmt:yuv420p
[scale @ 0x9215100] w:1280 h:720 fmt:yuv420p -> w:320 h:240 fmt:rgb24 flags:0x4
Output #0, gif, to 'output.gif':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-02-14 04:00:07
    encoder         : Lavf53.21.1
    Stream #0.0(und): Video: rawvideo, rgb24, 320x240, q=2-31, 200 kb/s, 90k tbn, 10 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Stream mapping:
  Stream #0.0 -> #0.0
Press ctrl-c to stop encoding
frame=  101 fps= 32 q=0.0 Lsize=    8686kB time=10.10 bitrate=7045.0kbits/s dup=0 drop=149    
video:22725kB audio:0kB global headers:0kB muxing overhead -61.778676%

謝謝。


257
2018-02-22 20:06


起源




答案:


ffmpeg 現在可以輸出更高質量的GIF。如果您使用較舊的構建考慮 下載最近的靜態版本 要么 編譯 ffmpeg

ffmpeg 例

gif with ffmpeg
203K

此示例將跳過輸入的前30秒並創建3秒輸出。它會將輸出縮放為320像素寬,並在保留縱橫比的同時自動確定高度。該 palettegen 和 paletteuse 過濾器將生成並使用從您的源生成的自定義調色板。

  1. 生成調色板:

    ffmpeg -y -ss 30 -t 3 -i input.flv \
    -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
    
  2. 使用調色板輸出GIF:

    ffmpeg -ss 30 -t 3 -i input.flv -i palette.png -filter_complex \
    "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
    

看到 採用FFmpeg的高品質GIF 了解更多示例和選項。


convert 例

另一種命令行方法是使用將電影導出到幀 ffmpeg 然後製作GIF convert 來自ImageMagick(或GraphicsMagick)。

ffmpeg and convert
246k

  1. 導出幀:

     mkdir frames
     ffmpeg -i input -vf scale=320:-1:flags=lanczos,fps=10 frames/ffout%03d.png
    
  2. 然後用 convert (要么 gm convert 如果您更喜歡GraphicsMagick)來製作動畫GIF:

     convert -loop 0 frames/ffout*.png output.gif
    

convert 你可以控制幀之間的延遲 -delay 如果需要的話


388
2018-02-22 21:31



添加了一些示例結果(雖然只是靜止幀)。這裡,第一個文件是4.1 MB,第二個文件大約是8 MB。 - slhck
@LordNeckbeard,你太棒了!非常感謝 -vf scale=320:-1,format=rgb8,format=rgb24 - Kamil Hismatullin
順便說一句,為了 convert 從我最終使用的PNG幀轉換的命令 convert -delay 5 -loop 0 -dither None -colors 80 "frames/ffout*.png" -fuzz "40%" -layers OptimizeFrame "output.gif",這大大減少了整體文件的大小 - Wilf
我覺得 convert 命令應該使用 -delay 10(幀之間0.1秒)匹配 -r 10 (10 fps)你正在餵的幀速率 ffmpeg。我用的時候 -delay 5,我看到gif以雙倍速度播放。 - Jack O'Connor
好的,我已經得到了,我用過了 scale=0:-1,所以當您將比例設置為 0,它將採取視頻的規模。 - Mousa Alfhaily


如果您希望避免使用中間圖像文件,可以在LordNeckBeard之間提供命令 ffmpeg 和ImageMagick的 convert 這樣就不需要中間文件了:

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而不進行優化。

請記住,在整個過程中,一切都在內存中,因此如果圖像非常大,您可能需要足夠的內存。


80
2018-03-18 09:47



這組命令也適用 avconv - raphael
您應該合併最後兩個轉換命令: convert -delay 5 -loop 0 -layers Optimize - output.gif - Clément
gif的運行速度似乎是源視頻的2倍? - Titan
@Titan認為它是第一個命令中的-r 10和第二個命令中的-delay 5。我也將延遲更改為10,現在似乎正常播放。 - Steven Huang
您還可以使用。避免使用中間圖像文件 split 在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


從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

H T 


29
2018-03-23 18:39





我製作了自己的腳本版本,它也可以參數化輸出分辨率和幀速率。

運行 ./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, 並且腳本與其他文件位於同一文件夾中。


13
2017-07-12 09:35



非常感謝您的腳本。我只是測試了它,效果很好! - orschiro


製作了一個腳本,測試和工作。

用法:

./avi2gif.sh ./vokoscreen-2015-05-28_12-41-56.avi

有PHUN :)

vim avi2gif.sh

#!/bin/sh

INPUT=$1

# 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 是一個優秀的ScreenCapturing工具Linux :)

感謝Michael Kohaupt :)搖滾穩定。

一些文件大小的統計信息:

5.3M = vokoscreen-2015-04-28_15-43-17.avi - > vokoscreen-2015-05-28_12-41-56.avi.gif = 1013K

看到了 結果在這裡。


8
2018-05-28 10:55





LINUX / UNIX / Mac系統

以下 @LordNeckbeard方法 同 ffmpeg 命令,請找到以下有用的Bash功能,可以添加到您的 ~/bash_profile 文件:

# Convert video to gif file.
# Usage: video2gif video_file (scale) (fps)
video2gif() {
  ffmpeg -y -i "${1}" -vf fps=${3:-10},scale=${2:-320}:-1:flags=lanczos,palettegen "${1}.png"
  ffmpeg -i "${1}" -i "${1}.png" -filter_complex "fps=${3:-10},scale=${2:-320}:-1:flags=lanczos[x];[x][1:v]paletteuse" "${1}".gif
  rm "${1}.png"
}

文件加載後(. ~/.bash_profile),你應該有新的 video2gif 命令。

用法示例:

video2gif input.flv

要么:

video2gif input.flv 320 10

縮放到320寬度,每秒10幀。

您還可以指定其他視頻格式(例如mp4)。


蘋果系統

你可以試試 GIF啤酒廠 可以從視頻文件創建GIF的應用程序。


另外,有幾個網站正在免費在線進行轉換。


7
2017-12-09 17:34





@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

7
2017-10-05 12:04



如果我理解正確,你將輸入分成o1和o2,並將o2複製到o3。那你為什麼需要o3?為什麼不直接使用o2? - Chloe
@Chloe你看到了嗎? fifo 過濾操作之間 o2 和 o3?避免 Buffer queue overflow 警告。 - alijandro


ffmpeg 與調色板 方法 可以在一個命令中運行,無需中介 .png 文件。

ffmpeg -y -ss 30 -t 3 -i input.flv -filter_complex \
"fps=10,scale=320:-1:flags=lanczos[x];[x]split[x1][x2]; \
[x1]palettegen[p];[x2][p]paletteuse" output.gif

這可以通過以下方式完成 split 過濾。


6
2017-09-30 15:23





所選答案假定您希望縮放源視頻並更改其生成的gif中的fps。如果您不需要這樣做,以下工作:

src="input.flv"
dest="output.gif"
palette="/tmp/palette.png"

ffmpeg -i $src -vf palettegen -y $palette
ffmpeg -i $src -i $palette -lavfi paletteuse -y $dest

當我想要一個忠實再現我正在使用的源視頻的gif時,這就派上用場了。


4
2017-11-14 23:01





以下是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)擴展名,那麼請改用:

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%
set var1=%1
set var2=%var1:~0,-4%
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y %var2%.gif

3
2018-06-23 22:31





對於Windows用戶:
創建 video2gif.bat Windows目錄中包含以下內容的文件:

@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

然後你可以使用它的任何地方就像這個例子:

video2gif myvideo.mp4

那你有 myvideo.gif 在當前目錄中。
如果 myvideo.gif 存在,來自你的問題是否覆蓋它。

編輯: 

我建議使用這個批處理腳本: https://github.com/NabiKAZ/video2gif


3
2018-04-21 15:36



我看到你在這裡做了兩件事:(1)將命令編寫為Windows(.BAT)命令腳本,(2)提供不同的過濾器組合(其他答案均未使用) 都  fps=10 和 scale=-1:-1)。 太陽的回答 已經給了我們一個批處理文件,那個(就像shell中的shell腳本一樣) pje的回答 和 thevangelist的答案)具有將過濾器列表分配給變量的優點(一旦),...(續) - Scott
(續)...所以它不需要拼出兩次列表(如批處理文件那樣)。 (我認為這會產生這樣的風險:如果用戶編輯腳本以更改其中一個列表而不更改另一個列表,則不一致會導致問題。)您是否至少可以解釋您選擇的過濾器(fps=10,scale=-1:-1)? (看到 知名度的回答 有關命令部分的解釋示例。) - Scott
@Scott你說的沒錯,所以我在這裡寫了一個新的有用的腳本: github.com/NabiKAZ/video2gif - Nabi K.A.Z.