あいんずのBLOG
スマホ写真をWebPに変換するときの注意点(EXIF回転とPIL vs ffmpeg)
2026-06-06
ブログに載せるスマホ写真をまとめてWebPに変換した際の知見をメモしておきます。特に「EXIF回転情報の扱い」でハマりやすいポイントがあったので、その対処と、変換ツール(Pillow / ffmpeg / cwebp)の画質差についてまとめます。
なぜWebPに変換するのか
スマホで撮ったJPEG写真は1枚あたり数MBになることも珍しくありません。WebPに変換すると、見た目の劣化をほとんど感じさせずにファイルサイズを大きく削減できます。今回は50枚の写真を quality=85 でWebP化し、合計サイズを大幅に圧縮できました。
ページの表示速度はそのまま体験の質に直結するので、画像の多い記事ほどWebP化の効果は大きくなります。
一番ハマるポイント:EXIF回転情報
スマホの写真には EXIF orientation(回転情報) というメタデータが埋め込まれています。これは「センサーが取り込んだ生のピクセルデータ」と「実際に表示すべき向き」がずれているときに、その差を吸収するための情報です。
たとえば、ある写真は次のような状態でした。
| 項目 | 値 |
|---|---|
| 生のピクセル寸法 | 2256 × 4000(縦長) |
| EXIF orientation | 8(反時計回りに90°回転して表示) |
| 実際に表示される向き | 4000 × 2256(横長) |
つまり「ファイルの中身は縦長だが、表示は横長」という写真が混ざっているわけです。ブラウザはEXIF情報を読んで自動的に回転して表示してくれるので、普段は意識しません。
ところが、単純にピクセルデータだけをWebPに変換してEXIFを捨てると、回転情報が失われて写真が横倒しになってしまうのです。これがWebP変換で最もハマりやすい落とし穴です。
解決策:回転をピクセルに「焼き込む」
対処は明確で、変換前にEXIF回転を実際のピクセルに適用(回転を焼き込み)してしまえば、その後はEXIF情報が無くても正しい向きで表示されます。Pillowなら ImageOps.exif_transpose() 一発で、画像ごとの向きを自動で判定して適用してくれます。
from PIL import Image, ImageOps
import glob, os
for f in glob.glob('*.jpg'):
im = Image.open(f)
im = ImageOps.exif_transpose(im) # EXIF回転をピクセルに焼き込み、フラグを除去
out = os.path.splitext(f)[0] + '.webp'
im.save(out, 'webp', quality=85, method=6)
os.remove(f)
ポイントは以下の通りです。
exif_transpose()… 画像ごとのEXIF orientationを読んで自動で正しい向きに回転。向きがバラバラなスマホ写真の一括変換でも、1枚ずつ条件分岐する必要がありません。quality=85… 写真用途で標準的な品質。視覚的にはほぼ無劣化で十分に軽量化できます。method=6… libwebpの圧縮努力度の最大値。遅くなりますが圧縮率が最良になります。
Pillow vs ffmpeg vs cwebp の画質差
「ffmpegで変換した方が画質が良いのでは?」と思うかもしれませんが、結論から言うと 同じ設定なら画質はほぼ同等 です。
理由はシンプルで、Pillow も ffmpeg も cwebp も、WebPエンコードには内部で同じ libwebp(Google公式ライブラリ)を使っている からです。エンコーダが同じなので、同じ品質設定なら出力に本質的な差は生まれません。
| 観点 | Pillow | ffmpeg | cwebp(公式CLI) |
|---|---|---|---|
| エンコーダ | libwebp | libwebp | libwebp |
| 同設定での画質 | 同等 | 同等 | 同等 |
| EXIF回転 | exif_transpose で画像ごとに自動 | 自動補正なし(向きごとに手動でtranspose) | 同左、要手動 |
| 細かい調整 | quality / method / lossless | quality / compression_level | 最も豊富(-sharp_yuv 等) |
実務上のポイントは次の2つです。
- 向きがバラバラなスマホ写真の一括変換では Pillow が有利。 ffmpegやcwebpはEXIF回転を自動補正しないため、画像ごとに向きを読んで回転フィルタを切り替える必要があり、手間が増えます。
- 画質を極めるなら cwebp の
-sharp_yuv。 色境界のにじみがわずかに改善しますが、ブログ用途では体感差はほぼありません。
# cwebpで画質重視に変換する場合の例
cwebp -q 85 -m 6 -sharp_yuv input.jpg -o output.webp
なお、元がJPEG(すでに非可逆圧縮済み)の場合は、どのツールを使っても「JPEGの劣化を引き継ぐ」点は共通です。元画像以上の画質にはならないので、quality=85 程度で十分というのが実感です。
まとめ
- スマホ写真のWebP変換では EXIF回転情報の扱いが最重要。回転をピクセルに焼き込んでから変換する。
- Pillowの
ImageOps.exif_transpose()を使えば、向きがバラバラな写真でも自動で正しく処理できる。 - WebPの画質はエンコーダ(libwebp)依存なので、Pillow / ffmpeg / cwebp で同設定なら画質はほぼ同等。一括変換の手軽さではPillowが扱いやすい。