Claude ile Otomasyon #5: Ekim Görsellerini WebP’ye Çevirdik, Önce Ölçtük

Ekim yazılarının yedi JPG görselini WebP'ye çevirdik, ama önce ölçtük. Kaynak PNG'ler JPG'lerle neredeyse aynı boyuttaydı, kayıpsız WebP kayıplı JPG'den küçük çıktı, aynı kalitedeki WebP ise JPG'nin %38'i kadardı. Yedekli ve kuru çalıştırmalı geçişi, sosyal medya önizlemelerini ve okurun gerçekte gördüğü kazancı anlatıyoruz.

Serinin dördüncü yazısını bekleyen işlerle bitirmiştik. Listenin ilk maddesi WebP dönüşümüydü: yeni yazıların görselleri 15 Ekim’den beri WebP biçiminde yükleniyordu, ama Ekim’in ilk yedi yazısı hâlâ JPG kullanıyordu. 26 Ekim’de bu işi Claude ile birlikte bitirdik. Dönüştürmeden önce ölçtük ve ölçümler birkaç beklentimizi bozdu. Kaynak PNG dosyaları JPG’lerle neredeyse aynı boyuttaydı. Kayıpsız WebP, kayıplı JPG’den küçük çıktı. Okurun gerçekte gördüğü kazanç ise dosyanın kendisindeki kazançtan epey azdı.

Kapsam: Neden Yalnızca Ekim?

İşe 12 Ekim’de başlamıştık. Önce medya kütüphanesinin tamamını ölçmek istedik: 557 dosya, 154’ü zaten WebP. Her dosyanın boyutunu öğrenmek için sunucuya dosya başına bir istek (HTTP HEAD) gönderdik. Bu ölçüm uzun sürdü, sunucu art arda gelen isteklerle yavaşladı ve işi durdurduk.

Sonra bir karar verdik: eski görsellere dokunmayacaktık. Dönüşüm yalnızca Ekim 2026 görsellerini ve sonraki yazıları kapsayacaktı. Bunu bilerek yaptık, çünkü asıl kazanç başka yerdeydi. Nisan–Eylül arasında yüklenen 33 PNG görselin ortalaması 2 MB, Ekim JPG’lerinin ortalaması ise 130 KB. Ama eski yazılar sosyal medyada ve arama motorlarında çoktan paylaşılmıştı. Yüzlerce dosyayı değiştirmenin riski, bu aşamada kazancından büyük görünüyordu.

Bu kez ölçümü farklı yaptık. WordPress, her medya dosyasının boyutunu ve otomatik ürettiği küçük kopyaların boyutlarını REST API’de zaten saklıyor (media_details). On görselin bütün bilgisini tek bir istekle aldık, sunucuya dosya başına istek atmadık.

Proje bilgisi Yazarlar: Ahmet Aksoy & Claude · Tarih: 26.10.2026 Ortam: Python 3.12.3, Pillow 10.2.0, Ubuntu 24.04 · WordPress 7.1.3 (REST API + uygulama şifresi) Değiştirilen: 7 yazının öne çıkan görseli · Örnek kod: proje 48

İlk Sürpriz: PNG Neredeyse JPG Kadar

Bizim yayın hattımızda öne çıkan görseller Python (Pillow) ile çiziliyor. Önce kayıpsız bir PNG kaydediliyor, siteye bunun JPG kopyası yükleniyor. Yani her JPG’nin elimizde kaynak bir PNG’si vardı. Fotoğraflarda PNG, JPG’nin birkaç katı büyüklükte olur. Bizim görsellerimizde durum farklıydı:

image                               original             JPG        WebP q85        WebP q75  lossless
claude-otomasyon-readme-bakimi.png    125406  137019  34.9dB   53334  35.0dB   40126  34.4dB     92716
claude-otomasyon-yayin-hatti.png      135912  131542  35.6dB   48924  35.6dB   36556  34.9dB    100182
dogru-gorunen-kod-yanlis-sonuc.png    133840  136922  34.5dB   52728  34.6dB   39654  34.0dB     97554
eylul-2026-yapay-zeka.png             160839  118599  36.2dB   48280  36.3dB   36270  35.3dB    109242
python-315-yenilikler.png             143438  134572  35.9dB   50318  35.8dB   37260  35.1dB    102720
python-dataclasses.png                140705  130739  34.6dB   50940  34.6dB   38412  34.1dB    100542
python-dekoratorler.png               149146  121580  35.9dB   45878  35.9dB   33948  35.2dB    105990

total JPG (or original): 910973 bytes, WebP q85: 350402 bytes (38%), lossless: 708946 bytes (78%)

İki görselde PNG, JPG’den bile küçük. Nedeni görsellerin türü: düz renk alanları, keskin kenarlı yazılar, birkaç renk. PNG bu tür görüntüleri çok iyi sıkıştırır. JPG ise fotoğraflar için tasarlanmıştır ve keskin kenarlarda hem kalite hem boyut kaybeder.

Kaliteyi Sayıyla Ölçmek

“WebP aynı kalitede daha küçük” demek kolay, ama “aynı kalite” neye göre? Tablodaki dB sütunları bunun için. Her dosyayı kaynak PNG ile piksel piksel karşılaştırdık ve farkı PSNR (tepe sinyal-gürültü oranı) ile ölçtük. PSNR desibel cinsinden verilir: değer ne kadar yüksekse görüntü kaynağa o kadar yakındır, kayıpsız bir kopyada değer sonsuzdur.

Sonuç açık: Ekim JPG’leri kaynağa ortalama 35.4 dB uzaklıkta. Aynı PNG’den quality=85 ile üretilen WebP de 35.4 dB. Yani aynı kalite, ama dosya boyutunun %38’i. Yedi görsel toplamda 911 KB’tan 350 KB’a iniyor. Yeni yazılarda zaten kullandığımız ayar da quality=85, method=6.

Bir yan bulgu: JPG ve WebP’nin “kalite” ayarları aynı ölçek değil. JPG’de 90 ile WebP’de 85 aynı sonucu vermez. Proje 48’deki demo bunu fotoğraf benzeri bir görüntüyle gösteriyor: orada JPG (kalite 90) 49.5 dB, WebP (kalite 85) 42.8 dB çıkıyor. Bu yüzden iki biçimi “kalite ayarı” ile değil, ölçülen sonuçla karşılaştırmak gerekiyor.

Kayıpsız WebP Ne Zaman Kazandırır?

Tablonun son sütunu ikinci sürprizdi. Kayıpsız WebP, yani kaynakla piksel piksel aynı olan kopya, kayıplı JPG’den ortalama %22 küçük (709 KB’a karşı 911 KB). Bu, aklımıza gelen ilk soruyu da cevapladı: görsellerimizi neden JPG olarak yüklüyorduk?

Ama bu sonucu genellemek yanlış olurdu. Proje 48’in demosunda aynı ölçümü iki yapay görüntüyle yaptık:

image                               original             JPG        WebP q85        WebP q75  lossless
demo: flat graphic                     13059   42850  37.7dB    8556  37.6dB    7242  37.3dB      1822
demo: photo-like                      494541  154146  49.5dB   54706  42.8dB   30080  40.7dB    337336

Düz renkli grafikte kayıpsız WebP 1.8 KB, JPG 42.8 KB. Fotoğraf benzeri görüntüde ise kayıpsız WebP 337 KB ile JPG’nin iki katından büyük. Kayıpsız WebP yalnızca grafiklerde kazandırıyor. Biz siteye kayıplı WebP (q85) yüklemeyi seçtik. Kaynağa en yakın sonucu kayıpsız WebP veriyordu, ama dosya boyutu q85’in iki katıydı. Gözle görülür bir fark yokken bu boyutu taşımanın anlamı yoktu.

Kaynaktan Dönüştürmek

Elimizde PNG kaynaklar olmasaydı yayındaki JPG’leri WebP’ye çevirebilirdik. Bunu da ölçtük:

Kaynak WebP q85 toplam Ortalama PSNR
PNG → WebP 350 KB 35.4 dB
JPG → WebP 359 KB 33.8 dB

JPG’den yapılan dönüşüm hem %2.6 daha büyük hem de 1.6 dB daha kötü. Nedeni şu: kayıplı bir biçimden başka bir kayıplı biçime geçerken iki kayıp üst üste biniyor. Üstelik ikinci sıkıştırıcı, birincinin bıraktığı bozulmaları da korunması gereken ayrıntı sanıp saklamaya çalışıyor. Kaynak dosyalarınızı saklamanın bir nedeni daha.

Geçiş: Önce Yedek, Sonra Kuru Çalıştırma

Değişikliği yapan betik (gecis.py) yayın hattımızdaki wp_yukle.py aracının istek fonksiyonunu kullanıyor. Her yazı için şunları yapıyor:

  1. Yazının şu anki öne çıkan görselini ve o görselin bilgilerini (başlık, alt metin, altyazı, açıklama) okuyor.
  2. Yeni WebP dosyasını medya kütüphanesine yüklüyor ve eski görselin bilgilerini olduğu gibi ona kopyalıyor.
  3. Yazının featured_media alanını yeni görselle değiştiriyor ve yazının durumunun ve yayın tarihinin değişmediğini kontrol ediyor.

Betik varsayılan olarak hiçbir şeyi değiştirmiyor, yalnızca ne yapacağını yazıyor (kuru çalıştırma). Değişiklik ancak --uygula ile yapılıyor ve o zaman da önce bütün yazı ve görsel bilgileri bir yedek dosyasına yazılıyor. İstekler arasında üç saniye bekleniyor: 12 Ekim’deki yavaşlamayı tekrarlamak istemedik.

Eski JPG dosyalarını silmedik. Bu yazılar sosyal medyada JPG önizlemeleriyle paylaşıldı ve platformlar o görselleri kendi sunucularında saklıyor olsa da, eski bağlantıların bir yerde hâlâ JPG adresini gösterme ihtimali var. Medya kütüphanesinde yedi fazla dosya, kırık bir önizlemeden daha ucuz.

Kuru çalıştırma bir şeyi de doğruladı. 19 Ekim yazısının görseli 12 Ekim’de düzeltilip yeniden yüklenmişti ve WordPress yeni dosyaya -1 eki koymuştu (dogru-gorunen-kod-yanlis-sonuc-1.jpg). Betik bu yazıyı doğru kaynak PNG ile eşleştirdi.

Doğrulama: Okur ve Sosyal Medya Ne Görüyor?

Değişiklikten sonra yedi yazının sayfasını tek tek indirdik ve üç şeye baktık: sayfadaki görsel, bağlantı önizlemesi için kullanılan og:image etiketi ve sunucunun görseli hangi içerik türüyle gönderdiği. Yedisinde de üçü WebP’yi gösteriyordu (image/webp).

Bu kontrolde fark ettiğimiz bir şey: sayfalarımızda og:image etiketi iki kez yer alıyor, yani iki ayrı bileşen önizleme etiketi üretiyor. X (Twitter) için kullanılan twitter:image etiketlerinden biri de görsel adresinin sonuna ?w=640 ekliyor. Hepsi yeni görseli gösteriyordu, çünkü hepsi aynı featured_media alanından besleniyor. Görsel adresini etiketlere elle yazan bir düzenleme ise bunlardan birini kolayca unuturdu.

WebP ile ilgili en çok endişe ettiğimiz konu bağlantı önizlemeleriydi: LinkedIn’in WebP önizlemeyi desteklemediği zaman zaman söyleniyor. 26 Ekim yazısının görseli baştan WebP’ydi ve o gün LinkedIn, X ve Facebook’ta paylaşıldı. Üç platformda da önizleme görseli göründü. Bu tek bir gözlem, ama bizim için endişeyi gidermeye yetti.

Bir yan etki: öne çıkan görseli değiştirmek, yazının “son değiştirilme” tarihini de güncelliyor. Bizim temamızda bu tarih okura gösterilmiyor, yalnızca sayfanın article:modified_time etiketinde görünüyor.

Okurun Gördüğü Kazanç: %38 Değil

Yazının başında okurun gördüğü kazancın dosyanın kendisindeki kazançtan az olduğunu söylemiştik. WordPress her yüklenen görselden dört küçük kopya üretiyor ve sayfalar çoğu zaman bu kopyaları kullanıyor. Ana sayfadaki yazı kartları 300 ve 768 piksel genişliğindeki kopyaları gösteriyor. Tam boyutlu görsel yalnızca yazının kendi sayfasında yükleniyor. Yedi görselin bütün kopyalarını karşılaştırdık:

Kopya Genişlik JPG toplam WebP toplam Oran
thumbnail 150 43.7 KB 32.5 KB %74
medium 300 88.1 KB 61.7 KB %70
medium_large 768 358.0 KB 206.8 KB %58
large 1024 533.4 KB 286.6 KB %54
full 1200 911.0 KB 350.4 KB %38

Küçük kopyalarda kazanç azalıyor. 150 piksellik bir küçük resim zaten birkaç kilobayt, iki biçim arasındaki fark da o kadar küçük. Ayrıca bu kopyaları WordPress kendi ayarlarıyla üretiyor, bizim quality=85 ayarımız yalnızca tam boyutlu dosyaya uygulanıyor. Yazı sayfasını masaüstünde açan okur %62 daha az görsel verisi indiriyor (telefonda tarayıcı daha küçük bir kopya seçebiliyor). Ana sayfada gezinen okur için kazanç %30–42 arasında.

Çıkardığımız Dersler

  • Ölçmenin de bir maliyeti var. 557 dosyayı tek tek sorgulamak sunucuyu yavaşlattı. Aynı bilgi REST API’de zaten vardı ve tek bir istekle alınabiliyordu.
  • Kaliteyi ayar değeriyle değil, ölçerek karşılaştırın. JPG 90 ile WebP 85 aynı şey değil. PSNR gibi basit bir ölçü bile iki biçimi adil biçimde karşılaştırmaya yetiyor.
  • Görselin türü sonucu belirliyor. Grafikte kayıpsız WebP JPG’den küçük, fotoğrafta iki katı. Başkasının ölçümünü kendi görsellerinize uygulamadan önce kendi görsellerinizi ölçün.
  • Kaynak dosyaları saklayın. JPG’den dönüştürmek hem daha büyük hem daha kötü sonuç veriyor.
  • Geri dönüş yolunu açık bırakın. Eski görseller silinmedi ve yedek dosyası her yazının eski görsel numarasını tutuyor. Geri dönmek gerekirse yedi yazının featured_media alanını eski değerine çevirmek yetiyor.
  • Sonucu okurun gözünden kontrol edin. Medya kütüphanesindeki %38, ana sayfadaki okur için %30–42 demek.

Sırada Ne Var?

  • Nisan–Eylül görselleri: 2 MB ortalamalı 33 PNG hâlâ duruyor. Bu yazıdaki betik onlara da uygulanabilir. Paylaşılmış önizlemeleri bozmadan nasıl yapılacağına henüz karar vermedik.
  • Kod düzeltmeleri: #3’te bulunan kod hatalarının bir kısmını “Tamamlandı” Diyen Kod ve Regex Neyi Kabul Ediyor? yazılarında ele aldık. Sıralama ve veri yapısı projelerindeki hatalar bekliyor.
  • Bekçinin günlüğü: Kuyruk bekçisi çalışmaya devam ediyor.

Kaynaklar

Ahmet Aksoy & Claude

Not: Bu yazıdaki ölçüm tablolarını üreten aracın kaynak kodunu https://github.com/ahmetax/practical-python-examples deposundaki v312/48_webp_compare klasöründe bulabilirsiniz. python3 main.py <klasör> komutu kendi görsellerinizle aynı tabloyu çıkarır, python3 main.py --demo ise yazıdaki demo tablosunu üretir.

Bir Yanıt Bırak

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir