🚨 Muzibu HLS Timeout Hatası

Müzik çalma sisteminde 15 saniye timeout sorunu analizi ve çözüm önerileri

📅 Tarih: 22 Aralık 2025 🏷️ Kategori: Bug Fix ⚡ Öncelik: YÜKSEK

📝 Basit Anlatım (Herkes İçin)

Sorun Nedir?

Muzibu'da bir şarkı çalmaya çalıştığınızda, şarkının yüklenmesi 15 saniyeyi geçerse sistem "timeout" (zaman aşımı) hatası veriyor. Şarkı hiç başlamıyor veya çok geç başlıyor.

Neden Oluyor?

  • Sunucu, şarkı dosyasını kullanıcıya göndermeden önce "izin kontrolü" yapıyor (premium üye mi? oturum açmış mı?)
  • Bu kontroller bazen yavaş çalışıyor veya hata veriyor
  • Şarkı dosyası hazır olsa bile, izin alınamadığı için kullanıcıya gönderilemiyor
  • 15 saniye geçince sistem "artık beklemeyeceğim" diyor ve hata veriyor

Kullanıcı Deneyimi:

  • Şarkıya tıklıyorsunuz → 15 saniye bekliyor → "Hata: Şarkı yüklenemedi" yazıyor
  • Bazen otomatik olarak ikinci kez deniyor, o da başarısız olursa tamamen duruyor
  • Bazı şarkılar açılırken bazıları hiç açılmıyor (tutarsız davranış)

Neden Önemli?

Bu hata, kullanıcıların Muzibu'da müzik dinlemesini tamamen engelliyor. Premium üyelik satan bir platformda, ödeme yapan kullanıcıların müzik dinleyememesi kritik bir sorundur. Kullanıcı kaybına ve şikayetlere yol açar.

🔧 Teknik Detaylar (Geliştiriciler İçin)

📋 Console Hatası:

⚠️ HLS TIMEOUT: {
song: undefined,
timeout: '15000ms',
reason: 'HLS yüklenemedi (timeout)',
position_sec: 11
}
🔁 HLS retry with new signed URL {reason: 'timeout', attempt: 1}

🔗 HLS Stream URL:

https://muzibu.com/hls/muzibu/songs/354/playlist.m3u8 ?expires=1766426062&token=554108...&sig=81502...

✅ URL formatı doğru: /hls/muzibu/songs/{id}/{filename}

🧪 Curl Testi:

$ curl -I https://muzibu.com/hls/muzibu/songs/354/playlist.m3u8
HTTP/2 401 ❌
x-ratelimit-limit: 120
x-ratelimit-remaining: 119

❌ Sorun: 401 Unauthorized - Authentication başarısız oluyor

📁 İlgili Dosyalar:

  • 📄 public/themes/muzibu/js/player/core/player-core.js:2220 → HLS timeout logic (15 saniye)
  • 📄 Modules/Muzibu/app/Http/Controllers/Api/SongStreamController.php:547 → serveHls() method (playlist + segment serve)
  • 📄 Modules/Muzibu/Providers/MuzibuServiceProvider.php:187 → HLS route registration (throttle:120,1)
  • 📄 app/Services/SignedUrlService.php:52 → generateHlsUrl() (token + signature generation)

🔐 Authentication Akışı:

1.

Frontend → /api/muzibu/songs/{id}/stream

User session check, premium validation, HLS URL generation

2.

Backend → Signed URL oluşturur

Token: mzb_login_token, Expires: TTL, Signature: HMAC-SHA256

3.

Player → /hls/muzibu/songs/{id}/playlist.m3u8

HLS.js otomatik istek gönderir (token, expires, sig parametreleri ile)

4.

❌ serveHls() → Token validation FAIL → 401

Olası sebepler: Expired token, session missing, signature mismatch

5.

❌ HLS.js 15 saniye bekler → Timeout → Retry

Retry de başarısız olursa MP3 fallback'e geçer (veya hata verir)

🔍 Sorun Analizi

⚠️ Olası Sebepler:

1. Token Expired (En Olası)

expires=1766426062 parametresi geçmiş olabilir. URL oluşturulduğu anda TTL hesaplanıyor ama player çalarken zaman geçiyor.

// SignedUrlService.php:207-208
$durationSeconds = (int) ($song->duration ?? 0);
$ttlSeconds = max(480, min($durationSeconds + $bufferSeconds, 1800));
→ Min 8 dk, Max 30 dk TTL

2. Session/Cookie Missing

HLS.js tarayıcı tarafından paralel istek gönderir. Cookie otomatik gönderilmiyor olabilir.

// player-core.js:2292-2293
xhrSetup: function(xhr, url) {
xhr.withCredentials = false; // 🔑 CRITICAL: Disable credentials
}
→ Credentials kapalı! Cookie gönderilmez!

3. Signature Mismatch

Token oluşturulurken ve validate edilirken farklı signature hesaplanıyor olabilir.

// SongStreamController.php:566-567
$signatureBase = "/hls/muzibu/songs/{$songId}";
$expectedSig = hash_hmac('sha256', "{$signatureBase}|{$token}|{$expires}", config('app.key'));
→ Token + expires + app.key ile HMAC-SHA256

4. Session Terminated (Device Limit)

Kullanıcının oturumu başka cihazdan giriş yapılınca sonlandırılmış olabilir.

// SongStreamController.php:585-601
$sessionRow = DB::table('user_active_sessions')
->where('login_token', $token)->first();
→ Token DB'de yoksa 401 döner

🧪 Debug Önerileri:

1.
storage/logs/laravel.log dosyasını kontrol et
→ "HLS serve denied" logları ara
2.
Browser DevTools → Network tab → HLS isteklerini incele
→ Request Headers'da token parametresini kontrol et
3.
Console'da expires değerini timestamp'e çevir
new Date(1766426062 * 1000)
4.
user_active_sessions tablosunda token'ı kontrol et
SELECT * FROM user_active_sessions WHERE login_token = '554108...';

✅ Çözüm Önerileri

⚡ Hızlı Çözüm (Öncelikli):

1. TTL Süresini Artır

Şu an max 30 dakika olan TTL'i artır. Uzun şarkılarda timeout riski azalır.

// app/Services/SignedUrlService.php:54
$expiresInSeconds = 300, // 5 dakika
$expiresInSeconds = 3600, // 60 dakika ✅

2. Frontend Timeout Süresini Artır

15 saniye çok kısa. En az 30-45 saniye olmalı.

// player-core.js:2215
const hlsTimeoutMs = 15000; // 15s
const hlsTimeoutMs = 45000; // 45s ✅

3. HLS Retry Policy'yi Gevşet

HLS.js timeout retry sayısını artır. Daha fazla şans tanı.

// player-core.js:2254-2261
keyLoadPolicy: {
default: {
maxTimeToFirstByteMs: 15000,
maxTimeToFirstByteMs: 30000, // 30s ✅
maxLoadTimeMs: 30000,
maxLoadTimeMs: 60000, // 60s ✅

🔧 Orta Vadeli Çözüm:

1. URL Refresh Mekanizması Ekle

Şarkı çalarken URL expire olmadan önce otomatik yenile.

// player-core.js (zaten var! satır 1948-1959)
✅ refreshHlsUrlForCurrentSong() metodu mevcut
→ Daha erken tetiklenmeli (şu an TTL'in %20'si önce, %50 yapılabilir)

2. Daha Detaylı Error Logging

401 hatası alındığında tam sebep loglanmalı (token missing? expired? signature fail?)

// SongStreamController.php:570
Log::warning('HLS serve denied', [
'reason' => 'EXACT_REASON', // ← Ekle
'token_valid' => $token !== null,
'signature_match' => $sig === $expectedSig,
'is_expired' => Carbon::now()->timestamp > $expires,
]);

3. Graceful Degradation (MP3 Fallback)

HLS başarısız olursa otomatik MP3'e geç. Kullanıcı hiç beklemeden dinlemeye devam etsin.

// player-core.js:2228-2230 (zaten var!)
✅ MP3 fallback mevcut
→ Daha hızlı tetiklenmeli (retry sayısı azaltılmalı: 1 → 0)

🏗️ Kalıcı Çözüm (Uzun Vadeli):

1. CDN + Nginx Direct Serve

HLS dosyalarını Laravel'den değil, doğrudan Nginx'ten serve et. Authentication Nginx modülü ile yap.

  • Nginx ngx_http_auth_request_module kullan
  • Laravel sadece /auth-check endpoint'i sağla (hızlı token validation)
  • Nginx statik dosyaları direkt serve eder (PHP overhead yok)
  • CloudFlare/CloudFront gibi CDN ekle (global caching)

2. Redis Session Storage

Session'ları dosya yerine Redis'te tut. Daha hızlı lookup, timeout riski azalır.

// .env
SESSION_DRIVER=redis
CACHE_DRIVER=redis

3. Async HLS Validation

Token validation'ı asenkron yap. İlk istek hemen dosyayı serve etsin, background'da validation çalışsın.

⚠️ Güvenlik riski var, dikkatli implement edilmeli (rate limiting + monitoring şart)

📋 Aksiyon Planı (Adım Adım)

1️⃣

Debug: Log Analizi

storage/logs/laravel.log dosyasında "HLS serve denied" loglarını bul. Hangi sebeple 401 dönüyor? (token missing, expired, signature fail, session missing)

Tahmini süre: 10 dakika
2️⃣

Quick Fix: Timeout Artır

Frontend timeout: 15s → 45s
Backend TTL: 300s → 3600s (60 dakika)
HLS.js maxLoadTimeMs: 30s → 60s

Tahmini süre: 15 dakika
3️⃣

Test: Gerçek Kullanıcı Senaryosu

Premium üye hesabı ile giriş yap → Şarkı çal → Console'u izle → Hata devam ediyorsa log'a bak

Tahmini süre: 20 dakika
4️⃣

İyileştir: Error Logging

SongStreamController::serveHls() metoduna detaylı log ekle. Hangi validation'da fail oluyor göster.

Tahmini süre: 30 dakika
5️⃣

Kalıcı: URL Refresh Optimize

refreshHlsUrlForCurrentSong() metodunu daha erken tetikle (%20 → %50). Expire olmadan yenile.

Tahmini süre: 45 dakika
6️⃣

Monitoring: Production İzleme

Production'da 1 hafta izle. Timeout hataları azaldı mı? Kullanıcı şikayeti var mı?

Tahmini süre: 1 hafta

🤖 Bu rapor Claude AI tarafından oluşturulmuştur

📅 Oluşturulma Tarihi: 22 Aralık 2025