WebPとは
Googleが開発している画像フォーマットで、ウェッピーと読みます。
JPEGと比較してファイルサイズが25-34%小さくなり、採用することで表示の高速化が見込めます。
WebPに対応するプラットフォームは徐々に増加しています。
参考リンク
WebサイトのWebP対応方法
まだWebPに対応できていないプラットフォームが存在するため、JPEG(またはPNG)とWebPと両フォーマットの画像を用意する必要があります。
画像の使い分け方としては、HTMLタグで出し分ける方法と、HTTP RequestのAcceptヘッダの値に応じてサーバのレスポンスを変える方法があります。
HTMLで出し分ける例
<picture>
<source type="image/webp" src="A.webp">
<img src="A.jpg">
</picture>
サーバで出し分ける例
[実践]WebP画像を用意する方法
今回WebPの対応をする画像は、Amazon S3で管理しております。
画像はブラウザからサーバサイドアプリ経由でS3にアップロードされる仕組みになっています。
既存の仕組みを変更せずWebP画像を用意したかったため、S3に画像がアップロードされるとAWS Lambdaで自動的に変換する仕組みを作ることにしました。
Lambda functionの実装
functionの作成
Management ConsoleでLambda functionを作成します。
Pythonで実装したかったので、RuntimeはPythonを選択しました。
IAM Roleの設定
JPEGの画像がアップロードされるバケットの読み込み、WebPの画像をアップロードするバケットへの書き込みとそのオブジェクトのパーミッション変更ができる権限を設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::bucketName/path-to-image/*"
}
]
}
Codeの作成
S3のイベント情報から元画像をダウンロードし、変換したものをS3にアップロードする、という処理を記述します。
from PIL import Image
import urllib.parse
import boto3
import os
s3 = boto3.client('s3')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
source_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
destination_key = source_key + u'.webp'
source_file = u'/tmp/' + os.path.basename(source_key)
destination_file = source_file + u'.webp'
try:
s3.download_file(Bucket=bucket, Key=source_key, Filename=source_file)
img = Image.open(source_file, 'r')
img.save(destination_file, 'webp', quality = 80)
s3.upload_file(Filename=destination_file,
Bucket=bucket,
Key=destination_key,
ExtraArgs={"ACL":"public-read","ContentType":"image/webp"})
return source_key
except Exception as e:
print(e)
raise e
ライブラリのインストールとZip化
必要なライブラリ(webp)をインストールするため、lambda_function.py を作成したディレクトリで下記のコマンドを実行します。
pip install webp -t ./
ライブラリインストール後、作業中ディレクトリの内容は下記のようになります。
$ ls -1
PIL/
Pillow-6.0.0.dist-info/
_cffi_backend.cpython-36m-x86_64-linux-gnu.so*
_webp.abi3.so*
bin/
cffi/
cffi-1.12.3.dist-info/
lambda_function.py
numpy/
numpy-1.16.3.dist-info/
pycparser/
pycparser-2.19.dist-info/
webp/
webp-0.1.0a13.dist-info/
webp_build/
下記のコマンドを実行し、zipファイルを作成します。
zip -r convertJpegToWebp.zip ./*
functionへの登録
Function codeパネルにてCode entry typeをUpload a .zip file
とし、Function packageのUploadボタンを押してzipファイルをアップロードします。
S3にEvent Notificationを登録
変換元となる画像がアップロードされるS3バケットに、Lambdaを起動するEvent Notificationを登録します。
画像の登録をトリガーとしたいため、EventsにはAll object create eventsを選択し、対象とする画像のPrefix, SuffixをFilterに設定、TypeはLambdaを選択して作成したLambda functionを設定します。
以上で実装完了です。
元画像をアップロードした数秒後に、WebPの画像が作成されていることが確認できます。
まとめ
WebP対応するにあたり、未対応環境も考慮すると、WebPとJPEG/PNGの両方を用意しておくことは必須です。手作業で画像を用意しようとしたら大変ですが、自動化する仕組みを作ってしまえば手間無く用意できます。
ファイルサイズが2〜3割程度小さくなるので、画像の多いWebサイトであれば導入のメリットは大きいと思います。