feed

2015年05月05日, 編集履歴

動画ファイルからより良いアニメーションGIFを作る

QuickTime PlayerでスクリーンキャプチャしたMOVからベターなアニメーションGIFを作る」で書いた方法よりも、より良い手法が解ったので覚え書き。

 前回の手法をかんたんにまとめると、

  1. ffmpegを使って動画を連番画像に切り出す
  2. ImageMagickのconvertコマンドで連番画像をアニメーションGIFに纏める

だった。前回の手法の問題点は、手順2で処理に時間が掛かること、動画の内容によっては色味が変化、あるいは崩れる可能性があることだった。

 今回の手法はImageMagickは用いずffmpegだけを用いる。ffmpegはv2.6以上必須。動画はffmpegが扱えるならなんでも良いと思う。

 手順:

  1. ffmpegで動画で使われている色を元に最適化されたパレット画像を生成
  2. ffmpegでパレットを元にアニメーションGIFを生成

パレット画像の生成

 パレット画像を生成するには、以下を実行する。

$ ffmpeg -i input.mov -vf palettegen -y palette.png

 -i input.movで入力動画の指定、-y palette.pngで出力するパレット画像の指定。-vf palettegenでパレット画像の生成を指定(palettegenフィルタのドキュメント)。

アニメーションGIFの生成

 パレット画像を元にアニメーションGIFを生成するには、以下を実行する。

$ ffmpeg -i input.mov -i palette.png -lavfi paletteuse -y output.gif

 入力動画と共にパレット画像も指定し、アニメーションGIFを生成する。-lavfi paletteuseでパレット画像の使用を指定(paletteuseフィルタのドキュメント)。

結果

を以下に示す。

ファイルサイズ動画・画像処理時間
入力動画148KB
ImageMagick(前回の手法)709KB約23秒
ffmpeg、パレット画像不使用293KB約2秒
ffmpeg、パレット画像使用(今回の手法)663KB約6秒

 ImageMagickを用いる手法(前回の手法)では、

$ ffmpeg -i input.mov -r 20 frames/%03d.png
$ convert -delay 5 -layers optimize frames/*.png output-imagemagick.gif

パレット画像不使用の手法では、

$ ffmpeg -i input.mov -r 20 -y output-ffmpeg-normal.gif

パレット画像使用の手法(今回の手法)では、

$ ffmpeg -i input.mov -vf fps=20,palettegen=stats_mode=diff -y palette.png
$ ffmpeg -i input.mov -i palette.png -lavfi fps=20,paletteuse -y output-ffmpeg-palette.gif

を実行した。

 前回の手法で生成したアニメーションGIFはテキストエディタのウィンドウの背景が薄青く変色してしまっているのが解る。これはまだましな方で、動画によってはもっと大きく色が崩れてしまったり、前フレームの残像が残ったりすることがある。パレット画像不使用の場合はドロップシャドウやメニューなど、半透明がからむ部分で編みかけのようになってしまっている。それらに比べて今回の手法で生成したものは、そういう画像の乱れが見られない。
 また、処理にかかった時間もパレット画像不使用に比べれば遅いものの、前回の手法の方よりは大幅に速い。出力ファイルサイズもパレット画像不使用よりは大きいが前回の手法よりは小さい、という結果になった。

おまけ(動画の切り抜き、拡大・縮小、FPSの変更)

 QuickTime Playerでスクリーンキャプチャする際、範囲選択の領域サイズが表示されないので、狙った領域サイズで収録するのが難しい。そこで、範囲選択を大きめに取って収録し、ffmpegを用いて切り抜き、縮小する方法を考える。

 切り抜きの場合、

$ ffmpeg -i input.mov -vf crop=640:480:52:0 -y output.mov

のようにする。-vf crop=640:480:52:0で切り抜きを指定(cropフィルタのドキュメント)。この指定の場合、元動画の左上を原点として(52, 0)の座標から領域サイズ640x480での切り抜きを行う。

 拡大・縮小の場合、

$ ffmpeg -i input.mov -vf scale=400:-1:flags=lanczos -y output.mov

のようにする。-vf scale=400:-1:flags=lanczosで拡大・縮小を指定(scaleフィルタのドキュメント)。

 FPSの変更は、

$ ffmpeg -i input.mov -vf fps=20 -y output.mov

のようにする(fpsフィルタのドキュメント)。

 切り抜きしつつ、縮小しつつ、FPSを指定して、パレット画像の生成をするには、

$ ffmpeg -i input.mov -vf crop=640:480:52:0,fps=20,scale=400:-1:flags=lanczos,palettegen -y palette.png

さらに、このパレット画像を使用してアニメーションGIFを生成するには、

$ ffmpeg -i input.mov -i palette.png -lavfi crop=640:480:52:0,fps=20,scale=400:-1:flags=lanczos,paletteuse -y output.gif

を実行する。

 ffmpegは引数指定が複雑で難しい。

余談

 今回の実験で使用した動画は、現在開発中の絵文字を入力するインプットメソッドの動作デモ。
 日本人的には、OS標準の日本語IMやATOK、Google日本語入力等の日本語インプットメソッドを通じて絵文字の入力はある程度容易に、いつも通りの操作で行えるが、ふだんインプットメソッドを意識しないで文字入力している層(英語圏など)はどうしているんだろうか。わざわざ文字ビューアを起動して、検索して、選択して、とやっているのか——そういうところから着想を得て現在鋭意開発中。ふだん通りの入力操作の延長上で絵文字をかんたんに入力できる環境を目指します。
 全世界の標準USインプットメソッドをこのEmoji IMで置き換えてやろうという野望を抱いています。

参考