25
6

More than 1 year has passed since last update.

絶対にやっちゃダメだというgif変換方法と、その他の変換方法をやってみた

Last updated at Posted at 2022-02-21

気になるツイートを見つけました。

ffmpeg -i input.mp4 output.gif

で「容量が10倍とかになります」で「絶対にやっちゃダメです」と主張しているようですが、何の10倍かわかりません。
そこで、実際にgif変換を試してみることにしました。

使用するffmpeg

執筆時点で最新のWindows版を用意しました。
Builds - CODEX FFMPEG @ gyan.devffmpeg-git-full.7z を用いました。

ffmpeg version 2022-02-21-git-b8e58f0858-full_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11.2.0 (Rev7, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
libavutil      57. 21.100 / 57. 21.100
libavcodec     59. 21.100 / 59. 21.100
libavformat    59. 17.102 / 59. 17.102
libavdevice    59.  5.100 / 59.  5.100
libavfilter     8. 27.100 /  8. 27.100
libswscale      6.  5.100 /  6.  5.100
libswresample   4.  4.100 /  4.  4.100
libpostproc    56.  4.100 / 56.  4.100

変換元

今回は、以下の2種類の変換元を用意しました。

これを10fps、音声なしに変換し、1分間を切り出しました。
Bad Apple!!は最初の1分を、フリー素材は動きが激しくなってくる30秒地点から1分を切り出しました。
さらに、フリー素材のもとのサイズは1280×720でしたが、Giamでのgif変換に失敗したので縮小することにしました。

ffmpeg -i bad_apple_2_5.avi -t 60 -r 10 -an -q:v 2 bad_apple_2_5.mp4
ffmpeg -ss 30 -i FDR_and_7th_Street_Skateboarding-HD.mp4 -t 60 -r 10 -s 800x450 -an -q:v 2 street.mp4

以下のようなデータが得られました。

ファイル名 性質 解像度 長さ フレームレート ファイルサイズ
bad_apple_2_5.mp4 影絵 256×224 01:00 10 242,472 バイト
street.mp4 日常 800×450 01:00 10 5,659,549 バイト

gif変換

絶対にやっちゃダメとされる方法

まずは、元ツイートで絶対にやっちゃダメとされている方法をやってみました。

ffmpeg -i bad_apple_2_5.mp4 bad_apple_2_5_dame.gif
ffmpeg -i street.mp4 street_dame.gif

変換結果のファイルサイズは以下のようになりました。

変換結果 ファイルサイズ 元ファイルの何倍か
bad_apple_2_5_dame.gif 2,886,557 バイト 11.90
street_dame.gif 55,128,416 バイト 9.74

両方について、ファイルサイズは元ファイルの10倍前後になりました。
元ツイートの「余裕で容量が10倍とかになります」は、変換元のファイルとの比較だった可能性が考えられます。
ただし、これだけではffmpegが悪いのかgifの性質が悪いのかはわかりません。

Giam

ffmpegで動画を画像群に変換した後、Giam Version 2.09 を用いてgifに変換してみました。

mkdir bad_apple_2_5
ffmpeg -i bad_apple_2_5.mp4 bad_apple_2_5\%04d.png
mkdir street
ffmpeg -i street.mp4 street\%04d.png

Giamの書き込みオプションは、以下のようにしました。

  • パレット:できるだけパレットを統一
  • 最大色数:256色
  • 無条件ディザ:オフ
  • インターレース:オフ

変換結果のファイルサイズは以下のようになりました。
_noopt がついているファイルはGiamの「各コマサイズの最適化」の適用前、ついていないファイルは適用後です。

変換結果 ファイルサイズ 元ファイルの何倍か
bad_apple_2_5_giam_noopt.gif 3,539,418 バイト 14.60
bad_apple_2_5_giam.gif 3,335,043 バイト 13.75
street_giam_noopt.gif 92,632,809 バイト 16.37
street_giam.gif 94,372,316 バイト 16.67

いずれも「絶対にやっちゃダメとされる方法」より変換結果のファイルサイズは大きくなってしまいました。
さらに、フリー素材の変換結果では、「各コマサイズの最適化」の適用後の方が適用前よりファイルサイズが大きくなっています。
これは、入力の性質上各コマの画像サイズの削減はできず、前のコマと色が(偶然)同じ部分を無理矢理透明化したことで、
画像が複雑になり、圧縮が効きにくくなったためであると推測できます。

ffmpegで画像群からgifを作る

元ツイートは「これは絶対にやっちゃダメです」と主張していますが、「これ」が何かはよくわかりません。
もしかしたら、入力にmp4を使っているのが悪いかもしれません。
そこで、mp4のかわりに、Giamの入力として用いた画像群を入力として用いてみました。

ffmpeg -r 10 -i bad_apple_2_5\%04d.png bad_apple_2_5_frompng.gif
ffmpeg -r 10 -i street\%04d.png street_frompng.gif
変換結果 ファイルサイズ 元ファイルの何倍か
bad_apple_2_5_frompng.gif 2,886,557 バイト 11.90
street_frompng.gif 99,971,673 バイト 17.66

Bad Apple!!の変換結果は「絶対にやっちゃダメとされる方法」とピッタリ同じサイズでしたが、
フリー素材の変換結果はGiamによる変換結果よりさらに大きくなってしまいました。
Giamで開いて数コマ見てみた結果、mp4から直接変換した時に比べ、透過色で塗られる部分が少なくなっているようでした。
mp4から直接変換した時に比べ、エンコードの際の画像の劣化が減っている可能性があります。
例えば、4コマ目の画像は以下のようになっていました。

絶対にやっちゃダメとされる方法 Giam(最適化後) 画像群から変換
street_dame_004.png street_giam_004.png street_frompng_004.png

ImageMagickで画像群をgifに変換後、まとめる

餅は餅屋です。
事前に画像群を画像処理ソフトウェア…ImageMagickでgifに変換した後、それをアニメーションにしてみましょう。
Windows Binary Release の ImageMagick-7.1.0-25-Q16-HDRI-x64-dll.exe を使いました。

Version: ImageMagick 7.1.0-25 Q16-HDRI x64 2022-02-16 https://imagemagick.org
Copyright: (C) 1999-2021 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenCL OpenMP(2.0)
Delegates (built-in): bzlib cairo flif freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib
Compiler: Visual Studio 2022 (193030709)

gifに変換した画像を直接ffmpegに入力しようとするとうまく変換できなかったので、変換したgifを一旦pngに変換してからgifアニメに変換しました。

mogrify -format gif bad_apple_2_5\*.png
mogrify -format gif street\*.png
mkdir bad_apple_2_5_gif
mv bad_apple_2_5\*.gif bad_apple_2_5_gif\
mkdir street_gif
mv street\*.gif street_gif\
mogrify -format png bad_apple_2_5_gif\*.gif
mogrify -format png street_gif\*.gif
ffmpeg -r 10 -i bad_apple_2_5_gif\%04d.png bad_apple_2_5_mogrify_ffmpeg.gif
ffmpeg -r 10 -i street_gif\%04d.png street_mogrify_ffmpeg.gif

ffmpegだけでなく、Giamを用いても変換を行いました。
Giamの入力には、gifから変換したpngではなく、gifを用いました。
_noopt がついているファイルはGiamの「各コマサイズの最適化」の適用前、ついていないファイルは適用後です。

変換結果のファイルサイズは以下のようになりました。

変換結果 ファイルサイズ 元ファイルの何倍か
bad_apple_2_5_mogrify_ffmpeg.gif 2,384,378 バイト 9.83
bad_apple_2_5_mogrify_giam_noopt.gif 2,381,371 バイト 9.82
bad_apple_2_5_mogrify_giam.gif 2,383,864 バイト 9.83
street_mogrify_ffmpeg.gif 101,550,512 バイト 17.94
street_mogrify_giam_noopt.gif 98,906,161 バイト 17.48
street_mogrify_giam.gif 98,746,853 バイト 17.45

Bad Apple!! の変換結果は、「絶対にやっちゃダメとされる方法」より小さくなり、かつffmpegとGiamでほとんど同じサイズになりました。
しかし、元ツイートで「絶対にやっちゃダメとされる方法」を絶対にやっちゃダメとしている根拠である「容量が10倍とか」にはなってしまっています。
フリー素材の変換結果は、ffmpeg、Giamともに、pngの画像群から変換を行った場合より、gifへの変換を行った場合のほうが大きくなりました。
減色処理が2回走ることで、何か悪い影響があるのかもしれません。

ImageMagickで画像群をアニメーションgifにする

ImageMagickにもgifアニメを作る機能があるので、試してみました。

convert -delay 10 -loop 0 bad_apple_2_5\*.png bad_apple_2_5_convert.gif
convert -delay 10 -loop 0 street\*.png street_convert.gif
変換結果 ファイルサイズ 元ファイルの何倍か
bad_apple_2_5_convert.gif 2,842,270 バイト 11.72
street_convert.gif 101,544,003 バイト 17.94

Bad Apple!! のデータは「絶対にやっちゃダメとされる方法」に近いサイズに、フリー素材のデータはImageMagickでgifに変換した画像群をffmpegで変換した時に近いサイズになりました。

さらに良い入力を与えてみる

Bad Apple!! のデータは、白黒なのでgifにしやすそうということで今回の入力として選びました。
しかし、mp4に変換する過程で劣化し、余計な色が入っているかもしれません。
「絶対にやっちゃダメとされる方法」で変換した結果のコマをGiamでチェックすると、不自然な点々が入っているものがあり、効率の良い変換ができていない可能性が考えられます。

以下、31コマ目を比較してみます。
ただし、Giamで最適化をかけると一部の(動きの無い?)フレームが飛んでずれるようなので、Giamについては31コマ目に相当すると思われる16コマ目を用います。

ffmpeg
「絶対にやっちゃダメとされる方法」
Giam ImageMagick → ffmpeg ImageMagick → Giam ImageMagick
bad_apple_2_5_dame_031.png bad_apple_2_5_giam_016.png bad_apple_2_5_mogrify_ffmpeg_031.png bad_apple_2_5_mogrify_giam_016.png bad_apple_2_5_convert_031.png

そこで、FCEUXから出力するAVIファイルを未圧縮のものにし、それを直接ffmpegに入力してgifアニメや画像群に変換してみることにしました。
画像群からも、ffmpeg、Giam、およびImageMagickを用いてgifアニメに変換します。

ffmpeg -i bad_apple_2_5_raw.avi -t 60 -r 10 bad_apple_2_5_raw.gif
mkdir bad_apple_2_5_raw
ffmpeg -i bad_apple_2_5_raw.avi -t 60 -r 10 bad_apple_2_5_raw\%04d.png
ffmpeg -r 10 -i bad_apple_2_5_raw\%04d.png bad_apple_2_5_raw_frompng.gif
convert -delay 10 -loop 0 bad_apple_2_5_raw\*.png bad_apple_2_5_raw_convert.gif

さらに、比較のためmp4にも変換しておきます。

ffmpeg -i bad_apple_2_5_raw.avi -t 60 -r 10 -an -q:v 2 bad_apple_2_5_raw.mp4

変換結果のファイルサイズは以下のようになりました。

変換結果 説明 ファイルサイズ ffmpeg直接の何倍か mp4の何倍か
bad_apple_2_5_raw.mp4 mp4 102,964 バイト 0.06 1.00
bad_apple_2_5_raw.gif ffmpeg直接 1,802,129 バイト 1.00 17.50
bad_apple_2_5_raw_frompng.gif ffmpeg画像群経由 1,824,862 バイト 1.01 17.72
bad_apple_2_5_raw_giam_noopt.gif Giam最適化前 587,201 バイト 0.33 5.70
bad_apple_2_5_raw_giam.gif Giam最適化後 555,235 バイト 0.31 5.39
bad_apple_2_5_raw_convert.gif ImageMagick 608,777 バイト 0.34 5.91

全体的に、mp4から変換した時よりファイルサイズが小さくなっています。
しかし、ffmpegでの変換結果は、GiamやImageMagickでの変換結果に比べてファイルサイズが約3倍大きくなっています。
一方、GiamやImageMagickでの変換結果は、mp4に変換した時と比べてもファイルサイズが6倍以下に収まりました。

31コマ目(Giamは16コマ目)を比較してみます。

ffmpeg直接 ffmpeg画像群経由 Giam最適化後 ImageMagick
bad_apple_2_5_raw_031.png bad_apple_2_5_raw_frompng_031.png bad_apple_2_5_raw_giam_016.png bad_apple_2_5_raw_convert_031.png

Giamでは白と黒の変化の最低限の記録になっているようであるのに対し、ffmpegではやはり謎の点々が入ってしまいました。
そこで、以下のコマンドを用い、gifから各コマの画像を取り出してみました。

ffmpeg -i bad_apple_2_5_raw.gif bad_apple_2_5_raw_gif_frames\%04d.png
ffmpeg -i bad_apple_2_5_raw_giam.gif bad_apple_2_5_raw_giam_gif_frames\%04d.png

その結果、ffmpegで変換をした方には背景の白い部分に謎の黄色い点々が入っており、画像が劣化していることがわかりました。
以下は31コマ目(Giamは16コマ目)です。

ffmpegによる変換結果 Giamによる変換結果
0031.png 0016.png

まとめ

Bad Apple!! の変換結果

ファイル名 説明 ファイルサイズ 入力の何倍か
bad_apple_2_5.mp4 入力 242,472 バイト 1.00
bad_apple_2_5_dame.gif ffmpeg 2,886,557 バイト 11.90
bad_apple_2_5_frompng.gif 画像群 → ffmpeg 2,886,557 バイト 11.90
bad_apple_2_5_convert.gif 画像群 → ImageMagick 2,842,270 バイト 11.72
bad_apple_2_5_giam_noopt.gif 画像群 → Giam (最適化なし) 3,539,418 バイト 14.60
bad_apple_2_5_giam.gif 画像群 → Giam 3,335,043 バイト 13.75
bad_apple_2_5_mogrify_ffmpeg.gif 画像群 → gifに変換 → ffmpeg 2,384,378 バイト 9.83
bad_apple_2_5_mogrify_giam_noopt.gif 画像群 → gifに変換 → Giam (最適化なし) 2,381,371 バイト 9.82
bad_apple_2_5_mogrify_giam.gif 画像群 → gifに変換 → Giam 2,383,864 バイト 9.83

フリー素材の変換結果

ファイル名 説明 ファイルサイズ 入力の何倍か
street.mp4 入力 5,659,549 バイト 1.00
street_dame.gif ffmpeg 55,128,416 バイト 9.74
street_frompng.gif 画像群 → ffmpeg 99,971,673 バイト 17.66
street_convert.gif 画像群 → ImageMagick 101,544,003 バイト 17.94
street_giam.gif 画像群 → Giam (最適化なし) 94,372,316 バイト 16.67
street_giam_noopt.gif 画像群 → Giam 92,632,809 バイト 16.37
street_mogrify_ffmpeg.gif 画像群 → gifに変換 → ffmpeg 101,550,512 バイト 17.94
street_mogrify_giam.gif 画像群 → gifに変換 → Giam (最適化なし) 98,746,853 バイト 17.45
street_mogrify_giam_noopt.gif 画像群 → gifに変換 → Giam 98,906,161 バイト 17.48

Bad Apple!! (未圧縮) の変換結果

ファイル名 説明 ファイルサイズ mp4の何倍か
bad_apple_2_5_raw.mp4 mp4 (ffmpeg) 102,964 バイト 1.00
bad_apple_2_5_raw.gif ffmpeg 1,802,129 バイト 17.50
bad_apple_2_5_raw_frompng.gif 画像群 → ffmpeg 1,824,862 バイト 17.72
bad_apple_2_5_raw_giam_noopt.gif 画像群 → Giam (最適化なし) 587,201 バイト 5.70
bad_apple_2_5_raw_giam.gif 画像群 → Giam 555,235 バイト 5.39
bad_apple_2_5_raw_convert.gif 画像群 → ImageMagick 608,777 バイト 5.91

結論

ドット絵などの色数が少なく、それぞれの色の領域がはっきりしている画像をgifアニメに変換する場合は、その前に不可逆圧縮をかけて画像を劣化させてしまうと、画像が複雑になり、gifにした時にファイルサイズが大きくなる原因となるので、不可逆圧縮をかけてはいけません。
また、不可逆圧縮をかけなくても、ffmpegによりgifアニメへの変換を行った場合、ファイルサイズが比較的大きくなり、コマのデータに謎の点々が入ることがありました。
ffmpegの今回の使い方でgifアニメへの変換を行うと、劣化させずに変換できる画像でも劣化してしまうことがあるため、この使い方はこのようなケースのgifアニメの作成には適さないようです。

一方、実写の動画などの色数が多い画像をgifアニメに変換する場合は、ffmpegで直接変換する方法が今回の実験では一番ファイルサイズが小さくなりました。
容量が10倍など大きくなるのが許容できないのであれば、そもそも実写の動画などをgifアニメに変換するのがいけないと考えられます。

特定の変換方法を「絶対にやっちゃダメです」などと言って代案も提示せずに放り出すではなく、入力の性質、求める画質やファイルサイズ、再生環境などの条件に合わせた適切な変換方法を探すのがいいでしょう。

参考サイト

今回は、各ソフトウェアの使い方について、以下のサイトを参考にしました。

25
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
6