v1.0 8.514 Satır JS 6 Backend Dosya

Muzibu Player Derinlemesine Analiz Raporu

HLS Sistemi, Adaptive Bitrate, Soft Mode, Crossfade ve Tam Mimari Analiz

22 Şubat 2026 main branch 26 Sorun Tespit Edildi

Basit Anlatım (Herkes İçin)

Player Nedir?

Muzibu'nun müzik çalar sistemi. Spotify veya Apple Music'teki çalar gibi düşünün. Şarkı seçersiniz, çalar, sonraki şarkıya geçer, ses ayarlarsınız.

HLS Nedir?

HLS (HTTP Live Streaming) = Şarkıyı küçük parçalara bölüp gönderme yöntemi. Netflix videoları nasıl parça parça yükleniyorsa, şarkılar da öyle. Bant genişliğiniz düşerse kalite otomatik düşer, yükselirse kalite artar. Neden önemli? Hem korsan indirmeyi zorlaştırır, hem de internet hızına göre en iyi deneyimi sunar.

Adaptive Bitrate Nedir?

İnterneti hızlı olan kişiye yüksek kaliteli ses, yavaş olan kişiye düşük kaliteli ses gönderme. Otomatik. 4 seviye var: Ultra düşük (32k), Düşük (64k), Orta (128k), Yüksek (~250k). Neden önemli? Mobil verideyken az veri harcar, WiFi'deyken en iyi kaliteyi verir.

Soft Mode Nedir?

Bazı kullanıcılara (kurumsal, çok kullanıcılı hesaplar) düşük kaliteli ses sunma modu. Sunucu yükünü ve bant genişliği maliyetini azaltır. Neden önemli? 50+ kullanıcılı kurumsal hesaplarda sunucu maliyetini %60-70 düşürebilir.

Bulunan Sorunlar

Toplamda 26 sorun tespit edildi. Bunlardan 5'i kritik (acil düzeltilmeli), 9'u orta seviye, 12'si düşük seviye iyileştirme. Kritik sorunlar: şifreleme dosya adı çakışması, segment süresi tutarsızlığı ve kalite filtresi hatası.

Genel Mimari

Player Dosya Yapısı

public/themes/muzibu/js/player/
├── core/
│   ├── player-core.js        # Ana Alpine.js bileşeni (8.514 satır)
│   └── safe-storage.js        # localStorage güvenli wrapper
├── features/
│   ├── api.js                 # Kimlikli fetch helper (401 handling)
│   ├── auth.js                # Giriş/kayıt sistemi
│   ├── buffer-monitor.js      # Buffer sağlık takibi
│   ├── device-profiler.js     # Cihaz profilleme (RAM, CPU)
│   ├── favorites.js           # Favori şarkı/playlist
│   ├── old-device-checker.js  # Eski cihaz tespiti
│   ├── performance-debug.js   # Performans izleme
│   ├── play-helpers.js        # Çalma yardımcıları
│   ├── session.js             # Oturum yönetimi
│   ├── spa-router.js          # SPA sayfa geçişleri
│   ├── speed-tester.js        # Ağ hız testi
│   └── spot-player.js         # Kurumsal reklam oynatıcı
└── lib/
    └── hls.min.js             # HLS.js v1.4.12

Şarkı Çalma Akışı

Kullanıcı Tıklar
togglePlayPause()
API İsteği
/songs/{id}/stream
Format Çözümleme
resolveAudioFormat()
URL Şifre Çöz
XOR + Base64 decrypt
HLS / MP3?
stream_type kontrolü
Çalmaya Başla
HLS.js / Howler.js

Alpine.js State Yapısı (Temel Alanlar)

Kimlik & Oturum

isLoggedIn — Giriş durumu
currentUser — Kullanıcı bilgileri
showAuthModal — Giriş modali

Çalma Durumu

isPlaying — Çalıyor mu
currentTime / duration — Zaman
volume / isMuted — Ses
progressPercent — İlerleme

HLS Durumu

isHlsStream — HLS aktif mi
hlsCurrentLevel — Kalite (0-3)
isSlowConnection — Yavaş bağlantı
currentStreamType — "hls" / "mp3"

HLS Sistemi

Frontend — HLS.js Entegrasyonu

HLS.js Konfigürasyonu (Satır 462-546)
HLS_SHARED_CONFIG = {
  enableWorker: true,              // Web Worker ile ayrı thread
  lowLatencyMode: false,           // VOD, canlı değil
  autoStartLoad: false,            // Manuel başlatma (ABR lock için KRİTİK)
  startLevel: 3,                   // Yüksek kaliteden başla
  abrEwmaDefaultEstimate: 250000,  // 250kbps başlangıç tahmini
  abrBandWidthUpFactor: 0.5,       // Muhafazakar yükseltme (0.7→0.5)
  abrBandWidthFactor: 0.8,         // Muhafazakar düşürme (0.95→0.8)
  maxBufferLength: 12,             // 12sn buffer (GC dostu)

  keyLoadPolicy: {
    default: {
      maxTimeToFirstByteMs: 10000,   // Key yükleme timeout: 10sn
      maxLoadTimeMs: 20000,          // Key toplam timeout: 20sn
      timeoutRetry: { maxNumRetry: 3, retryDelayMs: 1000 }
    }
  }
}
Key Pre-Cache Sistemi (Satır 352-454) — Race Condition Çözümü

Problem: HLS.js v1.4.12'de key-loader race condition — aynı key URI için birden fazla fragment yüklenmesi keyUriToKeyInfo map'ini eziyor.

Çözüm: 3 katmanlı key önbellekleme sistemi:

1. Key Normalize
URL parametrelerini alfabetik sırala, cache buster kaldır → tutarlı cache key
2. Pre-fetch
Çalmadan ÖNCE key'i fetch() ile indir → _hlsKeyCache[]'e kaydet
3. Custom Loader
CachingKeyLoader — HLS.js XHR'ı intercept et, cache'ten senkron döndür
HLS Instance Pool (Satır 548-678)

Pool Yönetimi

  • • 2 adet HLS.js instance havuzu
  • acquire() — Havuzdan al
  • release() — Havuza geri ver
  • • Stale instance temizleme
  • • Overflow: yeni instance → hard limit

Cleanup Sırası

  1. 1. hls.stopLoad()
  2. 2. hls.detachMedia()
  3. 3. hls.removeAllListeners()
  4. 4. hls.destroy()
  5. 5. audio.load() — MediaSource flush
  6. 6. DOM'dan kaldır (pool hariç)
MP3 Fallback Mekanizması (Satır 6113-6147)

Tetikleyiciler: HLS init hatası, Fatal error, bufferAppendError, 60sn timeout

triggerMp3Fallback(reason):
  1. HLS taint + release (pool'a geri ver)
  2. Blob URL cleanup
  3. safeAudioCleanup() — Event handler temizleme
  4. fallback_url varsa → playWithHowler()
  5. Toast: "HLS başarısız, MP3 ile çalınıyor..."

Backend — HLS Dönüştürme & Sunma

ConvertToHLSJob — Dönüştürme İşlemi

FFmpeg Pipeline

ffmpeg -i input.mp3 \
  -c:a aac -b:a {bitrate}k \
  -af "loudnorm + stereotools + eq + lowpass" \
  -hls_key_info_file enc.keyinfo \
  -hls_time 6 -hls_list_size 0 \
  -hls_segment_filename "segment-%03d.ts" \
  playlist.m3u8

Kalite Seviyeleri

SeviyeBitrateKanalSample RateSegment
ultralow32 kbpsMono22.05 kHz4 sn
low64 kbpsMono22.05 kHz4 sn
mid128 kbpsStereo44.1 kHz4 sn
high~180-280 kbpsStereo44.1 kHz6 sn
AES-128 Şifreleme Akışı
Key Oluştur
random_bytes(16)
IV Oluştur
bin2hex(random_bytes(16))
Keyinfo Dosyası
URI + key path + IV
FFmpeg Şifrele
-hls_key_info_file
Key Endpoint: GET /hls-key/muzibu/songs/{id}?token=...&sig=...&expires=...
Key Dosyası: storage/tenant{id}/app/public/muzibu/hls/{songId}/enc.bin
İmza: HMAC-SHA256 ile doğrulanır, süresi dolmuşsa 401 döner
API Endpoint'leri
EndpointYetkiAçıklama
/api/muzibu/songs/{id}/streamAuthŞifreli HLS/MP3 URL döndürür
/hls/muzibu/songs/{id}/master.m3u8SignedMaster playlist (variant listesi)
/hls/muzibu/songs/{id}/segment-*.tsPublicAES-128 şifreli segment (auth yok)
/hls-key/muzibu/songs/{id}Signed+Rate16-byte AES-128 key (60req/dk)
/audio/songs/{id}/{exp}/{sig}SignedCDN MP3 URL (path-based)
/songs/{id}/track-startSanctumDinleme başlangıcı (play_id döner)
/songs/{id}/track-hitSanctum30sn milestone (play_count++)
/songs/{id}/track-endSanctumBitiriş/atlama (sendBeacon)

Adaptive Bitrate (ABR) Sistemi

ABR Stratejisi

Başlangıç Seviyesi
startLevel: 3 — Yüksek kaliteden başlar, gerekirse düşürür
Bant Genişliği Tahmini
abrEwmaDefaultEstimate: 250kbps — EWMA algoritması ile ölçüm
Yükseltme Eşiği
abrBandWidthUpFactor: 0.5 — 2x bant genişliği gerekli (muhafazakar)
Düşürme Eşiği
abrBandWidthFactor: 0.8 — %80 altına düşerse kalite indirilir

Startup Lock Mekanizması

  1. 1 loadSource() öncesi → _abrStartupLocked = true
  2. 2 MANIFEST_PARSEDcurrentLevel = startLevel (sabit)
  3. 3 FRAG_BUFFEREDunlockABR()currentLevel = -1 (oto)
  4. 4 5sn fallback timeout (FRAG_BUFFERED geç gelirse)
Neden? İlk segment'te ABR yanlış düşük seviye seçmesin diye. Yüksek kaliteden başlar, ilk parça yüklendikten sonra ABR devralır.

Cihaza Göre Adaptasyon

Düşük RAM / CPU: startLevel=0, buffer=10MB
saveData modu: Kalite otomatik düşürülür
slow-2g bağlantı: Ultra düşük kaliteye sabitlenir

Soft Mode & Format Sistemi

Format Çözümleme Zinciri (D4)

1
Admin Tercihi
user.audio_preference — Admin panelden atanan
↓ auto ise
2
Kurumsal Eşik
50+ kullanıcılı hesaplar → MP3 zorlanır
↓ eşik altındaysa
3
Sistem Varsayılanı
MUZIBU_DEFAULT_AUDIO_FORMAT=auto

Soft Player Modu (D8)

Ne yapar? Master playlist'ten yüksek kalite variant'ları çıkarır.

// SongStreamController::serveHls()
if (soft=1) {
  allowed = ['ultralow', 'low']  // config'den
  // high ve mid kaldırılır
  master.m3u8 → sadece ultralow + low
}
Sorun: Regex filtresi hatalı çalışıyor (Bkz: Sorun #7)

URL Şifreleme (Frontend)

Backend şifreli URL döndürür: response._ + response.__

Frontend XOR ile çözer → stream_url, fallback_url, stream_type

Crossfade Sistemi (E Grubu)

DURUM: DEVRE DIŞI

Kod hazır ancak kapalı. HLS keyLoadError sorunu çözüldü, artık açılabilir.

Implementasyon (Satır 2465-2650)

  1. 1. Durum kontrol — pause/stop yapıldıysa başlatma
  2. 2. Cache check — Sonraki şarkı URL'de varsa instant crossfade
  3. 3. Stream fetch — Sonraki şarkı bilgisi al
  4. 4. Format belirle — HLS mi MP3 mi?
  5. 5. Paralel çalma — currentAudio fade-out, nextAudio fade-in

Dual Audio Yönetimi

hlsAudio — Aktif çalan element
hlsAudioNext — Preload / crossfade element
Crossfade ABR: 3sn timeout (main 5sn)
Risk: Dual audio aynı anda buffer → bant genişliği yarılanır

Queue & Playlist Yönetimi

nextTrack() Akışı

  1. 1. _nextTrackInProgress eşzamanlılık kilidi
  2. 2. 10sn timeout (kilit takılırsa otomatik serbest)
  3. 3. 300ms minimum interval (çift tetikleme önleme)
  4. 4. fromNaturalEnd: true → gapless geçiş
  5. 5. _safePlayFromQueue(): max 3 deneme + token yenileme
  6. 6. Queue bittiyse → _refillQueue()

Queue Yenileme Zinciri

Adım 1 Tür ile doldur (_fetchUniqueGenreSongs)
Adım 2 Popüler şarkılar (/songs/popular)
Adım 3 Karıştır (Fisher-Yates) + baştan çal
Adım 4 Acil durum: tür 1 ile doldur
Tekrarlama filtresi: Song ID'leri takip edilir, aynı şarkı atlanır

Güvenlik & Şifreleme

İmza Doğrulama

Algoritma: HMAC-SHA256
Base: "{path}|{user_id}|{expires}"
Key: config('app.key')
Doğrulama: sig === expected_sig && now < expires

Playlist ve key endpoint'lerinde zorunlu. Segment'ler AES-128 şifreli olduğu için imzasız sunulur (CDN uyumlu).

Güvenlik Katmanları

AES-128 segment şifreleme
HMAC-SHA256 URL imzalama
XOR + Base64 URL gizleme (frontend)
File traversal koruması (regex whitelist)
Rate limiting: 60req/dk (sadece key endpoint)
Token = user_id (tahmin edilebilir) — Bkz: Sorun #22

Performans Optimizasyonları

OptimizasyonKonumEtki
G1 Lazy HLS.js yüklemeSatır 14-36JS bundle küçülür, sayfa hızlanır
Progress 250ms intervalSatır 6235Ana thread yükü %60 azalır
HLS Instance havuzuSatır 548-678Instance oluşturma/yok etme maliyeti sıfır
Key pre-cacheSatır 352-454Key yükleme gecikmesi sıfır
DOM cache (hlsAudio lookup)Satır 1044-1060DOM sorguları ~0
Stream LRU cacheSatır 7289-7299Tekrar çalma: ağ isteği yok
Segment'ler session'sızRoute middlewareParalel 30+ istek → session kilidi yok
M3U8 disk cache (3600sn)ControllerDosya okuma maliyeti azalır
CDN uyumlu path-based URLSignedUrlServiceCloudflare cache kullanılabilir
Buffer 12sn (GC dostu)HLS configBellek baskısı azalır

Tespit Edilen Sorunlar (26 Adet)

Kritik Sorunlar (5 Adet)

#1 Yüksek Kalite Bitrate Master Playlist'te 0
Dosya: HLSService.php:125
Problem: $targetBitrate değişkeni generateMasterPlaylist() çağırıldığında tanımsız. calculateTargetBitrate() sonucu dış scope'a taşınmıyor.
Sonuç: Master playlist'teki high variant bandwidth = 0 → HLS.js ABR yanlış karar verir.
Çözüm Önerisi
// calculateTargetBitrate() sonucunu sakla
$targetBitrate = $this->calculateTargetBitrate($originalBitrate);
// ... FFmpeg komutunu oluştur ...
$highBitrate = (int) str_replace('k', '', $targetBitrate) * 1000;
$this->generateMasterPlaylist($storagePath, $highBitrate);
#2 Segment Süresi Tutarsızlığı (6sn vs 4sn)
Dosya: ConvertToHLSJob.php:138 vs HLSService.php:20
Problem: ConvertToHLSJob: -hls_time 6 → HLSService: CHUNK_DURATION = 4
Sonuç: Ana HLS 6sn segment, variant'lar 4sn segment → Master playlist'te tutarsızlık. Seeking sorunlarına yol açabilir.
#7 Soft Mode Playlist Filtre Regex'i Hatalı
Dosya: SongStreamController.php:754-777
Problem: Regex sadece playlist.m3u8 satırını kaldırıyor, #EXT-X-STREAM-INF header satırını bırakıyor. Kalan header → HLS.js'de "playlist not found" hatası.
#8 Encryption Key Dosya Adı Çakışması (enc.key vs enc.bin)
Dosyalar: ConvertToHLSJob → enc.bin, HLSService → enc.key, SongStreamController → enc.bin arıyor
Problem: HLSService ile oluşturulan variant'larda key dosya adı enc.key, ama serveKey() enc.bin arıyor.
Sonuç: Variant key yüklenemez → keyLoadError.
#19 Encryption Key Dosya Adı Standardizasyonu Yok
Problem: 3 farklı dosyada 2 farklı isim kullanılıyor. Tek bir standart (örn: enc.key) belirlenip tüm dosyalarda uygulanmalı.

Orta Seviye Sorunlar (9 Adet)

#3 addVariantsToExisting() Eksik Key Oluşturma
Variant ekleme sırasında keyinfo dosyası oluşturma tutarlılığı belirsiz.
#5 generateMp3128() Path Formatı Tutarsız
sourceMp3: Job'dan mutlak yol, API'den bağıl yol geliyor.
#9 Variant Key URI Endpoint Uyumsuzluğu
createVariantKeyInfo() variant adını URI'ye ekliyor ama serveKey() bunu kontrol etmiyor.
#15 MP3 128k CDN URL Kalite Parametresi
SignedUrlService'den ?q=mp3_128 gönderiliyor ama backend'de bu parametreyi alan endpoint belirsiz.
#17 getHlsDir() 3 Ayrı Yol Denemesi
Tenant context'te yalnızca Yol 2 çalışır, diğerleri gereksiz fallback.
#22 Token = user_id (Tahmin Edilebilir)
İmza doğrulama güçlü ama token'ın user_id olması bilgi sızıntısına neden olabilir.
#25 Playlist Cache 1 Saat — Stale Riski
Variant eklendiğinde cache invalidate edilmiyor → eski master.m3u8 sunulabilir.
#26 FFprobe Hata Yönetimi Eksik
shell_exec() NULL dönebilir, json_decode başarısız → undefined array access.
#10 TTL Max 1 Saat — Crossfade'de Yetersiz
Uzun şarkılarda veya crossfade sırasında imza süresi dolabilir. Max 2 saat önerilir.

Düşük Seviye Sorunlar (12 Adet)

#4 Key URI'de variant parametresi tutarsızlığı
#6 MP3 128k dosya adı standardizasyonu eksik
#11 FFmpeg AF parametresi (kontrol edildi, sorun yok)
#12 hls_time tutarsızlığı (#2 ile aynı)
#13 Tüm segment'lerde tek IV (acceptable)
#14 MP3 128k dosya boyutu log kontrolü zayıf
#16 İmza formatı eşleşiyor (sorun yok)
#18 getMp3Path() Spatie tenant-aware belirsiz
#20 High variant bandwidth hesaplama (zaten EXTINF kullanılıyor)
#21 Crossfade hâlâ kapalı (açılabilir)
#23 Segment public erişim (AES şifreli, kabul edilebilir)
#24 File traversal koruması (zaten iyi)

Dosya Haritası

BileşenDosya YoluSatır
Ana Playerpublic/themes/muzibu/js/player/core/player-core.js8.514
Stream ControllerModules/Muzibu/App/Http/Controllers/Api/SongStreamController.php~800
HLS Servisiapp/Services/Muzibu/HLSService.php~650
Dönüştürme JobModules/Muzibu/App/Jobs/ConvertToHLSJob.php~250
Signed URLapp/Services/SignedUrlService.php~180
Variant CommandModules/Muzibu/App/Console/Commands/AddHlsVariantsCommand.php~280
Muzibu ConfigModules/Muzibu/config/config.php~80
API RoutesModules/Muzibu/routes/api.php~100
Player Bladeresources/views/themes/muzibu/components/player.blade.php~500
HLS.js Kütüphanepublic/themes/muzibu/js/player/lib/hls.min.jsv1.4.12

Özet & Öncelik Sırası

5
Kritik Sorun
Acil düzeltilmeli
9
Orta Seviye
Yakında düzeltilmeli
12
Düşük Seviye
İyileştirme önerisi

Genel Değerlendirme

Player Core (8.514 satır): Stabil, production-ready. HLS pool, key pre-cache, ABR startup lock gibi ileri seviye optimizasyonlar mevcut.
HLS Güvenlik: AES-128 + HMAC imza + file traversal koruması. Temel güvenlik sağlam.
Tamamlanan Gruplar: A (Queue), B (Favorites), G (HLS lazy), C (Spot), F (Session), D (Format) — hepsi çalışıyor.
Backend Tutarsızlıklar: enc.key vs enc.bin, segment 6sn vs 4sn, path formatları — standardizasyon gerekli.
Crossfade (E Grubu): Kod hazır, kapalı. HLS sorunu çözüldüğüne göre açılabilir.

Düzeltme Öncelik Sırası

  1. 1 enc.key / enc.bin standardizasyonu (#8, #19)
  2. 2 Segment süresi tutarsızlığı (#2)
  3. 3 High bitrate master playlist hatası (#1)
  4. 4 Soft mode regex düzeltmesi (#7)
  5. 5 Playlist cache invalidation (#25)
  6. 6 FFprobe hata yönetimi (#26)
  7. 7 TTL uzatma — crossfade hazırlığı (#10)
  8. 8 Crossfade'i aç (E Grubu)