ApacheでJPEGやPNGをWebPに変換する

WebPが普及して久しいですが、スマホで撮る写真はJPEG(iPhoneに関してはHEICとかいうフォーマット)だったり Windowsやmacに付属の画像編集ソフトではWebPに変換できなかったりと何かと対応は面倒です。
そこでサーバ側で自動変換を、更にいうとアプリケーションではなくHTTPサーバ(今回はApache)で変換をやりたいというのが趣旨になります。

やりたいことをまとめると以下の通りです。

  • .jpg.png にアクセスされたら .jpg.webp.png.webp にそれぞれリダイレクトする。
  • .jpg.webp.png.webp にアクセスされたら元の画像をWebPに変換してレスポンスを返す。

今回用意するもの

mod_ext_filter

Apacheモジュールの mod_ext_filter を使用することで クライアントに返そうとしているレスポンスボディに対しフィルタをかけることができます。
今回の場合でいうと、レスポンスとして返そうとしているJPEGファイルやPNGファイルのバイナリを入力としてWebPに変換するプログラムを実行し、 その出力をレスポンスとして返すようなことができます。
Apacheに同梱されているはずなので LoadMoodule すればすぐに使えるかと思います。

cwebp

cwebp はWebPの開発元であるGoogleが公開している画像変換ツールです。
たいていのLinuxディストリビューションでパッケージとして提供されていますが、バージョンが古いとうまく変換できなかったりするので なるべく公式サイトから最新版をダウンロードしてきたほうが良いかと思います。

設定ファイルの例

# モジュールの読み込み
LoadModule ext_filter_module modules/mod_ext_filter.so
LoadModule rewrite_module modules/mod_rewrite.so

# MIMEを追加
AddType image/webp .webp
AddType image/webp .jpg
AddType image/webp .png

# .jpg 、 .png をそれぞれ .jpg.webp 、 .png.webp にリダイレクトする
RedirectMatch permanent ^(.*)\.jpg$ $1.jpg.webp
RedirectMatch permanent ^(.*)\.png $1.png.webp

RewriteEngine On

# .jpg.webp 、 .png.webp へのアクセスはそれぞれもとのファイルの内容を返す
RewriteRule ^(.*)\.jpg\.webp$ $1.jpg [L]
RewriteRule ^(.*)\.png\.webp$ $1.png [L]

# フィルタ定義
# `-o -` で標準出力への出力を指定し、 `-- -` で標準入力からの入力を指定している
ExtFilterDefine png_to_webp mode=output intype=image/webp cmd="/usr/local/libwebp/bin/cwebp -o - -- -"
ExtFilterDefine jpg_to_webp mode=output intype=image/webp cmd="/usr/local/libwebp/bin/cwebp -o - -- -"

# フィルタを適用する
<LocationMatch ^(.*)\.jpg\.webp$>
    SetOutputFilter jpg_to_webp
</LocationMatch>

<LocationMatch ^(.*)\.png\.webp$>
    SetOutputFilter png_to_webp
</LocationMatch>