Crossfade Analiz & Aktivasyon Planı

E Grubu: Şarkılar arası yumuşak geçiş sistemi

8 Hata 3 Fazlalık 10 Doğru 4 Simülasyon

Mevcut Durum

Basit Anlatım

Crossfade, bir şarkı biterken sonraki şarkının yavaşça başlaması (ses geçişi) özelliğidir. Radyo yayınlarındaki gibi kesintisiz müzik deneyimi sağlar. Kod tamamen yazılmış ama kapalı durumda. Daha önce HLS şifreleme hatasını (keyLoadError) çözmemiz gerekiyordu — o hata artık çözüldü. Ancak açmadan önce birkaç hata düzeltilmeli.

Teknik Durum

Neden Kapalı?

// player-core.js:888-891 crossfadeEnabled: false, // Ana anahtar crossfadeDuration: 0, // Süre sıfır!

Duration 0 olduğu sürece tetikleme koşulu (timeRemaining <= 0) asla sağlanamaz

Config'de Ne Var?

// config.php:20 'crossfade_duration' => 7000 // 7 saniye // app.blade.php:537 crossfadeDuration: {{ config(..., 4000) }} // → window.PLAYER_CONFIG.crossfadeDuration = 7000 AMA player-core.js'te 0 ile override!

Crossfade Dosya Haritası

Fonksiyon Satır Görevi
startCrossfade()2500-2685Ana orkestratör — geçişi başlatır
createNextHowlerPlayer()2688-2718MP3 için 2. Howler instance
createNextHlsPlayer()2720-2864HLS için 2. HLS.js + audio element
completeCrossfade()2867-2972Eski player'ı temizle, yeni player'ı ata
fadeAudioElement()6525-6555HTML5 audio ses animasyonu (rAF)
startProgressTrackingWithElement()6613-6637Crossfade'e özel progress takibi
HlsPool.*549-678HLS.js instance havuzu (2 slot)
performance-debug.js1081-1091XMIX izleme paneli

Hatalar & Eksiklikler (8 Adet)

#1 — Event Dispatch Eksikliği

KRİTİK

Basit: Performans paneli crossfade'in başladığını/bittiğini hiç görmüyor. Sayaç hep 0 kalıyor.

Teknik: performance-debug.js satır 1081-1091'de player:crossfadeStart ve player:crossfadeEnd event'leri dinleniyor. Ancak player-core.js'te bu event'ler hiçbir yerde dispatch edilmiyor.

// performance-debug.js:1081 — DİNLİYOR ama tetikleyen YOK! window.addEventListener('player:crossfadeStart', function(e) { history.crossfadeCount++; // Asla artmaz! });
Çözüm: startCrossfade()'de dispatch başlangıç, completeCrossfade()'de dispatch bitiş event'i eklenecek.

#2 — crossfadeDuration Config Override

KRİTİK

Basit: Sunucuda 7 saniye ayarlanmış ama player bunu görmezden geliyor, 0 kullanıyor. 0 saniye = crossfade asla tetiklenemez.

Teknik: config.php'da crossfade_duration: 7000, app.blade.php'de PLAYER_CONFIG.crossfadeDuration: 7000 olarak inject ediliyor. Ama player-core.js:891'de crossfadeDuration: 0 hardcode — config değeri override ediliyor.

// ŞU AN: Hardcode 0 — config'i yok sayıyor! crossfadeDuration: 0, // OLMASI GEREKEN: Config'den al crossfadeDuration: window.PLAYER_CONFIG?.crossfadeDuration || 7000,

#3 — Howler Crossfade Hata Kurtarma Yok

ORTA

Basit: MP3 ile crossfade sırasında hata olursa müzik duruyor, kendi kendini kurtaramıyor. HLS'de bu sorun yok.

Teknik: createNextHowlerPlayer() satır 2711-2712'de onloaderror sadece console.error yapıyor. HLS tarafında fatal error → playSongFromQueue() ile otomatik skip var.

Çözüm: onloaderror'da isCrossfading = false + playSongFromQueue(nextIndex) eklenmeli.

#4 — Background Tab setTimeout Throttle

ORTA

Basit: Tarayıcı başka sekmede iken crossfade tamamlanması 1 dakikaya kadar gecikebilir. Eski şarkı susturulmuş ama bellek tüketiyor.

Teknik: Satır 2641'de setTimeout(..., crossfadeDuration) kullanılıyor. Chrome background tab'da setTimeout'u 1dk'ya kadar throttle eder. Eski HLS instance + audio element 1dk boyunca serbest bırakılmaz.

Çözüm: Background tab tespit edildiğinde completeCrossfade() hemen çağrılmalı (fade zaten atlanıyor, neden bekleyelim?).

#5 — startProgressTrackingWithElement: timeupdate Dispatch Yok

ORTA

Basit: Crossfade sırasında dinleme süresi limiti (play-limits) çalışmıyor.

Teknik: startProgressTracking('hls') satır 6587-6596'da player:timeupdate event'i dispatch ediyor. Ama crossfade'e özel startProgressTrackingWithElement() satır 6613-6637'de bu dispatch yok.

#6 — startProgressTrackingWithElement: playTracked Eksik

ORTA

Basit: Crossfade ile geçilen şarkılarda 30 saniyelik dinleme sayacı (hit +1) çalışmıyor.

Teknik: startProgressTracking('hls') satır 6598-6602'de 30s sonra trackSongPlay() çağrılıyor. startProgressTrackingWithElement()'te bu kontrol yok. Crossfade sonrası completeCrossfade() startProgressTrackingWithElement() çağırıyor (satır 2943) — sonra startProgressTracking('hls')'e geçişte (satır 2943 aslında element versiyonu) bu kayıp oluyor.

Çözüm: startProgressTrackingWithElement() içine timeupdate dispatch ve playTracked kontrolü eklenmeli. Aslında en temiz çözüm: completeCrossfade()'de startProgressTracking('hls') kullanmak (getActiveHlsAudio() zaten doğru element'i döndürüyor).

#7 — Howler Progress Tracking'de Shadowed Variable

DÜŞÜK

Satır 2605: const self = this; tanımlanıyor ama kullanılmıyor (arrow function içinde this zaten doğru). Üst kapsamda da satır 2528'de const self = this; var — shadowed variable. Hata değil ama karışıklık yaratıyor.

#8 — completeCrossfade'de Gereksiz Çift Atama

DÜŞÜK

queueIndex ve currentSong hem startCrossfade() satır 2575-2576'da hem de completeCrossfade() satır 2959-2960'da set ediliyor. İkincisi gereksiz çünkü değerler zaten aynı. Ancak güvenlik amaçlı (savunmacı programlama) bırakılabilir.

Fazlalıklar (3 Adet)

1

Satır 2605: const self = this; — Arrow function içinde gereksiz (silinmeli)

2

Satır 2959-2960: queueIndex ve currentSong çift ataması — startCrossfade'de zaten set ediliyor (savunmacı kod, bırakılabilir)

3

Satır 2964: updatePlayerColors() çift çağrı — startCrossfade satır 2585'te de çağrılıyor. completeCrossfade'deki kaldırılabilir (zaten aynı şarkı bilgisi)

Doğru Çalışan Mekanizmalar (10 Adet)

HlsPool destroy+fresh — decryptdata sorunu önleniyor
Alpine proxy bypass — closure variable ile
ABR startup lock — FRAG_BUFFERED + 3s timeout
Key prefetch — crossfade başlamadan key hazır
Dual audio element — hlsAudio / hlsAudioNext swap
Pause sırasında handling — timeout iptal, swap, cleanup
stopCurrentPlayback cleanup — howlNext + hlsNext temiz
Background tab — fade skip, direkt volume
Blob URL cleanup — memory leak önleme
Safari native HLS — canPlayType fallback

Simülasyonlar (4 Senaryo)

Senaryo 1: Normal Crossfade (HLS → HLS)

Şarkı 4:00, crossfadeDuration: 7000ms (7 saniye). currentTime = 3:53'e geldiğinde tetiklenir.

t = 3:53

startProgressTracking: timeRemaining = 7s ≤ 7s → startCrossfade() tetiklenir

t = 3:53.001

Guard: isPlaying ✓, isCrossfading=false ✓, hasActiveHls ✓, nextIndex ≠ -1 ✓

t = 3:53.002

Preload cleanup: Varsa temizle (crossfade kendi instance'ını kullanacak)

t = 3:53.003

isCrossfading = true — tekrar tetiklenme önlenir

t = 3:53.010

getCachedStream: Preload sayesinde URL cache'de → anında alınır

t = 3:53.020

createNextHlsPlayer: HlsPool.acquire() → hlsNext oluştu

prefetchHlsKey → ABR lock → loadSource → attachMedia → MEDIA_ATTACHED → startLoad

t = 3:53.500

MANIFEST_PARSED: nextAudio.play() → fadeAudioElement(0 → volume, 7s)

t = 3:53.510

UI güncelle: queueIndex, currentSong, currentTime=0, progressPercent=0, trackSongStart()

t = 3:53.520

Eski player fade-out: fadeAudioElement(volume → 0, 7s) — iki şarkı aynı anda çalıyor!

t = 4:00.520

completeCrossfade: Eski HLS release → swap (hlsNext → hls) → yeni progress tracking → preloadNextSong()

Sonuç: Sorunsuz geçiş. 7 saniye boyunca iki şarkı üst üste çalar, yumuşak ses geçişi sağlanır.

Senaryo 2: Background Tab Crossfade

t = 3:53

document.hidden = true → isBackgroundTab = true

t = 3:53.020

Yeni audio: nextAudio.volume = targetVolume (fade yok, direkt set)

t = 3:53.030

Eski audio: audio.volume = 0 (fade yok, direkt mute)

t = 3:53.040

setTimeout(completeCrossfade, 7000) — Chrome throttle: gerçekte ~60 saniye sonra çalışabilir!

t = 3:53 → 4:53

1 dakika boyunca: Eski HLS instance + audio element bellekte duruyor (volume=0 ama aktif). HlsPool'da 2 slot dolu → yeni crossfade başlatılamaz.

Sorun: Background'da fade yapılmıyor (doğru) ama completeCrossfade gecikiyor (yanlış). Bellek sızıntısı ve HlsPool tıkanması riski.

Senaryo 3: Crossfade Sırasında Pause

t = 3:55 (crossfade aktif, 2s geçmiş)

Kullanıcı pause'a basıyor

t = 3:55.001

crossfadeTimeoutId iptal: clearTimeout → 5s sonra completeCrossfade tetiklenmeyecek

t = 3:55.002

completeCrossfade hemen çağrılıyor: Swap yapılır, yeni şarkı aktif olur

t = 3:55.010

Tüm audio pause: hlsAudio + hlsAudioNext pause, event listener temizliği

Sonuç: Doğru çalışıyor. Play'e basınca yeni şarkıdan devam eder.

Senaryo 4: Crossfade Hatası

t = 3:53

startCrossfade: isCrossfading = true, createNextHlsPlayer başlatılıyor

t = 3:53.500

HLS Fatal Error: bufferAppendError veya mediaError

t = 3:53.510

Auto-recover: taint(hlsNext) → release(hlsNext) → safeAudioCleanup → isCrossfading=false

t = 3:53.610

playSongFromQueue(nextIndex): 100ms gecikme sonra direkt geçiş (fade yok ama müzik devam eder)

Sonuç: HLS hatalarında iyi kurtarma mekanizması var. Müzik kesilmez, sadece keskin geçiş olur.

Aktivasyon Planı

Basit Anlatım

8 sorunu düzeltip crossfade'i açacağız. İşler 3 aşamada yapılacak: Önce kritik hataları düzelt (2 adet — bunlar olmadan çalışmaz), sonra orta seviye sorunları düzelt (4 adet — çalışır ama eksik kalır), son olarak temizlik yap ve aç. Her aşamadan sonra test edeceğiz.

Aşama 1 Kritik Düzeltmeler

1A. Config'den crossfadeDuration Al

player-core.js satır 891

// ESKİ: crossfadeDuration: 0, // YENİ: crossfadeDuration: window.PLAYER_CONFIG?.crossfadeDuration || 7000,

1B. crossfadeEnabled Aç

player-core.js satır 888-890

// ESKİ: // 🚫 CROSSFADE DEVRE DIŞI — HLS keyLoadError çözülmeden açılamaz // E grubu hazır ama HLS key sorunu önce düzeltilmeli crossfadeEnabled: false, // YENİ: // 🎵 CROSSFADE: Şarkılar arası yumuşak ses geçişi (E grubu) crossfadeEnabled: true,

Aşama 2 Orta Seviye Düzeltmeler

2A. Event Dispatch Ekle

startCrossfade() başına + completeCrossfade() sonuna

// startCrossfade() — isCrossfading = true'dan hemen sonra: window.dispatchEvent(new CustomEvent('player:crossfadeStart', { detail: { fromSong: this.currentSong?.song_id, toSong: nextSong?.song_id, duration: this.crossfadeDuration } })); // completeCrossfade() — isCrossfading = false'dan hemen sonra: window.dispatchEvent(new CustomEvent('player:crossfadeEnd'));

2B. Howler Hata Kurtarma

createNextHowlerPlayer() satır 2711-2713

onloaderror: function(id, error) { console.error('Howler load error (crossfade):', error); // AUTO-RECOVER: Crossfade başarısız, direkt geçiş self.isCrossfading = false; self.crossfadeNextIndex = -1; if (self.howlNext) { try { self.howlNext.unload(); } catch(e) {} self.howlNext = null; } const idx = self.getNextSongIndex(); if (idx >= 0) setTimeout(() => self.playSongFromQueue(idx), 100); }

2C. Background Tab: Hemen completeCrossfade

startCrossfade() satır 2641 civarı

// Background'daysa fade yok, beklemek de gereksiz! if (isBackgroundTab) { // Hemen tamamla (setTimeout throttle riski yok) this.completeCrossfade(nextIndex, nextIsHls); } else { this.crossfadeTimeoutId = setTimeout(() => { this.crossfadeTimeoutId = null; this.completeCrossfade(nextIndex, nextIsHls); }, this.crossfadeDuration); }

2D. startProgressTrackingWithElement İyileştirmesi

timeupdate dispatch + playTracked kontrolü ekle

// startProgressTrackingWithElement() interval içine ekle: // player:timeupdate dispatch if (Math.floor(audioElement.currentTime) !== self._lastDispatchedSecond) { self._lastDispatchedSecond = Math.floor(audioElement.currentTime); window.dispatchEvent(new CustomEvent('player:timeupdate', { detail: { currentTime: Math.floor(audioElement.currentTime), isLoggedIn: self.isLoggedIn } })); } // 30s playTracked kontrolü if (!self.playTracked && audioElement.currentTime >= self.playTrackedAt && self.currentSong && self.isLoggedIn) { self.playTracked = true; self.trackSongPlay(self.currentSong.song_id); }

Aşama 3 Temizlik & Test

3A. Gereksiz const self = this; kaldır (satır 2605)

3B. Çift updatePlayerColors() çağrısını kaldır (satır 2964)

3C. ABA Test — 3 şarkılık crossfade döngüsü testi

Risk Analizi

Risk Olasılık Etki Önlem
Bellek sızıntısı (iki HLS instance) Orta Orta HlsPool destroy+fresh zaten çözüyor. Background fix ek koruma.
Audio glitch (eşzamanlı 2 ses) Düşük Düşük requestAnimationFrame tabanlı fade + volume clamp
HLS decryptdata race condition Düşük Yüksek ABR lock FRAG_BUFFERED'a kadar + key prefetch + destroy+fresh
Mobil cihaz performansı Orta Orta Düşük bellekli cihazlarda crossfade devre dışı bırakılabilir (gelecek)
Ağ bant genişliği (2x stream) Orta Düşük HLS ABR adapte olur, soft mode zaten düşük bitrate

Yapılacaklar Özet

# İş Dosya Öncelik Zorluk
1A crossfadeDuration config'den al player-core.js:891 KRİTİK Kolay
1B crossfadeEnabled = true player-core.js:890 KRİTİK Kolay
2A Event dispatch ekle player-core.js:2527, 2967 ORTA Kolay
2B Howler hata kurtarma player-core.js:2711 ORTA Kolay
2C Background tab hemen completeCrossfade player-core.js:2641 ORTA Kolay
2D progressTrackingWithElement iyileştir player-core.js:6625 ORTA Orta
3A Gereksiz self kaldır player-core.js:2605 DÜŞÜK Kolay
3B Çift updatePlayerColors kaldır player-core.js:2964 DÜŞÜK Kolay
3C ABA Test (crossfade döngüsü) - TEST -

Crossfade Tetikleme Noktaları (15 Adet)

Her tetikleme noktası crossfadeEnabled && timeRemaining <= (crossfadeDuration/1000) && timeRemaining > 0 && !isCrossfading kontrolü yapar. Bu çoklu tetikleme "son şans" güvenlik ağıdır — birden fazla yerde kontrol edilerek şarkı sonu kaçırılması engellenir.

# Kaynak Satır Path
1startProgressTracking('hls')6604-6607Ana HLS interval
2startProgressTrackingWithElement()6630-6633Crossfade sonrası HLS
3Fresh stream ontimeupdate6051-6055HLS.js fresh
4Fresh stream onended6068-6072Son şans: HLS.js
5Preloaded Safari ontimeupdate4542-4546Safari native preload
6Preloaded Safari onended4552-4554Safari native son şans
7Preloaded HLS.js ontimeupdate4731-4735Preloaded HLS.js
8Preloaded HLS.js onended4741-4743Preloaded son şans
9Preloaded BUFFER_EOS4675-4677Buffer sonu
10Fresh stream BUFFER_EOS5736-5738Fresh buffer sonu
11completeCrossfade ontimeupdate2936-2937Crossfade sonrası handler
12Howler MP3 onend5374-5377MP3 son şans
13Safari ontimeupdate6270-6274Safari native
14Safari trackEndFallback6307-6310Safari 0.5s fallback
15Safari onended6329-6331Safari son şans
24 Şubat 2026 • Muzibu.com