✅ Muzibu Playback Fixes

Tüm console hatalarını çözdük, şarkılar artık çalıyor!
📅 5 Aralık 2025 🎯 Tenant: muzibu.com (1001) 👤 Şarkı çalma sistemini tamamen düzelttik

🎉 Sonuç

Şarkı çalma sistemi tamamen çalışır hale geldi!

✅ HLS chunk token authorization düzeltildi

✅ Thumbnail görselleri düzeltildi

✅ Cover image priority logic eklendi (song > album > placeholder)

✅ Tenant-aware storage path problemi çözüldü

✅ HLS.js query string preservation uygulandı

🐛 Çözülen Hatalar

1

HLS Chunks 404 Error ÇÖZÜLDÜ

Hata: GET https://muzibu.com/api/muzibu/songs/319/chunk_000.ts 404

Sebep: HLS.js, playlist.m3u8 içindeki chunk URL'lerinden query string'leri (?token=...) ve /chunk/ path segment'ini kaldırıyordu

Çözüm:

  • HLS.js'ye custom xhrSetup fonksiyonu eklendi
  • LEVEL_LOADED event'i ile chunk URL'leri token'larıyla birlikte saklandı
  • XHR request'leri sırasında token'lı URL'ler geri yüklendi
2

Tenant Storage Path Hatası ÇÖZÜLDÜ

Hata: Chunk dosyaları storage/app/public/ yerine storage/tenant1001/app/public/ konumunda

Sebep: PlaylistGeneratorService ve SongController tenant-aware storage path kullanmıyordu

Çözüm:

  • tenant('id') kontrolü eklendi
  • Path logic: storage_path("../tenant{$tenantId}/app/public/{$path}")
  • Her iki dosyada da (PlaylistGeneratorService.php, SongController.php) uygulandı
3

Chunk Pattern Uyumsuzluğu ÇÖZÜLDÜ

Hata: FFmpeg chunk_XXX.ts oluştururken, kod segment-XXX.ts arıyordu

Çözüm:

  • Regex pattern güncellendi: /((?:segment-|chunk_)\d+\.ts)/
  • Chunk detection logic: str_contains($line, 'chunk_') eklendi
  • Artık her iki format da destekleniyor (segment-XXX.ts ve chunk_XXX.ts)
4

Thumbnail Route Eksik ÇÖZÜLDÜ

Hata: GET /thumb/2054/56/56 404

Sebep: Thumbmaker route yoktu, frontend /thumb/{mediaId}/{width}/{height} formatında istek yapıyordu

Çözüm:

  • routes/web.php'ye /thumbmaker query string route eklendi
  • /thumb/{mediaId}/{width}/{height} shortcut route eklendi (thumbmaker'a redirect)
  • Media::findOrFail() ile doğrulama yapılıyor
5

Cover Image Logic ÇÖZÜLDÜ

İstek: Şarkının kendi görseli öncelikli, yoksa albüm görseli gösterilsin

Çözüm:

  • player-core.js'ye cover priority logic eklendi
  • Öncelik: song.media_id > album.media_id > placeholder
  • Fallback: /placeholder-album.jpg
6

TypeError: this.pause is not a function ÇÖZÜLDÜ

Hata: Guest preview bittiğinde this.pause() çağrısı hataya düşüyordu

Çözüm:

  • Howler.js için: this.howl.pause()
  • HLS.js için: audio.pause()
  • Conditional pause logic eklendi (engine detection)

🔧 Teknik Detaylar

🔐 HLS Token Authorization

✅ ChunkTokenService ile signed URL generation

✅ Token içeriği: song_id, chunk_name, user_id, is_premium, expires_at

✅ Token TTL: 15 dakika (900 saniye)

✅ HMAC-SHA256 signature ile güvenlik

✅ Guest kullanıcılar: İlk 4 chunk erişimi (30 saniye preview)

✅ Premium kullanıcılar: Tüm chunk'lara sınırsız erişim

📁 Multi-Tenant Storage

✅ Central: storage/app/public/

✅ Tenant 1001: storage/tenant1001/app/public/

✅ HLS chunks: muzibu/hls/{song_id}/

✅ Chunk format: chunk_000.ts to chunk_059.ts

✅ Playlist: playlist.m3u8

✅ Encryption: AES-128 CBC mode

⚙️ HLS.js Configuration

enableWorker: true (web worker kullan)

lowLatencyMode: false

✅ Custom xhrSetup (token preservation)

LEVEL_LOADED event listener (chunk URL caching)

✅ Query string preservation logic

✅ Fallback to MP3 on HLS error

🎵 Player Architecture

✅ Dual Engine: HLS.js (primary) + Howler.js (fallback)

✅ HLS Priority: Önce HLS dene, başarısızsa MP3

✅ Guest Preview: 30 saniye (4 chunk × 7.5s avg)

✅ Fade-in/Fade-out: 1000ms smooth transition

✅ SPA Navigation: Müzik kesintisiz devam eder

✅ Alpine.js reactive state management

📝 Değiştirilen Dosyalar

1. routes/web.php

Thumbmaker route'ları eklendi (query string + path-based)

2. app/Services/Muzibu/PlaylistGeneratorService.php

Chunk pattern fix + tenant storage path + signed URL generation

3. Modules/Muzibu/app/Http/Controllers/Api/SongController.php

Tenant storage path fix (serveChunk method)

4. public/themes/muzibu/js/player/core/player-core.js

HLS.js xhrSetup + LEVEL_LOADED event + pause fix + cover priority logic

🧪 Test Senaryoları

✅ Test 1: Guest Kullanıcı Preview

Logout olun → Herhangi bir şarkı çalın → 30 saniye sonra otomatik durmalı

✅ Test 2: Premium Kullanıcı Tam Çalma

Premium hesapla login → Şarkı baştan sona kesintisiz çalmalı

✅ Test 3: Thumbnail Görüntüleme

Player'da şarkı görseli doğru görünmeli (şarkının kendi görseli veya albüm görseli)

✅ Test 4: SPA Navigation

Şarkı çalarken sayfa değiştir → Müzik kesintisiz devam etmeli

✅ Test 5: HLS Fallback

HLS conversion olmamış şarkı → Otomatik MP3'e fallback yapmalı

🔧 Bonus Fix: Throttle Middleware

Hata: Call to undefined method Symfony\Component\HttpFoundation\BinaryFileResponse::header()

Sebep: ThrottleByUserType middleware, BinaryFileResponse üzerinde ->header() method çağırıyordu

Çözüm: ->headers->set() kullanılacak şekilde güncellendi

// ❌ BEFORE:
return $response
    ->header('X-RateLimit-Limit', $maxAttempts)
    ->header('X-RateLimit-Remaining', $remainingAttempts);

// ✅ AFTER:
$response->headers->set('X-RateLimit-Limit', $maxAttempts);
$response->headers->set('X-RateLimit-Remaining', $remainingAttempts);
return $response;