Jxck

WebP – Webを速くするためにGoogleがやっていること Make the Web Faster 01 –

連載: Make the Web Faster (2)

画像は、サイズが大きい(大きくなりがちな)コンテンツの一つです。 最近は画像を使わないページはほとんどなく、むしろ使う量はどんどん増えているんじゃないでしょうか。また、HiDPI対応などでサイズも増えつつあるでしょう。 Googleの調査では、現在Web上のトラフィックの65%を画像が占めているそうです。Introで解説したように、パフォーマンスを考えるとファイルサイズは「なるべく小さく」が望ましいため、画像は通常圧縮された形式で使用されます。

webp logo

WebPは、Googleが開発した圧縮形式で、従来の形式よりもファイルサイズを小さくすることを目的としています。今回はそんなWebPの概要と使い方、注意点を取り上げます。

画像圧縮とは?

ここで対象としているのはピクセル形式の画像で、ざっくり言うと「1pxごとにそこが何色なのか」という情報を持つ形式です。 例えば、Windowsのペイントなどで作れるBitmap(.bmp)という形式がなじみ深いでしょうか。

ところが、例えば以下の画像を見て下さい、同じ色が連続している場所があります。 そこで、「このピクセルは赤、このピクセルも赤…」と繰り返す情報を、「ここからここまで赤」と置き換えると、同じ情報を小さく表せるはずです。

可逆圧縮のイメージ図

このように、同じ情報を小さく表現する方法を圧縮といいます。これを画像に適用したのが画像圧縮です。 上の図の方法は逆の計算をすれば元の画像が完全に復元できるため、「可逆圧縮(lossless)」といいます。

また、写真などにはものすごく細かい色の変化もあり、なくなっても人間は気づかれない場合が多いので、こうしたデータを捨てることで圧縮率を上げる方法もとられます。代わりに、完全には元に戻せなくなるため、この方法は「非可逆圧縮」と呼ばれます。

非可逆圧縮のイメージ図

この例は、あくまでもイメージで、実際には同じ情報を小さく表わす方法はいろいろとあり、それにより圧縮形式が異なります。 次によく使われる圧縮形式を見てみましょう。

圧縮形式

Webの世界では、現在以下の三つがよく使われています。

  • JPEG: 写真など色数の多いものに有効。非可逆圧縮。
  • GIF: 色数が少ないアイコンなどに有効、アニメーションが可能。可逆圧縮(*1)。
  • PNG: アイコンなどに使われ、透過も可能。可逆圧縮。

現状はこれらの形式を場合に応じて使い分けているわけですが、Googleは多くの場合にこれらの形式よりも小さく圧縮でき、透過やアニメーションなどの機能もそろった新しい圧縮形式を開発しました。それが、WebPです。

*1: 非可逆も可能です。

WebP

読み方は、Weppy=ウェッピーです。 ファイルの構造としては、同じくGoogleが持つVP8コーデックを用いたWebMという動画フォーマットをベースとしており、WebMの1フレームだけを切り出したものがWebPで、それをRIFFという軽量なコンテナに格納した形式になっています。

https://developers.google.com/speed/webp/

WebPは以下のような特徴があります。

  • 可逆 / 非可逆圧縮が可能
  • 透過 (アルファチャネル) が可能
  • 写真の圧縮にも向いている
  • アニメーションが可能
  • カラープロファイル対応
  • メタデータを持たせることができる

画像に求められる基本的な機能をひと通り備えており、一つのフォーマットで幅広い用途で利用できるように作られていることがわかります。 現在Googleのサービスでは、Gmail、Google Drive、Picasa、Play Magazines、Image Search、YouTube、Chrome Web Storeなどがサポートしており、Facebookもサポートを始めました。

ブラウザ対応

現在、以下のブラウザがWebPに対応*2しています。

  • Chrome
  • Opera (12.0~)
  • Android Browser (4.2~)
  • Chrome for Android

Firefoxでは議論中で、IEやSafariは対応していません。 こうしたクライアントを対象とする場合は、後ほど説明するフォールバックが必要になります。

*2: http://caniuse.com/webp

ツール

WebPは以下のような公式のライブラリ、オーサリングツールなどで生成することができます。

しかし、FacebookがWebPをサポートしたところ、ユーザから「画像をダウンロードしたら、編集ソフトで編集できなかった」というクレームがあったというニュースがありました。

これは、上記のようなメジャーなものを除いて、まだWebPに対応していないオーサリングツールが多くあることを意味しています。 また、OSのデフォルトのプレビューでは見れないため、Webから落とした後のことも考えるのであれば、代替手段として同じ画像のPNGやJPEGをダウンロードする手段を用意することが望ましいでしょう。

WebP Library

今回はWebP公式ライブラリに同梱されたCLIツールを用いて、実際に画像をWebPに変換してみます。 公式ライブラリは以下のページで公開されています。

Downloading and Installing WebP

ここには以下のツールと、開発用のライブラリが含まれます。

  • cwebp: WebP への変換
  • dwebp: WebP からの変換
  • vwebp: WebP の表示
  • webpmux: アニメーションの作成
  • gif2webp: GIF から WebP への変換

これらのツールはかなりたくさんのオプションがあります。詳細はドキュメントを参照ください。

ここでは、使い方の解説を兼ねてPNG、JPEG、GIFとの簡単な比較をしてみます。(ライセンス情報は末尾に記載)

あくまで簡単な実験です、より厳密かつ詳細な比較結果は、こちらを参照ください。

可逆圧縮

可逆圧縮を、PNGファイルと比べてみます。 対象はPNGがよく使われるWebのUIアイコンとして、下記のPNGをもとにWebPに変換したものを比較します。

::
$ cwebp uikit.lossless.png -o uikit.lossless.webp -lossless
PNG WebP
loss less png
74 KB 62 KB

非可逆圧縮

非可逆圧縮をJEPGファイルと比べてみます。 対象はJPEGがよく使われる写真として、おなじみlennaさんのPNGをもとに、ImageMagickでJPEGに変換したものとWebPに変換したものを比較します。

::
$ cwebp lenna.lossless.png -o lenna.lossy.webp
$ convert lenna.lossless.png lenna.lossy.jpeg
JPEG WebP
74 KB 20 KB

アニメーション

5つのJPEG画像をもとに、500msごとに切り替えるアニメーションをGIFとWebPで作って比較します。

::
$ webpmux -frame 1.webp +500+0+0+0 -frame 2.webp +500+0+0+0 -frame 3.webp +500+0+0+0 -frame 4.webp +500+0+0+0 -frame 5.webp +500+0+0+0 -o animation.webp
$ convert -delay 50 -loop 0 *.jpg animation.gif
GIF WebP
262 KB 55 KB

残念ながら執筆時点では、WebPアニメーションを表示できるブラウザはないため、上記は表示されてないかもしれません。その場合はvwebpコマンドで表示できます。

::
$ vwebp animation.webp

GIFは色数が少ないため、写真を元にするとざらついた画質になりますが、WebPは比較して綺麗なアニメになっていることが分かると思います。

圧縮解凍の速度

WebPは圧縮率を上げるために、以下の追加コストがかかります。*4

  • 圧縮: JPEG より 5~10 倍程度のコスト
  • 解凍: JPEG より 1.3 倍程度のコスト

特に圧縮は大きな差に感じます。 しかし、画像は一般的に一度作られたら更新されることが少ないリソースであり、圧縮が必要なのは一回ですが、参照される機会が多いのが特徴です。 WebPは多少時間をかけて、じっくりと小さく圧縮することを選択しています。

CPU資源は、サーバ側はサービスの規模に応じて投資してコントロールできますし、クライアント側は最近はモバイル端末ですらそれなりの処理性能を持っています。 ネットワーク資源は、サーバとクライアント間で状況により変わり、サービス側の投資だけではコントロールしきれないという特徴があります。 したがって、圧縮/解凍にかかる時間よりも、ファイルを小さくすることを選択するほうが、現在のWebを取り巻く環境を考えると妥当な場合が多いと考えられます。

しかし、動的に画像を生成するようなサービスでは、従来のフォーマットと比べるなどの検証が必須になるでしょう。

*4 http://www.igvita.com/slides/2013/io-webp.pdf (P.13)

フォールバック

執筆時点では対応するブラウザは限られています。従ってWebP非対応のブラウザのためにはPNGなどへのフォールバックを検討する必要があります。 対応方法は主に以下があります。

  • サーバ側で対応
    • Accept ヘッダでの判別
    • User-Agent ヘッダでの判別
  • クライアント側対応
    • JavaScript でのフォールバック

Accept での判別

クライアント・サーバ間での対応フォーマットの確認は、通常HTTP1.1のコンテントネゴシエーションという機能を用いて行います。 具体的には、WebPに対応したブラウザは、画像のリクエストのAcceptヘッダにimage/webpを付与することが求められており、サーバはこの値をもとにクライアントの対応を知ることができます。

手元のChrome29では、HTML中のimgタグのリクエストに以下のヘッダが確認できました。

Chrome の Accept Header

この方法は、クライアントとサーバの間にキャッシュサーバが入る場合に注意が必要です。 同じURLから取得できるコンテンツがクライアントによって異なるので、キャッシュが共有されることで問題が起こる可能性があるためです。 これを防ぐためには、キャッシュに「Acceptヘッダによって、配信するソースが違う」ということを教えるためにVaryヘッダを付与します。 (この情報はGoogleのBotなどがコンテンツ内容を把握する上でも重要です。)

::
Vary: Accept

コンテントネゴシエーションをサーバに設定する例は、webp-detectが参考になります。

User-Agentでの判別

Chrome29は先のように、imgタグに対してimage/webpを送っていましたが、直接画像のURLにアクセスした場合は送っていません。(Canaryでは全ての画像のリクエストに送ります) またWebPに対応していなくても、全てを許容する意味の */* を送信するブラウザもあり、Acceptヘッダだけで判別するのは難しい場合があります。

そして、せっかく画像サイズを減らしているのに、Acceptヘッダに新しい情報を追加してしまっては、クライアントからサーバへ送信する情報を増やします。その理由から全てのブラウザが、今後Acceptヘッダを対応をするかどうかはまだ分かりません。 *3

こうしたブラウザ場合は、対応をUser-Agentから判断することもできます。 対応するブラウザは、http://caniuse.com/webp から確認できますが、より細かくバージョンを指定したい場合は、 Google Page Speed のソースが参考になります。

*3 HTTP/2.0では、HPACKというヘッダの送受信を効率化する方式が採用される見通しであり、ヘッダへの情報追加によるオーバーヘッドは、HTTP/1.1に比べて減らせる可能性があります。

Nginx のサンプル

以下は、ここまでの判別方法を元に、Nginxでブラウザの対応に応じて切り替える例です。 対応している場合はlogo.webpを、非対応の場合はlogo.pngをレスポンスしています。

実際に以下のリンクで動作を確認できます。(対応ブラウザはWebP、非対応はPNG画像が返ってきます)

https://jxck.io/labs/webp/logo

HTMLごと切り替える

logo.webpとlogo.pngのURLを明示的に分けたい場合は、それらを含むHTMLをまるごと切り替える方が良い場合もあります。

この場合も、User-Agentによって切り替え、Varyヘッダを付与するとよいでしょう。 もしくは、以下のヘッダを付与することでキャッシュの共有を限定してしまう方法もあります。

::
Cache-Control: private

ただしこの方法では、例えばWebPに対応したクライアントで取得したlogo.webpのURLをtwitterなどで共有した場合、 WebPに対応しないクライアントでそれを開くと中身を見ることはできません。こうした状況を想定するならUser-Agentも併用する必要があるでしょう。

JavaScriptでフォールバックする方法

まず、Modernizr.jsには、ブラウザのWebPサポートを調べる機能があります。 これを用いて、読み込む画像をJavaScriptで動的に切り替えることができます。

また、WebPがWebMの1フレームに相当することを利用し、 videoタグでWebPを表示可能にする weppy.js というライブラリもあります。

これを用いると、WebMに対応したFireFoxでもWebPが表示できます。

より強力なライブラリとして、WebPのデコードをJSでやってしまうwebp.jsというライブラリもあります。 こちらは、なんとIE6以降でほぼ全てのブラウザに対応しています。

まとめ

画像を効率よく圧縮できれば帯域を節約でき、特にモバイル対応の場合は全体のパフォーマンスに大きく影響が出ます。 WebPはこの点を解消するために生まれ、圧縮率等に関しては一定の成果を出していると言えるでしょう。

しかし、まだ普及しきっていないため、フォールバックなど考慮すべき点もあります。特に、フォールバックのために施した対策のために、WebPで得られた以上のオーバーヘッドが生じては、パフォーマンスの観点からは台無しです。(全てWebP対応を考えた上での暫定策であれば別ですが)

また、圧縮効果が高いかどうか、不可逆でも画質を維持できるかどうかは、全てどういう画像をどういう用途で配布するかにかかります。パフォーマンスの向上も、今回解説したことを踏まえて、「推測するな測定せよ」を忘れずに実施してください。

Version

  • libwebp 0.3.1
  • ImageMagick 6.8.6-3
  • Mac OSX 10.7.5

Photo License

週間PVランキング

新着記事

Powered byNTT Communications

tag list

アクセシビリティ イベント エンタープライズ デザイン ハイブリッド パフォーマンス ブラウザ プログラミング マークアップ モバイル 海外 高速化 Angular2 AngularJS Chrome Cordova CSS de:code ECMAScript Edge Firefox Google Google I/O 2014 HTML5 Conference 2013 html5j IoT JavaScript Microsoft Node.js Polymer Progressive Web Apps React Safari SkyWay TypeScript UI UX W3C W3C仕様 Webアプリ Web Components WebGL WebRTC WebSocket WebVR