ffmpegで動画をキレイなGIFアニメーションに変換する方法

先日、「gtop - 端末で使えるグラフィカルなシステムモニタ」を書いた時、スクリーンキャプチャした動画をffmpegでGIFアニメーションにして貼り付けました。その時に用いた方法を紹介します。最近はTwitterやInstagramもGIFアニメーションに対応しているので、Linuxで動画をGIFアニメーションに変換する方法を知っておけば、役に立つこともありそうです。

まず、Ubuntuでgtopを実行し、RecordMyDesktopで動作している様子をキャプチャしました。これは、デフォルトで「~/ビデオ/out.ogv」というファイルに出力されました。

開始10秒目から10秒間をGIF化したかったので、まずは以下のようにコマンドを実行してみました。

ffmpeg -ss 10 -t 10 -i out.ogv gtop-1.gif

このコマンドでできたのが、以下の画像です。

なんだかツブツブが入っていて、汚くなってしまいました。どうも、最大256色しか使えないGIFアニメーションをキレイに作成するには、あらかじめ「パレット画像」を作っておき、それを用いて変換する必要があるようです。また、他の画像とのバランスを考えて横幅を800pxに変換することにしました。

まず、以下のコマンドで横幅800pxで10秒間の動画「gtop.mp4」に切り出しました。

ffmpeg -ss 10 -t 10 -i out.ogv -vf scale=800:-1 gtop.mp4

次に、切り出した動画からパレット画像(palette.png)を作成しました。

ffmpeg -i gtop.mp4 -vf palettegen palette.png

そして、パレットを使いつつGIFアニメーションを出力しました。

ffmpeg -i gtop.mp4 -i palette.png -filter_complex paletteuse gtop-2.gif

これでキレイなGIFができたのですが、サイズが916KBytesになってしまいました。そこで、そんなに動きのある動画ではないので、フレームレートを15fpsから2fps(1秒間に2フレーム)に落とすため、以下の通り実行して作りなおしました。最初のコマンドでfps=2を指定しています。

ffmpeg -ss 10 -t 10 -i out.ogv -vf scale=800:-1,fps=2 gtop.mp4
ffmpeg -i gtop.mp4 -vf palettegen palette.png
ffmpeg -i gtop.mp4 -i palette.png -filter_complex paletteuse gtop-3.gif

これで530KBytes程度になりました。以下の画像です。

ここでは動きが少なく、縦横サイズも小さい動画を用いましたが、スマホやデジカメで撮った動画ならフレームレートが30fpsや60fpsで、ピクセル数もずっと多いはずです。そういった動画をそのままGIFにすると、巨大なファイルになってしまいます。カットする秒数を短くする、縦横サイズを小さくする、フレームレートを10〜15fps程度ぐらいに落とすといった処理を行えば、うまく小さくすることができるでしょう。以下は、1080pのsample.mp4の開始15秒目から8秒間をを、320x180ピクセル、10fpsでGIFに変換する例です。

ffmpeg -ss 15 -t 8 -i sample.mp4 -vf fps=10,scale=320:180,palettegen palette.png
ffmpeg -ss 15 -t 8 -i sample.mp4 -i palette.png -filter_complex "fps=10,scale=320:180,paletteuse" out.gif