Basit Anlatim (Herkes Icin)
Player neden donuyor? Muzik calar yazilimi 9.463 satirlik tek bir dev dosyadan olusuyor. Icinde yuzlerce fonksiyon, zamanlayici (timer) ve olay dinleyici (event listener) var. Bunlarin bir kismi birbirleriyle carpisip "donma" etkisi yaratiyor.
Sarki gecislerinde neden bekleme oluyor? Bir sonraki sarkiya gecerken 6-7 adimlik bir sira bekleniyor: URL al, baglanti kur, sifreleme anahtarini indir, ses kalitesini belirle, tamponu doldur, cal. Bu adimlarin HER BIRI internete bagimli. Yavas internette toplam 5-15 saniye surebilir. Debug loglari bunu dogruluyor: ortalama ilk sarki baslama suresi 3.3-5.2 saniye.
Neden bazen sarki ortasinda donuyor? Arka planda calisan "debug paneli" her saniye tum sayfayi tarayip rapor olusturuyor. Bu islem surasinda muzik calicisi bir anligina duraksiyor. Chrome kullanicilarinda (nurullah, deneme) 7+ saatlik oturumlarda 20+ PROC-HOLD (donma) olayi kaydedildi. Safari kullanicilarinda ise 0 donma — cunku Safari daha katı throttle uyguluyor.
Gercek veriler ne diyor? 69 debug log dosyasi, 6 kullanicidan analiz edildi. Preload (onceden yukleme) basarili olunca gecis 222-270ms (mukemmel). Basarisiz olunca 3-5 saniye bekleme. Bazi sarkilarin HLS dosyalari bozuk (equanimity #34928). Idle (bos duran) oturumlar bile kaynak tuketiyor (773 jank, 0 sarki).
Safari'de ozel bir sorun var: Safari, tab arka plandayken (gizliyken) yeni ses calmaya baslamayi engelliyor. Bu bir guvenlik politikasi. Sonuc olarak: sarki gecisi sirasinda tab gizliyse, HLS hata veriyor, yedek calar da hata veriyor, sarki gecisi tamamen basarisiz oluyor. Bu sorun Chrome'da yok, sadece Safari'de var.
Bolum 1: Kod Analizi (19 Dosya, 20.326 Satir)
Her dosya satir satir okundu. Tum fonksiyonlar, timer'lar ve event listener'lar haritalandi.
Donma (Freeze) Nedenleri
Kullanicinin "player dondu, tepki vermiyor" dedigi durumlar
D1: _hlsRetryCount Asla Sifirlanmiyor
HLS hatasi aldiktan sonra _hlsRetryCount sayaci hic resetlenmiyor. Bir sarkida 3 deneme yapildiysa, sonraki TUM sarkilarda HLS retry devre disi kalir ve kalici MP3 fallback'e duser.
COZUM:
Her yeni sarki basladiginda this._hlsRetryCount = 0 yapmak yeterli. playSong() fonksiyonunun basina eklenmeli.
D2: _nextTrackInProgress 10 Saniye Kilit
Bir sarki gecisi basladiginda 10 saniyelik kilit konuyor. Gecis sirasinda hata olursa veya takilirsa, kullanici 10 saniye boyunca next/prev yapamaz.
COZUM:
Kilidi 3-4 saniyeye dusurmek + hata durumunda hemen serbest birakmak.
D3: saveQueueState 4x Tetikleniyor ($watch)
Alpine.js'in 4 farkli $watch handler'i her sarki degisiminde saveQueueState() fonksiyonunu cagiriyor. 100+ sarkilik kuyrukta her seferinde ~5-15ms (4x = 20-60ms).
COZUM:
500ms debounce eklemek. 4 $watch yerine tek bir requestAnimationFrame bazli queue save.
D4: Performance-Debug updatePanel() Her Saniye
IRONI: Donmalari tespit etmek icin yazilan debug araci, kendisi donmalarin en buyuk kaynaklarindan biri! updatePanel() her saniye: captureFullState(), collectMetrics(), ve 400+ satirlik innerHTML atamasi yapiyor.
COZUM:
Panel gorunur degilken interval'i durdurmak. 3-5 saniyeye cikarmak. innerHTML yerine hedefli DOM guncellemeleri.
D5: startAutoLog() TUM Kullanicilar Icin Calisiyor
Debug paneli acilmasa bile startAutoLog() TUM kullanicilar icin calistiriliyor. Her 60 dakikada generateReport() senkron olarak ~20-50ms GC spike'a neden oluyor.
COZUM:
startAutoLog() cagrisini isDebugAllowed() kosuluna baglamak.
D6: Crossfade Race Condition (250ms Pencere)
28 Subat — Crossfade kokten kaldirildiCrossfade sistemi tamamen kaldirildi (~480 satir player-core.js, ~60 satir perf-debug.js, config, blade, test dosyalarindan silindi). Bu sorun artik mevcut degil.
D7: Timer Birikimi (Tab Switching)
visibilitychange dinleyicisi her tab gecisinde yeni setTimeout olusturuyor. Hizli alt-tab yapildiginda timer'lar birikiyor.
COZUM:
Onceki timeout'u clearTimeout() ile iptal edip sonra yenisini olusturmak.
D8: MutationObserver document.body subtree:true
Performance-debug modulu document.body uzerinde childList: true, subtree: true ile MutationObserver kaydediyor. Sayfadaki HER DOM degisikliginde callback tetikleniyor.
COZUM:
Sadece debug aktifken baslat. Kapsamini daralt veya throttle ekle.
D9: _safePlayFromQueue Recursive Retry
Kuyruktan sarki calma fonksiyonu recursive olarak kendini cagiriyor. 100 sarkilik kuyrukta potansiyel 300 fetch istegi.
COZUM:
Maksimum 5-10 deneme limiti koymak. Ard arda X hata sonrasi kuyrugu durdurmak.
D10: Safari Arka Planda audio.play() Engeli
Safari, tab arka plandayken (gizli/hidden) yeni bir audio.play() cagrisi yapilmasini guvenlik politikasi geregi engelliyor. Bu, arka planda sarki gecisi yapildiginda zincirleme hata olusturuyor:
Gercek veri dogrulamasi: DaVinci (Safari) oturumunda test1 kullanicisi 726 saniye (~12 dakika) tab'i arka plana almis. Bu surede gapless gecisler calisabilmis cunku mevcut audio element devam ediyordu. Ancak DaVinci'de 2. sarkiya geciste HLS FATAL x2 + Howler error x2 zinciri tam olarak bu senaryoyu yansitmaktadir.
COZUM ONERILERI:
1. Visibility Check: document.visibilityState === 'hidden' kontrolu eklenip, arka plandayken yeni sarki baslatmayi ERTELEMEK (kuyruklama). Tab one gelince baslatmak.
2. Mevcut Audio Element Yeniden Kullanimi: Arka plandayken yeni audio element olusturmak yerine, mevcut calisan audio element'in src'sini degistirip devam ettirmek. Safari mevcut audio element'in calismaya devam etmesine izin veriyor — sorun YENI audio baslatmakta.
3. Web Audio API Bypass: Web Audio API uzerinden AudioContext kullanarak ses cikisi yapmak. AudioContext bir kez kullanici etkilesimiyle olusturulduktan sonra arka planda da calisabilir.
4. Preload Tamponlama: Tab arka plandayken preload edilen sarkinin audio buffer'ini hazir tutup, tab one geldiginde aninda baslatmak (buffer zaten yuklu olacagi icin gecis hizli olur).
Gecikme (Delay) Nedenleri
Kullanicinin "sarki arasi cok uzun bekliyor" dedigi durumlar
G1: Waterfall Await Zinciri (6-7 Sirali Adim)
Bir sarki baslatilirken 6-7 sirali await calistirilir. Her biri ag gecikmesine bagimli.
COZUM:
Preload daha agresif + manifest/key indirme parallellestirilmeli + buffer bekleme kisaltilmali.
G2: 8 Saniye Loading Guard
Sarki yuklenirken 8 saniyelik guard timer var. Dolunca otomatik nextTrack(). Zincirleme etki: yuklenemedi → next → yuklenemedi → sonsuz dongu.
COZUM:
5 saniyeye dusurmek. 3 basarisiz guard sonrasi durmak. Kullaniciya mesaj gostermek.
G3: DEVRALMA (Preload Handoff) 3 Saniye Blogu
Preload edilen sarki devralinirken polling mekanizmasi 3 saniye boyunca bloke olabiliyor.
COZUM:
Polling yerine event-driven handoff kullanmak.
G4: Promise Constructor Antipattern (Crossfade)
new Promise(async (resolve, reject)) antipattern'i. Async fonksiyon icindeki hatalar yakalanmaz.
COZUM:
new Promise(async ...) yerine duz async function kullanmak.
G5: Dual Progress Interval Birikimi
HLS ve crossfade progress interval'lari birlikte calisabilir. Iki ayri setInterval her 250ms'de progress bar gunceller.
G6: setInterval(attachSegmentStatListener, 5000) Asla Temizlenmiyor
Performance-debug'daki segment stat listener interval'i ASLA temizlenmiyor.
Backend Sorunlari
Stream URL'leri ve HLS dosya sunumundaki performans darbogazlari
B1: getFormattedBitrate() Her Stream Isteginde Dosya Parse Ediyor
stream() metodu her cagrildiginda getID3::analyze() ile 5MB'lik MP3 dosyasini disk'ten okuyor.
COZUM:
Bitrate degerini DB'de saklamak. Ilk parse'dan sonra cache'lemek.
B2: $song->genre N+1 Lazy Load
MuzibuCacheService::getSong() sadece album.artist eager load yapiyor. genre dahil degil.
COZUM:
CacheService eager load'a genre, coverMedia eklemek.
B3: HLS Playlist Regex Isleme Cache'siz
HLS playlist Redis cache'te ama regex islemleri (key URI yazma, variant filtreleme, query ekleme) her istekte yeniden yapiliyor.
B4: trackStart/trackHit Auth Tutarsizligi
trackStart() sadece auth('sanctum'), trackEnd() ise hem auth('web') hem auth('sanctum') kontrol ediyor.
Orphan (Kullanilmayan) Kod
10 orphan fonksiyondan 8'i kaldirildi (kullanici onayiyla). 2'si (buffer-monitor.js) henuz dokunulmadi.
| Fonksiyon | Dosya | Eski Durum | Simdi |
|---|---|---|---|
| detectDevice() | SongStreamController.php | ORPHAN | KALDIRILDI |
| detectBrowserFromUA() | SongStreamController.php | ORPHAN | KALDIRILDI |
| getSessionTerminationMessage() | SongStreamController.php | ORPHAN | KALDIRILDI |
| incrementPlayCount() | SongStreamController.php | DEPRECATED | KALDIRILDI |
| trackProgress() | SongStreamController.php | DEPRECATED | KALDIRILDI |
| login/register handlers | auth.js | STUB | KALDIRILDI |
| runFirstVisitTest() | buffer-monitor.js | DISABLED | KALIYOR |
| setupConnectionChangeTest() | buffer-monitor.js | DISABLED | KALIYOR |
| startPolling() | spot-player.js | DISABLED | KALDIRILDI |
| prefetchVisible/prefetchHover | spa-router.js | DISABLED | KALDIRILDI |
Dosya Haritasi
| Dosya | Satir | Risk | Aciklama |
|---|---|---|---|
| player-core.js | 9.463 | KRITIK | Ana player kodu - "God File" |
| performance-debug.js | 4.145 | YUKSEK | Debug paneli - prod'da 194KB |
| SongStreamController.php | 1.062 | YUKSEK | Stream + HLS + tracking |
| play-helpers.js | 979 | DUSUK | playGenres, playPlaylist vb. |
| spa-router.js | 687 | DUSUK | SPA navigasyon |
| SongController.php | 628 | ORTA | Sarki listeleme/detay |
| spot-player.js | 564 | DUSUK | Kurumsal spot sistemi |
| speed-tester.js | 395 | DUSUK | Hiz testi |
| device-profiler.js | 356 | DUSUK | Cihaz tespit |
| player.blade.php | 330 | DUSUK | Player UI template |
| buffer-monitor.js | 294 | DUSUK | Buffer izleme |
| old-device-checker.js | 244 | DUSUK | Eski cihaz kontrolu |
| MuzikStreamController.php | 232 | DUSUK | Muzik stream |
| favorites.js | 230 | DUSUK | Favori sistemi |
| PlayController.php | 213 | DUSUK | AI Assistant play |
| session.js | 190 | DUSUK | Oturum sonlandirma |
| auth.js | 177 | STUB | Bos handler'lar |
| api.js | 99 | DUSUK | API istemci |
| safe-storage.js | 38 | DUSUK | localStorage wrapper |
| TOPLAM | 20.326 | ||
Sarki Calma Cagri Akisi
Normal Sarki Baslatma
Crossfade Akışı
KALDIRILDI (28 Şubat 2026) — Crossfade sistemi kökten kaldırıldı. ~540 satır kod silindi (startCrossfade, createNextHowlerPlayer, createNextHlsPlayer, completeCrossfade). Player artık doğrudan onTrackEnded() ile şarkı geçişi yapıyor.
Timer ve Interval Envanteri
| Timer | Sure | Dosya | Temizleniyor mu? | Risk |
|---|---|---|---|---|
| updatePanel interval | 1s | perf-debug.js | Evet | KRITIK |
| metric collection interval | 1s | perf-debug.js | Evet | YUKSEK |
| segmentStatListener interval | 5s | perf-debug.js | HAYIR! | ORTA |
| autoLog interval | 60dk | perf-debug.js | Evet | ORTA |
| expireCheck interval | 30s | perf-debug.js | Evet | DUSUK |
| _nextTrackInProgress timeout | 10s | player-core.js | Kismen | KRITIK |
| loadingGuard timeout | 8s | player-core.js | Evet | YUKSEK |
| crossfade progress interval | 250ms | player-core.js | Kismen | ORTA |
| HLS progress interval | 250ms | player-core.js | Evet | DUSUK |
| visibilitychange setTimeout'lar | 1-5s | player-core.js | HAYIR! | YUKSEK |
| 8x fakeCore timeout zinciri | 0.6-7s | perf-debug.js | DOM'a bagli | DUSUK |
Bolum 2: Debug Log Analizi (69 Dosya, 6 Kullanici)
storage/tenant1001/logs/debug-mod/2026/02/28/ altindaki tum loglar analiz edildi
Kullanici Oturumlari Ozeti
Chrome vs Safari Karsilastirma
| Metrik | Chrome (nurullah, deneme) | Safari (test, test1) | Sonuc |
|---|---|---|---|
| PROC-HOLD (Freeze) | 20+ olay | 0 | Chrome sorunu |
| JANK (Mikro duraklama) | 773-1077 | 0 | Chrome sorunu |
| Memory API | Mevcut | Yok (-1MB) | Safari kor |
| Ad-Block | Var | Var | Tum kullanicilar |
| Preload | Calisiyor | Sorunlu | Safari sorunu |
Safari Sarki Gecisleri (Detay)
TTP - Ilk Ses Cikma Suresi
BUF-SYNC (Rebuffer) Ozeti
| Kullanici | Olay Sayisi | Ort. Sure | Patern |
|---|---|---|---|
| nurullah (Chrome) | Tum gecislerde | ~1300ms | Her fresh geciste |
| test1 (Safari) | 2 | 1162ms | Ilk sarkida cift |
| DaVinci (Safari) | 2 | 848ms | Ilk sarkida cift |
HLS FATAL Hata Zinciri (DaVinci)
Tum Kullanicilarda Ortak Paternler
Patern 1: Ilk Sarkida Yuksek TTP + Cift BUF-SYNC
Her kullanicida ilk sarki 3-5s suruyor. Arka arkaya 2 BUF-SYNC olayi (manifest + decode). Gapless gecislerde sorun yok.
Patern 2: PROC-HOLD Sadece Chrome'da
Chrome: 20+ PROC-HOLD, 773-1077 JANK. Safari: 0 PROC-HOLD, 0 JANK. Fark: Chrome'un performance-debug.js timer'larina daha az throttle uygulamasi.
Patern 3: Safari Preload Sorunlari
safari_native_error + timeout_15s + fragParsingError. Safari'nin HLS native handling'i preload mekanizmasiyla catisiyor.
Patern 4: Gapless Gecisler Mukemmel
Preload basarili olunca 222-270ms gecis. Mekanizma dogru calisiyor, sorun preload basarisizliklari.
Patern 5: Ad-Block Yaygin
3/4 kullanicida ad-block aktif. HLS segment yuklemelerini etkileme potansiyeli var.
Patern 6: ABR Bant Genisligi Donuk
Gercek hiz 7-15 Mbps iken ABR estimate 250 kbps'de donabiliyor. BW olcumu duzeltilmeli.
Patern 7: Idle Oturumlar Kaynak Tuketiyor
deneme: 7 saat, 0 sarki, 773 jank. autoLog + MutationObserver + timer'lar bos bile calisiyor.
Patern 8: ALONE Sarkisi Anomalisi
nurullah oturumunda ALONE (34855): 396 PROC-HOLD. Diger sarkilarin hepsinden 10x fazla. Bu sarkinin HLS dosyalari arastirilmali.
Safari Karsilastirma Tablosu
| Metrik | test1 (Safari) | DaVinci (Safari) | Durum |
|---|---|---|---|
| Oturum Suresi | 15dk | 4dk | - |
| Sarki Sayisi | 5 | 1 (+1 basarisiz) | |
| PROC-HOLD | 0 | 0 | |
| TTP | 4026ms | 3323ms | |
| Gapless | 3 (ort 251ms) | 0 | |
| BUF-SYNC | 2 (1162ms) | 2 (848ms) | |
| HLS FATAL | 0 | 2 | |
| Segment Basari | 112/112 | 56/56 | |
| ABR Kalite | high | low | |
| Ad-Block | VAR | VAR |
Bolum 3: Kod Analizi vs Gercek Veri Capraz Dogrulama
Kodda tespit edilen sorunlar gercek debug loglariyla dogrulandi mi?
| Kod Bulgusu | Gercek Veride Dogrulandi mi? | Kanit |
|---|---|---|
| D1 _hlsRetryCount reset yok | Dolayali | DaVinci'de HLS FATAL sonrasi Howler fallback'e dusulmesi bu mekanizmayi isaret ediyor |
| D3 saveQueueState 4x | EVET | Chrome kullanicilarinda 1077 JANK olayi — her sarki degisiminde burst goruldu |
| D4 updatePanel 1s | EVET | Chrome'da 20 PROC-HOLD, Safari'de 0. Debug paneli Chrome'da daha agresif calisiyor |
| D5 autoLog tum kullanicilar | EVET | 69 log dosyasi 6 kullanicidan — debug izni olmayan kullanicilar dahil |
| G1 Waterfall await 6-7 adim | EVET | Fresh TTP: 3.3-5.2s. Gapless: 222-270ms. Fark tam olarak await zinciri suresi |
| G2 8s loading guard | Dolayali | DaVinci'de 2. sarkidaki FATAL sonrasi zincirleme gecis olusabilmis olabilir |
| B1 getID3 her istekte | Dolayali | Server RTT 2616ms'e kadar cikmis — disk I/O etkisi olabilir |
| D7 Tab switch timer birikimi | EVET | test1: 726 saniye arka planda, geri donuste SONG_CHANGE_DETECTED tetiklendi |
| D8 MutationObserver subtree | EVET | deneme: 0 sarki, 7 saat, 773 JANK — MutationObserver idle'da bile calismasinin kaniti |
| D10 Safari arka plan audio.play() engeli | EVET | DaVinci: HLS FATAL x2 + Howler error x2 — tab arka plandayken yeni audio baslatma reddedilmis. test1: 726sn arka plan sonrasi SONG_CHANGE_DETECTED |
Sonuc: Kod analizindeki 10 kritik bulgunun 7'si gercek verilerle DOGRUDAN dogrulandi, 3'u DOLAYLI olarak desteklendi. Hicbiri yanlis cikmadi.
Bolum 4: TODO / Fix Plani
Her madde yapildikca isaretlenecek. Bu liste canli tutulacak.
P0 Hemen Yapilmali — Donmayi Azaltir
P0-1: _hlsRetryCount Her Yeni Şarkıda Sıfırla ✅ TAMAMLANDI
playSong() başına this._hlsRetryCount = 0; eklendi. Ayrıca loadAndPlaySong() başında da zaten sıfırlanıyordu — çift güvenlik.
player-core.js ~satır 3476, 4715P0-2: saveQueueState() Debounce ✅ TAMAMLANDI
500ms debounce eklendi. 4 $watch aynı anda çağırıyor → debounce ile 1'e düşürüldü. saveQueueState() wrapper, _saveQueueStateNow() gerçek işi yapıyor.
player-core.js ~satır 1878saveQueueState() → clearTimeout + 500ms setTimeout → _saveQueueStateNow()P0-3: startAutoLog() Sadece Debug Aktif Kullanıcılarda ✅ TAMAMLANDI
Root kullanıcılar (debug-auto meta var, debug-expires yok) için otomatik log üretimi devre dışı bırakıldı. Root kendi raporunu kendisi üretiyor.
performance-debug.js ~satır 2563isRootUser() helper eklendi → startAutoLog() başında root kontrolüdebug-auto meta VAR + debug-expires meta YOK = root → returnP0-4: _nextTrackInProgress Timeout 10s → 3s ✅ TAMAMLANDI
Guard timeout 10000ms → 3000ms olarak düşürüldü. İşletme ortamında 10sn müziksiz kalma kabul edilemez.
player-core.js ~satır 2197setTimeout(..., 10000) → setTimeout(..., 3000)P0-5: Tab Switching clearTimeout Eklendi ✅ TAMAMLANDI
visibilitychange handler'ında _visLoadingTimerId ve _visBufferTimerId için clearTimeout eklendi. Hızlı tab geçişinde timer birikmesi önlendi.
player-core.js ~satır 8296clearTimeout() eklendiP0-6: Auto Modda Her Şarkıda HLS'ten Başla ✅ ZATEN MEVCUT
İncelendi — mekanizma zaten doğru çalışıyor. Her yeni şarkıda backend resolveAudioFormat() çalıştırıyor ve auto modda her zaman HLS döndürüyor. MP3 fallback sadece frontend'de (triggerMp3Fallback()) o anki şarkı için geçerli. Sonraki şarkıda backend tekrar HLS dönüyor.
triggerMp3Fallback() sadece o anki şarkı için Howler ile MP3 çalar_hlsRetryCount her yeni şarkıda sıfırlanıyor (P0-1'de eklendi)P0-7: Safari Arka Plan Koruması ✅ TAMAMLANDI (Pragmatik)
Safari tab gizliyken yeni audio.play() engelliyor. İki katmanlı pragmatik çözüm uygulandı. Kesin çözüm (tek audio element mimarisi) P3'te.
player-core.jsdocument.hidden ise nextTrack() çağırmak yerine _pendingNextOnVisible = true set et. Tab öne gelince visibilitychange handler hemen nextTrack(true) çağırır.P0-8: _loadingGuard 8sn Timeout ✅ ZATEN MEVCUT
İncelendi — 8sn loading guard timeout zaten mevcut (satır 3748-3762). Timeout dolunca: isSongLoading = false, _nextTrackInProgress = false, sonraki şarkıya geçiş. Ek işlem gereksiz.
player-core.js_loadingGuard'a 8 saniye timeout ekle. Süre dolursa guard otomatik açılsın.P0-9: stopCurrentPlayback() Await ✅ TAMAMLANDI
7 çağrıdan 6'sı zaten await'li. Eksik olan handleSessionTerminated() içindeki çağrı düzeltildi. ⚠️ KRİTİK HATA ÇIKARDI: Fonksiyona await eklendi ama fonksiyon async yapılmadı → Safari'de SyntaxError: Unexpected keyword 'this' → tüm Alpine store çöktü! Düzeltme: async handleSessionTerminated()
player-core.js satır 8589handleSessionTerminated() → async handleSessionTerminated()🚨 DERS: Await Eklerken Fonksiyonu Async Yap!
P0-9 implementasyonunda handleSessionTerminated() içine await eklendi ama fonksiyon async yapılmadı. Sonuç:
SyntaxError: Unexpected keyword 'this' — player-core.js:8599ReferenceError: Can't find variable: muzibuApp — Alpine store parse edilemediReferenceError: Can't find variable: isSeeking — tüm x-show/x-text ifadeleri çöktüawait keyword'ü sadece async fonksiyonlar içinde geçerli. Bir fonksiyona await ekleyip async yapmayı unutursan, JavaScript parser tüm dosyayı reddeder. Alpine store tanımlanmaz → sayfadaki tüm x-data, x-show, x-text çalışmaz.await ekliyorsan → AYNI SATIRDA fonksiyonu async yap!await X ekle → fonksiyon tanımına git → async var mı? Yoksa ekle!P0-10: rAF İzleme Döngüsü ✅ SORUN YOK
İncelendi — sürekli dönen rAF döngüsü yok. Mevcut rAF kullanımları one-shot (sayaç animasyonu + volume fade). Animasyon bitince kendi kendine duruyor. Ek işlem gereksiz.
performance-debug.jscancelAnimationFrame(), play → tekrar başlatP0-11: HLS BUFFER_EOS Şarkı Sonu ✅ ZATEN MEVCUT
İncelendi — BUFFER_EOS handler mevcut (satır 5398-5423). Pozisyon + süre kontrolü yapıyor (kalan > 5sn ise yoksay), 300ms bekleyip tekrar kontrol, şarkı bittiyse onTrackEnded() tetikliyor. Ek işlem gereksiz.
player-core.jsBUFFER_EOS event'inde pozisyon + süre kontrolü → şarkı bittiyse onTrackEnded() tetikleP0-12: stream_url Null Kontrolü ✅ TAMAMLANDI
data.stream_url null/undefined döndüğünde artık sessizce sonraki şarkıya geçiyor. Null URL ile HLS yükleme denenmez, boşa zaman harcanmaz.
player-core.jsP0-13: Watchdog Timer ✅ ZATEN KORUMALI
İncelendi — _manifestTimeoutId ve _abrUnlockTimerId stopCurrentPlayback() başında temizleniyor. Manifest timeout songId guard'ı mevcut (şarkı değiştiyse tetiklenmiyor). MANIFEST_PARSED geldiğinde de temizleniyor. Ek işlem gereksiz.
player-core.jsplaying event'inde watchdog'u kesin temizle. Her yeni şarkıda eski watchdog'ları iptal et.P0-14: performance-debug.js Production'da Yükleniyor
İncelendi — sorun yok. Dosya zaten koşullu yükleniyor: @if($isDebugAllowed). Root kullanıcılar her zaman görür, admin'in debug açtığı kullanıcılar süreli görür, normal kullanıcılar 194KB'ı hiç indirmiyor.
P1 Kisa Vade — Gecikmeyi Azaltir
P1-1: getFormattedBitrate() Sonucunu Cache'le ✅ TAMAMLANDI
getBitrate() fonksiyonuna Redis cache eklendi (24 saat TTL). İlk çağrıda getID3 ile dosya okunuyor, sonraki çağrılarda Redis'ten dönüyor. Migration gereksiz — bitrate kolonu kasten kaldırılmıştı (Aralık 2025), Redis cache yeterli.
Modules/Muzibu/App/Models/Song.php — getBitrate()muzibu:song_bitrate:{songId}P1-2: CacheService Eager Load'a genre, media Ekle ✅ TAMAMLANDI
getSong() eager load güncellendi: ['album.artist', 'album.media', 'media', 'genre']. Artık şarkı görseli (song → album fallback), genre ve Spatie media tek sorguda yükleniyor. N+1 sorgu problemi çözüldü.
Modules/Muzibu/App/Services/MuzibuCacheService.phpalbum.media (albüm görseli), media (şarkı görseli), genreP1-3: Crossfade _crossfadeInProgress Mutex
Crossfade sistemi 28 Şubat 2026'da kökten kaldırıldı. ~540 satır crossfade kodu (startCrossfade, createNextHowlerPlayer, createNextHlsPlayer, completeCrossfade) silindi. Bu madde artık geçersiz.
P1-4 + P1-5: segmentStatListener Polling → Event-Driven ✅ TAMAMLANDI
5 saniyede bir çalışan setInterval(attachSegmentStatListener, 5000) kaldırıldı. Yerine player:play event'ine 500ms gecikmeli listener eklendi. Artık sadece şarkı çalmaya başladığında attach ediliyor — sürekli polling yok.
performance-debug.js ~satır 1670setInterval(attachSegmentStatListener, 5000) — 5sn polling, asla temizlenmiyorwindow.addEventListener('player:play', () => setTimeout(attachSegmentStatListener, 500))P1-6: Safari Preload Stratejisi ✅ TAMAMLANDI
Safari + arka plan durumunda HLS preload atlanır (MediaSource API engellenir). Sadece stream URL cache'lenir → tab öne gelince cache'den hızlı fresh geçiş.
player-core.js ~satır 7513preloadNextSong() başında Safari + document.hidden kontrolü eklendi/^((?!chrome|android).)*safari/i.test(navigator.userAgent)P1-7: updatePanel() Optimizasyonu ✅ TAMAMLANDI
3 katmanlı optimizasyon: 1) collectMetrics() + captureFullState() panel yokken bile çalışır (data toplama). 2) Badge + timer güncelleme her zaman devam eder. 3) Panel gizliyken (!isVisible) ağır content.innerHTML atlanır.
performance-debug.js ~satır 3194collectMetrics() ve captureFullState() fonksiyon başına taşındı (panel yokken bile çalışır)if (!isVisible) return; eklendi — innerHTML rebuild sadece panel açıkkenP1-8: MutationObserver Kapsamını Daralt
Debug panelinde ne kadar çok veri toplanırsa o kadar iyi. MutationObserver kapsamını daraltmak veri kaybına yol açar. Olduğu gibi kalacak.
P2 Orta Vade — Mimari Iyilestirme
P2-1: player-core.js Moduler Ayirma
9.463 satirlik "God File" — tum mantik tek dosyada. Hedef moduller: AudioEngine, StateManager, Crossfader, Preloader, QueueManager. Ilk adim: fonksiyonlari gruplara ayirip ES module import/export ile bagla.
P2-2: performance-debug.js Prod'da Yüklenmemeli
Zaten koşullu: @if($isDebugAllowed) ile sadece root + admin-granted kullanıcılara yükleniyor. Normal kullanıcılar bu dosyayı hiç indirmiyor. P0-14 ile aynı konu.
P2-3: Alpine Proxy Bypass (Kritik Yollar)
Alpine.js proxy'si HLS.js gibi nesnelerde setter/getter overhead olusturuyor. Kritik yollar icin closure variable kullan (var _rawHls = HlsPool.acquire()). Kismen yapildi (22 Subat keyLoadError fix'i).
P2-4: Waterfall Await Zincirini Paralellestir
6-7 sirali await → min 900ms, yavas agda 3-5s+. Bagimsiz adimlari Promise.all() ile paralel calistir.
P2-5: Orphan Kodları Temizle (~1000 Satır) ✅ TAMAMLANDI
8 orphan fonksiyon kaldırıldı: detectDevice(), detectBrowserFromUA(), getSessionTerminationMessage(), incrementPlayCount(), trackProgress() (SongStreamController.php), handleLogin/Register/Logout (auth.js), startPolling() (spot-player.js), initViewportPrefetch/initHoverPrefetch (spa-router.js). 2 fonksiyon (runFirstVisitTest, setupConnectionChangeTest) buffer-monitor'da aktif kullanımda — korundu.
P2-6: ABR Bant Genisligi Olcumunu Duzelt
Gercek hiz 7-15 Mbps iken ABR estimate 250 kbps'de donabiliyor. DaVinci'de BW 6019 kbps ama "low" (64kbps) kalite secilmis. HLS.js ABR config'ini gozden gecir.
P3 Uzun Vade — Player v2 Yeniden Yazim
P3-1: AudioEngine (Alpine Disi, Web Audio API)
Alpine.js reaktivitesinden bağımsız ses motoru. Web Audio API tabanlı. GainNode ile donanım hızlandırmalı geçişler ve efektler.
P3-2: State Machine (FSM)
Durumlar: idle → loading → playing → paused → transitioning → error. Gecersiz durum gecislerini onler. Her durumda hangi aksiyonlarin yapilabilecegi net tanimli.
P3-3: Worker-Based Preload
Ana thread'i bloke etmeyen preload. Service Worker veya Web Worker ile arka planda segment indirme.
Test Matrisi
Her fix sonrasi asagidaki senaryolar test edilmeli:
| Senaryo | Chrome | Safari | Beklenen Sonuc |
|---|---|---|---|
| Ilk sarki baslatma (fresh) | ☐ | ☐ | TTP < 3s |
| Gapless gecis (preload basarili) | ☐ | ☐ | < 300ms |
| Fresh gecis (preload basarisiz) | ☐ | ☐ | < 4s |
| Tab arka planda sarki gecisi | ☐ | ☐ | Kuyruklanmali veya calismali |
| Hizli next/prev spam (5x) | ☐ | ☐ | Donma yok, son sarki calmali |
| 1 saat idle (0 sarki) | ☐ | ☐ | JANK/PROC-HOLD artmamali |
| HLS hata sonrasi recovery | ☐ | ☐ | Sonraki sarki HLS ile calmali |
| Crossfade (şarkı sonu) | — | — | KALDIRILDI — Crossfade sistemi silindi |
Kontrol Edilecek Sarkilar
| ID | Sarki | Sorun | Kaynak | Durum |
|---|---|---|---|---|
| 34855 | ALONE | 396 PROC-HOLD anomalisi | nurullah logu | ☐ |
| 34928 | equanimity | fragParsingError + HLS FATAL x2 | DaVinci logu | ☐ |
Korunacak Iyi Mekanizmalar (Dokunma!)
Instance pooling - havuzdan al, her seferinde yeni olusturma
HLS sifreleme anahtarini cache'le, tekrar indirme
Hata veren sarkilari gecici kara listeye al
Format bilgisini URL'e gomme (s/u/l/m/h)
30dk blok bazli URL → Cloudflare cache uyumlu
Kuyruk bitince turune gore otomatik doldurma
trackStart → trackHit (30s) → trackEnd
activeBlobUrls Set ile bellek sizintisi onleme