Değişecek Dosyalar
# Ana Dosya (Tüm değişiklikler burada)
public/themes/muzibu/js/player/core/player-core.js
# Opsiyonel (Ayar eklenirse)
resources/views/themes/muzibu/components/player.blade.php
Mevcut Sistem (Gapless)
1. preloadNextSong() - Satır ~6800
Sonraki şarkıyı önceden yükler
_preloadedNext = {
songId: nextSong.song_id,
song: nextSong,
hls: hlsPreload,
audioId: audioId,
ready: false
}
2. onTrackEnded() - Satır ~5100
Şarkı bitince çağrılır, sonrakine geçer
audio.onended = () => {
this.onTrackEnded();
}
3. playPreloadedNext() - Satır ~6900
Preload edilmiş şarkıyı başlatır
if (this._preloadedNext && this._preloadedNext.ready) {
// Hemen başlat
this._preloadedNext.audio.play();
}
Yapılacak Değişiklikler
AudioContext + GainNode Ekle
Her audio element için Web Audio API bağlantısı
// player-core.js başına ekle
_audioContext: null,
_gainNodes: new Map(), // audioId -> gainNode
initAudioContext() {
if (!this._audioContext) {
this._audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
return this._audioContext;
}
connectToGainNode(audio, audioId) {
const ctx = this.initAudioContext();
const source = ctx.createMediaElementSource(audio);
const gainNode = ctx.createGain();
source.connect(gainNode);
gainNode.connect(ctx.destination);
this._gainNodes.set(audioId, gainNode);
return gainNode;
}
Crossfade Ayarları
Kullanıcı tercihi için ayarlar
// Ayarlar _crossfadeEnabled: true, // Crossfade açık/kapalı _crossfadeDuration: 4, // Saniye cinsinden (1-10) _crossfadeInProgress: false, // Çakışma önleme
timeupdate Event Değiştir
Şarkı bitmeden X saniye önce crossfade başlat
// Mevcut timeupdate handler'a ekle
audio.addEventListener('timeupdate', () => {
// ... mevcut kod ...
// CROSSFADE TETİKLEME
if (this._crossfadeEnabled && !this._crossfadeInProgress) {
const remaining = audio.duration - audio.currentTime;
if (remaining <= this._crossfadeDuration && remaining > 0) {
this.startCrossfade();
}
}
});
startCrossfade() Fonksiyonu
Ana crossfade mantığı
startCrossfade() {
if (!this._preloadedNext || !this._preloadedNext.ready) {
return; // Preload hazır değil, gapless devam
}
this._crossfadeInProgress = true;
const duration = this._crossfadeDuration;
const ctx = this._audioContext;
const now = ctx.currentTime;
// Mevcut şarkı: Fade Out
const currentGain = this._gainNodes.get(this.currentAudioId);
currentGain.gain.setValueAtTime(1, now);
currentGain.gain.linearRampToValueAtTime(0, now + duration);
// Sonraki şarkı: Fade In
const nextGain = this._gainNodes.get(this._preloadedNext.audioId);
nextGain.gain.setValueAtTime(0, now);
nextGain.gain.linearRampToValueAtTime(1, now + duration);
// Sonraki şarkıyı başlat
this._preloadedNext.audio.play();
// Crossfade bitince temizlik
setTimeout(() => {
this.finishCrossfade();
}, duration * 1000);
}
finishCrossfade() Fonksiyonu
Crossfade bitince temizlik
finishCrossfade() {
// Eski şarkıyı durdur
this.currentAudio.pause();
// State güncelle
this.currentSong = this._preloadedNext.song;
this.currentAudio = this._preloadedNext.audio;
this.currentAudioId = this._preloadedNext.audioId;
this.hls = this._preloadedNext.hls;
// Preload state temizle
this._preloadedNext = null;
this._crossfadeInProgress = false;
// Sonraki şarkıyı preload et
this.preloadNextSong();
}
Fallback: Gapless
Crossfade çalışmazsa otomatik gapless
// Başlangıçta kontrol et
canUseCrossfade() {
// Web Audio API var mı?
if (!(window.AudioContext || window.webkitAudioContext)) {
return false;
}
// GainNode test
try {
const ctx = new (window.AudioContext || window.webkitAudioContext)();
ctx.createGain();
ctx.close();
return true;
} catch (e) {
return false;
}
}
// init() içinde
if (!this.canUseCrossfade()) {
this._crossfadeEnabled = false;
console.log('Crossfade desteklenmiyor, gapless kullanılacak');
}
Dikkat: Preload Buffer
Crossfade için preload buffer'ı biraz artırmak gerekebilir:
# Mevcut (gapless için yeterli)
maxBufferLength: 20 // 2 segment
# Crossfade için önerilen
maxBufferLength: 40 // 4 segment
# Neden? Crossfade başladığında sonraki şarkı
# en az 4-5 saniye buffer'a sahip olmalı
Değişiklik Özeti
| # | Değişiklik | Konum | Zorluk |
|---|---|---|---|
| 1 | AudioContext + GainNode | Dosya başı | Kolay |
| 2 | Crossfade ayarları | Dosya başı | Kolay |
| 3 | timeupdate tetikleme | ~satır 5000 | Orta |
| 4 | startCrossfade() | Yeni fonksiyon | Orta |
| 5 | finishCrossfade() | Yeni fonksiyon | Orta |
| 6 | Fallback kontrolü | init() | Kolay |
| 7 | Preload buffer artır | ~satır 6830 | Kolay |
Sonuç
- 1 dosya değişecek: player-core.js
- ~100-150 satır kod eklenecek
- Zorluk: Orta (mevcut altyapı hazır)
- Risk: Düşük (fallback gapless var)