🌌

Webサイトの画像フォーマットは積極的に「AVIF」を使おう

2024/02/08に公開

2024年2月時点のWebサイトの画像圧縮・変換において、sharp(Node-API module)を使ったAVIFが実用可能なのか気になったので色々検証しました。
これは個人の実験による結論です。検証環境や方法などは本文をご覧ください。

結論

  • 基本的にWebPよりAVIFの方が、画質が良くなり容量が軽くなる。
  • 2024年2月現在では主要ブラウザはサポートされているので実用できるレベルでは。
    ※Edgeのみ2024年1月末の最新版からサポート。
  • Webサイトであれば、AVIFの設定はquality: 60〜80くらいに設定。
    他のオプションはデフォルトのままでよい。
    ※sharpのデフォルトはquality: 50
  • 保険としてフォールバック(AVIFに対応していないブラウザ対応)はした方がよい。
  • 生成(圧縮)する時間はWebPよりAVIFの方が2倍くらい長くなるので構成や設計には注意する。
  • 生成速度を優先するならqualityの設定を下げると効果的。
    effortで調整しない。

検証環境や方法など

環境

Name Version
OS macOS Ventura (13.5.1)
Processor 2.4 GHz 8-Core Intel Core i9
Node.js v20.11.0

いわゆるIntelのMacBook Proです。そろそろM2とかにしないとかな…😅

使用ライブラリ

Node.js製のsharp(v0.33.2)にて検証。
Next.jsやAstroなどのフレームワークにも採用されてますので、実用面からsharpで検証しました。
https://sharp.pixelplumbing.com/

サンプルデータ

下記4種類の画像で検証。

線形グラデーションのJPG画像(Gradation)


Photoshopで作成したもの。

カラーマップのJPG画像(Grid)


Three.jsでお馴染みのやつです。

ネコ様のJPG写真(Photo)


元素材の解像度が大きすぎるため縮小。毛並みの劣化具合で検証できます。
Thanks: Unsplash

ネコ様の背景を取り除いた透過PNG写真(Transparent)


上記JPG画像の背景緑を取り除き透過PNGにした写真。

その他

対象

コーポレートサイトや広告用のLPといった一般的なWebサイトの使用を目的とした検証・見解になります。
表示速度を優先するメディアサイト、画質にこだわるギャラリーサイトなどWebサイトやプロジェクトの特性に合わせパラメータは検討してください。

画質検証

元画像、デフォルト設定で生成された画像それぞれ表示比較する目視の検証になります。
実際に生成されたものが気になる方は下記検証リポジトリからAVIFに変換して確認してみてください。
もし、他によい方法などあればコメントなどで。

検証リポジトリ

あくまで検証用でざっくり作ってますので、処理や効率化とか甘いところあるとおもいます…。
※デフォルトにオプションを追加する形になってますので、仮にlossless: true{quality: 50, lossless: true}となります。
https://github.com/xx-suzuki/sharp-parameter-verification

# 依存ファイルのインストール
$ npm ci

# imagesフォルダの中にある画像データをdistに生成
# image-min.mjsにてパラメータ毎に生成する処理になってます。
$ npm run build

AVIFとWebPの比較

結論

  • 画質を基準にしたファイルサイズの比較では、AVIFの方がファイルサイズが小さくなる。
  • 元ファイルよりファイルサイズが大きくなったりするので、quality: 90以上の数値は設定しない。
  • 圧縮速度はWebPの方が早い。
  • AVIFとWebPのqualityの値は相関せず、AVIFのquality: 60とWebPquality: 80が同じくらいの画質。

画質

AVIFのquality: 60とWebPのquality: 80が大体同じくらいの画質。
WebPのquality: 70以下は画像の種類によって色がブレたりぼやけるので、使用は避けた方が良いかもしれません。

ファイルサイズ

AVIFとWebPのquality値を合わせて比較することに意味が無いため、案件の使用想定の画質合わせでAVIFはquality: 60、WebPはquality: 80の比較になります。
基本的にAVIFの方が圧縮率はよくなります。

圧縮速度

WebPの変換する方が早く、AVIFに変換するには2倍くらいプラスで時間がかかる。
マシンスペック、元の画像、オプションなど複合的な要因に影響されるため、2倍とはあくまで目安です。大体WebPが1秒で生成できるものはAVIFでは2〜3秒くらいかかるイメージです。

グラデーションの表現

グラデーションを綺麗に表示するなら、AVIF、もしくはjpgやpngで圧縮した方がよい。
WebPはlossless: truenearLossless: tureを有効に設定しないと綺麗に変換できないが、元の画像より容量が大きくなることもあり、わざわざWebPに変換する意味が無い。
特にWebPは縦線のような模様(モアレのような)が入るため注意が必要。

AVIFのオプション

設定できるのは下記の4つ。
https://sharp.pixelplumbing.com/api-output#avif

quality(品質):デフォルト50

低い値にすればするほど圧縮率が高く、圧縮時間も早くなる。
quality: 60〜80が元画像とほとんど見た目の変化がなく、圧縮率と時間のバランスよい。
元の画像と同じレベルを求めるなら、quality: 80

quality: 10は見た目は明らかに劣化するが、元画像1MBが1KBとか1024分の1くらいになる脅威の圧縮率。

デフォルトのquality: 50はややぼやけていると感じるレベル。

quality: 90〜100は画質の変化は目視ではわからないレベルで、圧縮率と時間の面からAVIFにするメリットがほとんどない。

quality: 40以下に設定すると生成速度が速くなる。

effort(エンコード速度):デフォルト4

低い値にすればするほどスピードが早く、圧縮率が悪くなる。
何も設定しないでデフォルトのeffort: 4で良い。
変換速度を優先したいなら、qualityを下げた方が効果的。

effort: 3以下に設定するとノイズや主に赤系の色ブレが起こる可能性あるので注意。

effort: 5〜9に設定しても大してファイルサイズ変わらない。
特にeffort: 9は時間かかりすぎる割にファイルサイズや画質も全然変わらないため設定しない方がよい。

lossless(可逆圧縮モード):デフォルトfalse

圧縮された画像を元の画像に戻すようにするかの設定。
変換時間も増え、元画像より容量が大きくなるケースがあるため、Webサイトでの利用であれば不要。

chromaSubsampling(エンコード方法):デフォルト'4:2:0'

色の解像度を下げて画像を圧縮するエンコード手法の設定。
'4:4:4''4:2:0'が設定できる。

ほとんど見た目が変わらず、デフォルトのchromaSubsampling: "'4:2:0'"で問題ない。
'4:4:4'の方が容量が若干大きく、時間も少し長くなる。

対応ブラウザ

2024年2月時点でChrome、Safariなどの主要ブラウザは全てサポートされている。
注意点としては、Edgeのみ2024年1月25日に安定版リリースされたv121からのサポートとなっているため、まだフォールバックの設定はしておいた方がよさそう。

https://caniuse.com/avif
https://learn.microsoft.com/en-us/deployedge/microsoft-edge-relnote-stable-channel

フレームワーク

Next.js、Astro、11ty、Nuxt (Nuxt Image)などの画像変換処理に大体sharpが導入されている。
オプションはそれぞれのフレームワークで設定できる(はず)なので、上記AVIFのオプションを参考にしてください。
注意点としては、動的にAVIF生成する場合は生成時間が問題となるため、事前にStatic Assets(publicフォルダなどの静的ファイル)に生成しておきそれを読み込む構成など対策が必要になる。

参考

https://nextjs.org/docs/app/building-your-application/optimizing/images

https://docs.astro.build/en/guides/images/

https://www.11ty.dev/docs/plugins/image/

https://image.nuxt.com/providers/ipx

実装方法サンプル

HTML

<picture>
  <source srcset="image.avif" width="1440" height="960" type="image/avif">
  <img src="image.jpg" decoding="async" width="1440" height="960" alt="">
</picture>

CSS

background-image: image-set(
  url("image.avif") type("image/avif"),
  url("image.jpg") type("image/jpeg")
);

https://caniuse.com/css-image-set

.htaccess (Apache)

# あくまで参考程度に

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_ACCEPT} image/avif
  RewriteCond %{REQUEST_URI} (?i)(.*)(\.jpe?g|\.png|\.gif)$
  RewriteCond %{DOCUMENT_ROOT}%1%2.avif -f
  RewriteRule (?i)(.*)(\.jpe?g|\.png|\.gif)$ %1$2\.avif [L,T=image/avif,R]
</IfModule>

<IfModule mod_mime.c>
  AddType image/avif .avif
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=REDIRECT_accept
</IfModule>

その他

デザインアプリケーションの対応状況

2024年2月現在、Photoshop・FigmaやAdobe XDなどといったデザインアプリケーションからAVIF出力はデフォルト機能としては無く、プラグインやアドオンを追加する必要がありそうです。
Web業界ではたびたび画像出力はデザイナー or エンジニアどちらがやるべき論みたいなものがありますが、AVIFの出力においてはエンジニアが対応して、出力されたものをデザイナーがチェックするという体制がよいとおもいます。

もしデザイナーの方でAVIFの画像を用意する必要があるのであれば、下記方法どちらかがよいとおもいます。

  • プラグインを入れての対応
  • Googleが開発した画像圧縮ツールSquoosh(Webアプリ版)を利用
    https://squoosh.app/

sharp

AVIFへの変換や圧縮以外にも色々できます。

  • リサイズ、クロッピング
  • 回転、反転
  • フィルター
  • 色彩の変更
  • jpg, pngの圧縮
  • WebPなど別のフォーマットに変換

その他の生成方法

Squoosh (libSquoosh)

Webアプリ版は開発が続けられていそうですが、Node.js版のlibSquooshは開発が停止してます。
https://github.com/GoogleChromeLabs/squoosh

ImageMagick、GraphicsMagickなど

サーバーサイドでAVIF生成する方法もあります。

imgIXなど

サービスプロバイダーを利用する方法もあります。
https://docs.imgix.com/apis/rendering/format/fm

おわりに

AVIFってどう?オプションは何を設定したらいい?実用可能?と軽い気持ちで始めた検証がかなり時間かかりました。
今後プロジェクトで使用していきますので、気になったことなどあれば追記する…かも。

冒頭の結論にも書きましたが、2024年2月現在の結論としては

  • 基本的にWebPに変換して使用するくらいならAVIFの方が、画質が良くなり容量が軽くなる。
  • 2024年2月現在では主要ブラウザはサポートされているので実用できるレベルでは。
    ※Edgeのみ2024年1月末の最新版からサポート。
  • Webサイトであれば、AVIFの設定はquality: 60〜80くらいに設定。
    他のオプションはデフォルトのままでよい。
    ※sharpのデフォルトはquality: 50
  • 保険としてフォールバック(AVIFに対応していないブラウザ対応)した方がよい。
    ※Edgeは特に注意が必要そう。
  • 生成(圧縮)する時間はWebPよりAVIFの方が2倍くらい長くなるので構成や設計には注意する。
  • 生成速度を優先するならqualityの設定を下げると効果的。
    effortで調整しない。
  • 生成した画像はチェックする。
  • NotionなどのアプリケーションもAVIF対応している。
  • AVIFはそのまま「エーブイアイエフ」と呼ぶのが正しいらしい。「アヴィフ」と言いたい…🫠

参考

https://sharp.pixelplumbing.com/
https://aomediacodec.github.io/av1-avif/
https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types
https://ics.media/entry/220204/
https://qiita.com/taqumo/items/3660b04400c28c5c2aa5
https://qiita.com/miyanaga/items/a616261de490cc342d08

Discussion