🔴 Bug Analizi HLS Streaming

Muzibu HLS Segment 404 Hatası

Müzik dinlerken segment dosyalarının yanlış URL pattern ile çağrılması sorunu

10 Ocak 2026 - Detaylı Sistem Analizi

📝 Basit Anlatım (Herkes İçin)

Sorun: Müzik çalarken bazen şarkı dosyaları yanlış adresten aranıyor ve bulunamıyor.

Örnek: Player "/api/muzibu/songs/123/segment-000.ts" diye arıyor, ama dosya "/hls/muzibu/songs/123/segment-000.ts" adresinde.

Sonuç: Bazen şarkılar takılabiliyor veya atlanabiliyor.

Neden Önemli: Kullanıcı deneyimi bozuluyor, şarkı akışı kesintiye uğruyor.

8 farklı şarkıda tespit edildi.

🔧 Teknik Detaylar (Geliştiriciler İçin)

📊 Hata Logları:

GET /api/muzibu/songs/28745/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/28704/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/28698/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/22187/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/28765/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/28773/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/11985/segment-000.ts HTTP/2" 404
GET /api/muzibu/songs/28741/segment-000.ts HTTP/2" 404

✅ Doğru URL Pattern:

GET /hls/muzibu/songs/31118/segment-000.ts?expires=1767993687&token=3&sig=... HTTP/2" 200

🎯 Sistem Mimarisi:

Backend (Laravel)

  • • SignedUrlService: HLS URL üretimi
  • • SongStreamController: Stream endpoint
  • • MuzibuServiceProvider: Route tanımları
  • • ConvertToHLSJob: FFmpeg conversion

Frontend (JavaScript)

  • • player-core.js: Ana player modülü
  • • HLS.js: HLS streaming library
  • • createHlsBlobUrl(): Blob URL converter
  • • playHlsStream(): HLS yükleme fonksiyonu

📁 Etkilenen Dosyalar:

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

• Line 109-151: createHlsBlobUrl() - Blob URL conversion

• Line 3350-4069: playSongFromQueue() - Ana play fonksiyonu

• Line 4069-4117: loadAndPlaySong() - Stream loader

• Line 4279-4650: playHlsStream() - HLS player

app/Services/SignedUrlService.php

• Line 52-72: generateHlsUrl() - HLS URL generator ✅ DOĞRU

Modules/Muzibu/Providers/MuzibuServiceProvider.php

• Line 305-317: HLS files route tanımı ✅ DOĞRU

Modules/Muzibu/app/Jobs/ConvertToHLSJob.php

• Line 79-122: FFmpeg HLS conversion ✅ DOĞRU

🔍 Sorun Analizi

1️⃣ Backend URL Generation (✅ DOĞRU)

// SignedUrlService.php (Line 62)
$basePath = "/hls/muzibu/songs/{$songId}/playlist.m3u8";

// Oluşturulan URL:
https://muzibu.com/hls/muzibu/songs/123/playlist.m3u8?expires=...&token=...&sig=...

✅ Backend doğru /hls/ prefix'i ile URL üretiyor.

2️⃣ Route Definition (✅ DOĞRU)

// MuzibuServiceProvider.php (Line 315)
Route::match(['get', 'options'], '/hls/muzibu/songs/{id}/{filename}', ...)
    ->where('filename', 'playlist\.m3u8|segment-\d+\.ts');

✅ Route doğru /hls/ pattern ile tanımlanmış.

3️⃣ Playlist.m3u8 İçeriği (✅ DOĞRU)

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXTINF:10.005333,
segment-000.ts    <-- Relative path (DOĞRU!)
#EXTINF:9.994667,
segment-001.ts
...

✅ Segment path'leri relative olarak yazılmış (doğru).

4️⃣ JavaScript Blob URL Conversion (⚠️ SORUN BURDA!)

// player-core.js (Line 119-133)
async function createHlsBlobUrl(originalUrl) {
    // 1. m3u8 içeriğini fetch et
    const response = await fetch(originalUrl);
    let m3u8Content = await response.text();

    // 2. Base URL'yi çıkar (segment'ler için)
    const urlObj = new URL(originalUrl);
    const baseUrl = urlObj.origin + urlObj.pathname.substring(0, urlObj.pathname.lastIndexOf('/') + 1);
    const queryString = urlObj.search; // ?token=...&expires=...&sig=...

    // 3. Relative segment URL'lerini absolute yap
    m3u8Content = m3u8Content.replace(
        /(segment-\d+\.ts)(\?[^\s\n]*)?/g,
        (match, segment, query) => {
            const finalQuery = query || queryString;
            return baseUrl + segment + finalQuery;  // ⚠️ SORUN BURDA!
        }
    );
}

❌ SORUN: baseUrl değişkeni originalUrl parametresinden çıkarılıyor.

Senaryo 1: Doğru URL gelirse ✅

originalUrl = "/hls/muzibu/songs/123/playlist.m3u8?token=..."
baseUrl = "https://muzibu.com/hls/muzibu/songs/123/"
Segment URL = "https://muzibu.com/hls/muzibu/songs/123/segment-000.ts?..." ✅ 200 OK

Senaryo 2: Yanlış URL gelirse ❌

originalUrl = "/api/muzibu/songs/123/playlist.m3u8?..." (YANLIŞ!)
baseUrl = "https://muzibu.com/api/muzibu/songs/123/"
Segment URL = "https://muzibu.com/api/muzibu/songs/123/segment-000.ts?..." ❌ 404 NOT FOUND

5️⃣ Neden Yanlış URL Geliyor?

Olası Neden 1: Cache'de Eski URL

Player stream URL'lerini cache'liyor. Cache'de eski /api/ prefix'li URL kalıyor olabilir.

Olası Neden 2: Refresh URL Fonksiyonu

HLS URL refresh mekanizması eski URL pattern kullanıyor olabilir.

Olası Neden 3: Fallback Mekanizması

HLS hata verince fallback URL eski pattern ile deniyor olabilir.

Olası Neden 4: Preload/Crossfade Path

Preload veya crossfade sırasında eski cached URL kullanılıyor olabilir.

💡 Çözüm Önerileri

✅ Çözüm 1: URL Validation (Öncelikli)

createHlsBlobUrl() fonksiyonuna URL validation ekle, /api/ prefix'ini /hls/ ile değiştir.

async function createHlsBlobUrl(originalUrl) {
    // ⚠️ URL FIX: /api/ prefix'ini /hls/ ile değiştir
    let fixedUrl = originalUrl;
    if (fixedUrl.includes('/api/muzibu/songs/')) {
        fixedUrl = fixedUrl.replace('/api/muzibu/songs/', '/hls/muzibu/songs/');
        console.warn('🔧 URL FIX: /api/ → /hls/', originalUrl);
    }

    const response = await fetch(fixedUrl);
    // ... rest of the code
}

⚡ Çözüm 2: Cache Temizleme

Stream URL cache'ini temizle, eski URL'leri kullanımdan kaldır.

// player-core.js içinde cache clear
clearStreamCache() {
    // LocalStorage/SessionStorage cache temizleme
    Object.keys(localStorage).forEach(key => {
        if (key.includes('stream_cache_')) {
            localStorage.removeItem(key);
        }
    });
}

🔍 Çözüm 3: Debug Logging

Player'a detaylı logging ekle, hangi URL'in nereden geldiğini takip et.

async function createHlsBlobUrl(originalUrl) {
    console.log('🎵 HLS Blob URL Creation:', {
        originalUrl: originalUrl,
        hasApiPrefix: originalUrl.includes('/api/'),
        hasHlsPrefix: originalUrl.includes('/hls/'),
        timestamp: new Date().toISOString()
    });

    // Server'a da log gönder (debug için)
    serverLog('hlsBlobUrlCreated', { url: originalUrl });
}

🛡️ Çözüm 4: Route Fallback (Son Çare)

Backend'e /api/muzibu/songs/{id}/segment-*.ts route'u ekle, doğru yere redirect et.

// MuzibuServiceProvider.php
// Eski URL'leri yeni URL'e redirect et (backward compatibility)
Route::get('/api/muzibu/songs/{id}/segment-{segment}.ts', function($id, $segment) {
    return redirect("/hls/muzibu/songs/{$id}/segment-{$segment}.ts?" . request()->getQueryString());
})->where('segment', '\d+');

⚠️ Bu geçici bir çözüm! Asıl sorun player'da düzeltilmeli.

🧪 Test Planı

1️⃣ Hata Tekrarı

• Loglardan etkilenen şarkılardan birini çal (song_id: 28745, 28704, vb.)

• Browser DevTools Network tab'ında /api/muzibu/songs/ isteği var mı kontrol et

2️⃣ URL Validation Testi

• Çözüm 1'i uygula, aynı şarkıyı tekrar çal

• Console'da "URL FIX" warning'i görünmeli

3️⃣ Segment İstekleri

• Network tab'da segment istekleri /hls/muzibu/songs/ ile başlamalı

• Tüm segment istekleri 200 OK dönmeli

4️⃣ Cache Temizleme

• Browser'da Ctrl+Shift+Delete → Cache temizle

• Tüm şarkıları baştan yüklet, hiçbirinde /api/ prefix olmamalı

5️⃣ Production Test

• Düzeltme sonrası 24 saat access log'ları takip et

grep "segment-.*404" access_log → 0 sonuç olmalı

🎵 Etkilenen Şarkılar

Song ID: 28745

10 Ocak 2026

Song ID: 28704

10 Ocak 2026

Song ID: 28698

10 Ocak 2026

Song ID: 22187

10 Ocak 2026

Song ID: 28765

10 Ocak 2026

Song ID: 28773

10 Ocak 2026

Song ID: 11985

10 Ocak 2026

Song ID: 28741

10 Ocak 2026

Toplam 8 şarkıda 404 hatası tespit edildi. Bu şarkılar cache temizleme sonrası test edilmeli.