ffmpegを使用して、適切な品質でビデオをGIFに変換するにはどうすればよいですか?


311

ffmpegでFLV映画を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の品質をどのように改善できますか?

コマンドの出力:

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%

ありがとう。


1
APNGが重要なのに、人々がGIFでパレットワークを行う方法はおもしろい。
КонстантинВан

回答:


447

ffmpeg

ffmpegからのGIF出力
183k

ffmpeg高品質のGIFを出力できます。downloadまたはcompileの最新バージョンを使用することを常にお勧めします

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)を作成します。
  • fpsフィルターはフレームレートを設定します。
  • スケールフィルターは、出力の幅を320ピクセルに変更し、アスペクト比を維持しながら高さを自動的に決定します。
  • palettegenおよびpaletteuseフィルタは、入力から生成されたカスタムパレットを生成して使用します。
  • 分割フィルターを使用すると、1つのコマンドですべてを実行できます。
  • -loop出力オプションでループを制御します。の値0は無限ループです。

より多くの例とオプションについては、FFmpegを使用した高品質GIFを参照してください。


Imagemagickのconvert

ffmpegからのGIF出力
227k

別のコマンドライン方法は、ImageMagickから(または)にパイプするffmpegことです。convertmagick

 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

フレームレートを設定する

組み合わせで設定したフレームレートfpsでのフィルタffmpeg-delayconvert。これはconvert、画像の生ストリームを取得するだけなので、複雑になり、fpsは保持されません。次に、の-delayconvertティック(秒あたり100ティック)であり、フレーム/秒ではありません。たとえば、with fps=12.5= 100 / 12.5 = 8 = -delay 8です。

convert-delay値を整数に丸めるので、8.4は8、8.5は9になります。これは、事実上、すべてのフレームに一定の遅延を設定するときに一部のフレームレートのみがサポートされることを意味します(特定の遅延はフレームごとに設定できますが、この答え)。

-delay出力オプションとして使用される場合、無視されるように見えるため-、例に示すように前に使用する必要があります。

最後に、ブラウザーと画像ビューアーは最小限の遅延を実装する-delay可能性があるため、いずれにしても無視される可能性があります。

US Fish&Wildlife Service National Conservation Training Centerのビデオ提供。


4
いくつかのサンプル結果を追加しました(ただし、まだ静止フレームです)。ここで、最初のファイルは4.1 MB、2番目のファイルは約8 MBです。
slhck

2
@LordNeckbeard、あなたは素晴らしい!感謝-vf scale=320:-1,format=rgb8,format=rgb24
カミルヒスマトゥリン

6
ところで、のためのconvertコマンド私が使用して終了PNGフレームから変換するためのconvert -delay 5 -loop 0 -dither None -colors 80 "frames/ffout*.png" -fuzz "40%" -layers OptimizeFrame "output.gif"全体的なファイルサイズを減少させる、かなり
Wilf

2
さて、私はそれを持っています、私は使用scale=0:-1したので、スケールを0に設定すると、ビデオからスケールが取得されます。
Mousa Alfhaily

2
このQ&Aは、今から100年後にすべての通信がミームを介して行われるため、トームに永続的にエンコードする必要があります(または、今のところ単に「固定」する必要があります)。この投稿の活動だけがそれを物語っていると思います。
ジョナサンノイフェルド

87

中間画像ファイルを回避したい場合は、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フォーマットはPNG形式されている場合、何らかの理由で(ppmであることを、出力形式を指定し、どちらかのconvertパイプからすべての画像を読み取らない、またはffmpegのはありませんそれらをすべて出力しない)。-両方のコマンドのためには、パイプがそれぞれ出力と入力のために使用されることを指定します。

ファイルを保存せずに結果を最適化するには、出力をconvert2番目の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:-指示convertGIFフォーマットされたデータとして、パイプへの出力および-layers Optimize第二伝えconvert実行するためoptimize-frame及びoptimize-transparancy方法を(ImageMagickの参照アニメーション最適化入門)。からの出力-layers Optimizeは常に小さいファイルサイズを提供するとは限らないことに注意してください。そのため、最初に最適化せずにgifに変換してみてください。

このプロセス全体ですべてがメモリ内にあるため、画像が非常に大きい場合は十分なメモリが必要になる場合があることに注意してください。


1
このコマンドセットは、次の場合にも機能します。avconv
raphael

最後の2つの変換コマンドをマージする必要があります。convert -delay 5 -loop 0 -layers Optimize - output.gif
Clément16年

gifはソースビデオの2倍の速度で実行されているように見えますか?
タイタン

@Titanは、最初のコマンドでは-r 10であり、2番目のコマンドでは-delay 5であると考えています。遅延も10に変更しましたが、現在は正常に再生されているようです。
スティーブン黄

2
splitffmpeg のフィルターを使用して、中間画像ファイルを回避することもできます。何もパイプする必要はありません: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

37

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


18

独自のバージョンのスクリプトを作成し、出力解像度とフレームレートもパラメーター化しました。

実行./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がインストールされており、スクリプトが他のファイルと同じフォルダーにある。


3
スクリプトをありがとうございます。私はちょうどそれをテストし、それはうまく機能します!
-orschiro

15

@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を直接使用しないのはなぜですか?
クロエ

1
@Chloe とのfifo間のフィルター操作を見ましたか?警告を回避するため。o2o3Buffer queue overflow
アリジャンドロ

+1これは私にとって非常にうまく機能します(参照されている問題を解決しました)。
イアンコリンズ

私はこのソリューションが大好きです。称賛!
レオニードウソフ

10

スクリプトを作成し、テストして動作します。

使用法:

./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はLinux用の優れたScreenCapturingツールです:)

たくさんありがとうMichael Kohaupt :)安定したロック。

いくつかのファイルサイズの統計:

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

こちらの結果をご覧ください。


10

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フィルターのおかげでできます。


10

Linux / Unix / macOS

以下の@LordNeckbeardアプローチffmpegコマンド、あなたの中に追加することができ、以下の便利なバッシュ機能見つけてください~/.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

1秒あたり10フレームで320幅に拡大縮小します。

別のビデオ形式(mp4など)を指定することもできます。


マックOS

ビデオファイルからGIFを作成できるGIF Breweryアプリを試すことができます。


あるいは、オンラインで無料で変換を行っているいくつかのウェブサイトがあります。


スクリプトはありませんPNGファイルについての私のためにエラーが発生し、私はGIF出力を取得していないが、.MP4入力ファイルは変更されません
lacostenycoder

7

選択した答えは、ソースビデオをスケーリングし、生成された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が必要なときに役立ちました。


6

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

そして、それを使用できる場所ならどこでもこの例のようになります:

video2gif myvideo.mp4

次にmyvideo.gif、現在のディレクトリにあります。存在する
場合myvideo.gifは、上書きするためにあなたからの質問。

編集:

このバッチスクリプトを使用することをお勧めします:https : //github.com/NabiKAZ/video2gif


2
ここで、2つのことを行ったことがわかります。(1)コマンドをWindows(.BAT)コマンドスクリプトとして記述し、(2)フィルターの異なる組み合わせを提供しました(他の回答はいずれもと fps=10を使用しませんscale=-1:-1)。  Sunの回答はすでにバッチファイルを提供しており、そのファイル(pjeの回答伝道者の回答シェルスクリプトなど)には、フィルターのリストを変数に割り当てるという利点があります(一度)、…(続き)
Scott

1
(続き)…そのため、リストを2回綴る必要はありません(バッチファイルのように)。(これにより、ユーザーがスクリプトを編集してリストの1つを変更し、他のリストを変更しない場合、不整合により問題が発生するリスクが生じると考えられます。)フィルターの選択(fps=10,scale=-1:-1)を少なくとも説明できますか?(コマンドの一部の説明の例については、著名人の回答を参照してください。)
スコット

1
@Scottあなたは正しいと言ったので、ここに新しい便利なスクリプトを書きます:github.com/NabiKAZ/video2gif
Nabi KAZ

4

以下は、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:サンプルのみの抽出

入力変数を1つだけ使用し、出力名に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

Windows 7/10の「右クリック」コンテキストメニューエントリを追加して、ビデオファイルをgifに変換する方法

他の回答のいくつかは、私が使用したvideo2gifスクリプトについて言及しました。ただし、任意のスクリプトを使用できます。

コンテキストメニューオプションを作成するには、レジストリを編集する必要があります。powershellコマンドプロンプトを開き、w / 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を実行」オプションが表示されます!

ところで私はffmpegをにインストールしC:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\video2gif.batスクリプトをのすぐ隣のbinディレクトリに入れましたffmpeg.exe。私も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キーを押すだけで、デフォルトをすばやく取得できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.