🎚️ Volume Normalization - Ses Dengeleme Sistemi

📅 Tarih: 2025-11-26 🎯 Tenant: muzibu.com (1001) 👤 Talep: ReplayGain standardı ile şarkılar arası ses farkını ortadan kaldırma ❌ YAPILACAK

🎯 Genel Bakış

Problem: Müzik platformunda şarkılar arasında ses seviyesi farkı kullanıcı deneyimini olumsuz etkiliyor. Bir şarkı çok yüksek sesle gelirken, diğeri çok düşük sesle gelebiliyor.

Çözüm: ReplayGain (Şarkıların algılanan ses seviyesini ölçüp dengelemek için endüstri standardı) kullanarak tüm şarkıları aynı ses seviyesine normalize edeceğiz.

Hedef: Spotify standardı olan -14 LUFS (Loudness Units relative to Full Scale - insan kulağının algıladığı ses seviyesi ölçüsü) seviyesine tüm şarkıları getirmek.

📊 Teknik Hedefler

  • Target: -14 LUFS (Spotify, Apple Music, YouTube standardı)
  • Maksimum Artırma: +6 dB (ses bozulmasını önlemek için)
  • Analiz: Şarkı sisteme yüklenirken arka planda
  • Uygulama: Player'da gerçek zamanlı, kullanıcı ses kontrolünü etkilemeden

🔍 Teknik Yaklaşım Seçimi

Volume normalization için 3 farklı teknik yaklaşım var. Her birinin artıları ve eksileri mevcut:

Yaklaşım Avantajları Dezavantajları Durum
FFmpeg + ebur128
(Açık kaynak ses işleme aracı + Avrupa yayın standardı ses ölçüm filtresi)
✅ Ücretsiz ve açık kaynak
✅ Spotify standardına tam uyumlu
✅ Hassas LUFS ölçümü
✅ Server'da zaten kurulu
❌ Her şarkı 30-60 saniye işlem süresi
❌ Server CPU yükü yüksek
❌ 26K şarkı için ~12-24 saat batch işlem gerekli
ÖNERİLEN
Essentia
(Müzik analizi için özel geliştirilmiş kütüphane)
✅ Müzik analizi için optimize
✅ Hızlı işlem
✅ Ek özellikler (BPM, key detection)
❌ Server'a ayrıca kurulum gerekli
❌ Python bağımlılığı
❌ Öğrenme eğrisi var
ALTERNATIF
Cyanite.ai API
(Bulut tabanlı müzik analiz servisi)
✅ Anlık sonuç
✅ Server yükü yok
✅ Profesyonel analiz
✅ Ek özellikler (mood, genre)
❌ Ücretli ($0.01/şarkı = 26K şarkı için ~$260)
❌ API bağımlılığı
❌ İnternet bağlantısı gerekli
ÜCRETLI

💡 Önerilen Seçim: FFmpeg + ebur128

Maliyet yoktur, Spotify standardına tam uyumludur ve server'da zaten kuruludur. Batch işlem ile 26K şarkıyı arka planda analiz edebiliriz (kullanıcı deneyimini etkilemez).

Strateji: Yeni yüklenen şarkılar anında, mevcut 26K şarkı background job ile gece saatlerinde işlenebilir.

📋 Yapılacaklar - Adım Adım Plan

1 Database Schema Genişletme Yüksek Öncelik

Ne Yapılacak: Songs tablosuna loudness bilgilerini saklamak için yeni alanlar eklenecek.

Yaklaşım:

  • loudness_db: Ölçülen LUFS değeri (-30.00 ile +10.00 arası)
  • loudness_gain: Hesaplanan gain değeri (target - actual)
  • Migration hem central hem tenant database'lerde çalışacak
  • Nullable olacak (mevcut şarkılar NULL, zamanla doldurulacak)

✨ Beklenen Sonuç

Her şarkı kaydında loudness bilgileri saklanabilecek, gerektiğinde yeniden hesaplanmadan direkt kullanılabilecek.

2 Song Model Güncelleme Yüksek Öncelik

Ne Yapılacak: Song model'inde loudness hesaplama metodları eklenecek.

Yaklaşım:

  • fillable dizisine yeni alanlar eklenecek
  • calculateNormalizationGain() metodu: Target LUFS ile mevcut değer arasındaki farkı hesaplayacak
  • Maksimum +6 dB gain limiti kontrolü içerecek
  • accessor ile player'da kolay erişim sağlanacak

✨ Beklenen Sonuç

Model üzerinden $song->loudness_gain ile direkt gain değerine erişilebilecek, player entegrasyonu kolay olacak.

3 Background Job - Loudness Analizi Yüksek Öncelik

Ne Yapılacak: FFmpeg ile LUFS ölçümü yapan background job oluşturulacak.

Yaklaşım:

  • Job, şarkı yüklendiğinde otomatik tetiklenecek (SongController'dan)
  • FFmpeg'in ebur128 filtresi ile integrated loudness ölçülecek
  • Çıktıdan LUFS değeri ayıklanacak (regex ile)
  • Target (-14 LUFS) ile fark hesaplanıp gain değeri bulunacak
  • Song kaydı güncellenecek
  • Hata durumunda retry mekanizması olacak (3 deneme)

⚠️ Kritik Nokta

FFmpeg işlemi CPU yoğun! Queue sistemi kullanılmalı ki şarkı yükleme işlemi yavaşlamasın. Job arka planda işlenirken kullanıcı diğer işlemlerine devam edebilmeli.

✨ Beklenen Sonuç

Şarkı yüklendiğinde kullanıcı beklemeden işlem tamamlanır, arka planda loudness analizi yapılır ve 30-60 saniye içinde tamamlanır.

4 Controller Entegrasyonu Orta Öncelik

Ne Yapılacak: Şarkı yükleme endpoint'inde job tetikleme mantığı eklenecek.

Yaklaşım:

  • SongController::store() metodunda şarkı kaydedildikten sonra
  • ProcessLoudnessAnalysisJob::dispatch($song) ile job kuyruğa atılacak
  • Response hemen dönecek (kullanıcı beklemeyecek)
  • Loudness bilgisi NULL olarak başlayacak, job tamamlanınca dolacak

✨ Beklenen Sonuç

Şarkı yükleme API'sı performansı korunacak, loudness analizi asenkron olarak yapılacak.

5 Player Entegrasyonu - Howler.js Yüksek Öncelik

Ne Yapılacak: Player'da ses seviyesi kontrol mantığı güncellenecek.

Yaklaşım:

  • Mevcut kod şu an sabit bir volume azaltması yapıyor (userVolume * 0.9)
  • Yeni mantık: loudness_gain değerini dB'den linear'e (ses güçlendirme biriminden doğrusal ölçeğe) çevirip uygulayacak
  • Formül: 10^(gain/20) ile dB değeri linear volume'a dönüştürülür
  • Kullanıcının volume kontrolü etkilenmeyecek (onun üzerine gain uygulanacak)
  • Loudness bilgisi yoksa (NULL) varsayılan 1.0 kullanılacak

⚠️ Kritik Nokta

dB'den linear dönüşüm önemli! Yanlış formül kullanılırsa ses ya çok sessiz ya da çok gürültülü olur. 10^(gain/20) formülü matematiksel standart.

✨ Beklenen Sonuç

Şarkılar arası geçişlerde ses seviyesi sabit kalacak, kullanıcı volume slider'ını sürekli ayarlamak zorunda kalmayacak.

6 Konsol Komutu - Toplu Analiz Orta Öncelik

Ne Yapılacak: Mevcut 26K şarkıyı toplu olarak analiz edecek Artisan komutu.

Yaklaşım:

  • Komut: php artisan muzibu:analyze-loudness
  • Batch işlem: Her seferinde 100 şarkı (--batch=100 parametresi)
  • Sadece loudness_db NULL olan şarkıları işleyecek
  • Progress bar ile ilerleme gösterilecek
  • Gece saatlerinde cron ile otomatik çalıştırılabilir
  • Hata durumunda log'lanacak ama devam edecek

💡 Strateji

26K şarkı için tahmini 12-24 saat. Gece 02:00-06:00 arası cron ile çalıştırılabilir (düşük trafik saatleri). Kullanıcı deneyimi etkilenmez.

✨ Beklenen Sonuç

Tüm mevcut şarkılar zamanla normalize edilecek, yeni yüklenenler otomatik olarak. Sistem tamamen otomatik hale gelecek.

⚠️ Kritik Noktalar & Dikkat Edilecekler

1. Migration Konusu

Mümkün olduğunca yeni migration oluşturmaktan kaçınacağız. Fakat loudness bilgileri için migration zorunlu. Songs tablosuna iki kolon eklememiz gerekiyor.

Çözüm: Hem central hem tenant migration'ları oluşturup test ortamında önce deneyeceğiz.

2. Queue Sistemi Kontrolü

Background job çalışması için Horizon/Queue worker'ın aktif olması gerekli. Eğer queue çalışmıyorsa loudness analizi hiç yapılmaz!

Çözüm: php artisan horizon:status komutu ile kontrol edilecek, eğer çalışmıyorsa uyarı verilecek.

3. Clipping Önleme

Maksimum +6 dB gain limiti çok önemli! Daha fazla artırırsak clipping (ses bozulması/çatırtı) oluşur.

Çözüm: Model'de calculateNormalizationGain() içinde min($gain, 6) kontrolü ile sınırlandırılacak.

4. Geriye Dönük Uyumluluk

Loudness_db NULL olan şarkılarda player bozulmamalı! Yeni şarkılar analiz edilene kadar eski mantıkla çalışmalı.

Çözüm: Player'da fallback: loudness_gain ?? 1.0 kullanacağız.

5. FFmpeg Kurulum Kontrolü

Server'da FFmpeg'in ebur128 desteği olmalı. Bazı minimal FFmpeg kurulumlarında bu filter olmayabilir.

Çözüm: İlk adımda ffmpeg -filters | grep ebur128 komutu ile kontrol edeceğiz.

🎵 Beklenen Sonuçlar

🎯 Kullanıcı Deneyimi

  • Şarkılar arası geçişlerde ses seviyesi tutarlı olacak
  • Kullanıcı her şarkıda volume slider'ını ayarlamak zorunda kalmayacak
  • Profesyonel müzik platformlarıyla (Spotify, Apple Music) aynı deneyim
  • Kulaklarda ani ses artışları olmayacak (sağlık açısından önemli)

⚙️ Sistem Tarafı

  • Yeni şarkılar otomatik olarak analiz edilecek
  • 26K mevcut şarkı background'da işlenecek
  • Performans etkilenmeyecek (asenkron işlem)
  • Loudness bilgileri cache'lenmiş olacak (her seferinde hesaplamaya gerek yok)

📊 Teknik Metrikler

  • Hedef: 26K şarkının %100'ü -14 LUFS standardına uyumlu
  • İşlem süresi: Şarkı başına 30-60 saniye (arka planda)
  • Toplam süre: ~12-24 saat (batch işlem ile)
  • Maliyet: $0 (FFmpeg açık kaynak)