HLS 4 Saniye Production v3

HLS 4-Saniye Standardizasyon

Production Deployment Rehberi + Claude Prompt

Basit Anlatim Teknik Detay Production Adimlari Dogrulama Hata Yonetimi Claude Prompt Test Sonuclari

📝 Basit Anlatim (Herkes Icin)

Muzibu'daki sarkilar dinlenirken kucuk parcalar halinde (segment) yukleniyor. Onceden bu parcalar 6 saniyeydi, simdi tum kalite seviyelerinde 4 saniye olarak standardize edildi.

Onceki Durum

  • High kalite: 6 saniye segment
  • Diger kaliteler: 4 saniye segment
  • Tutarsiz FFmpeg parametreleri
  • Eski olu kodlar mevcut

Simdiki Durum

  • Tum kaliteler: 4 saniye segment
  • Standart FFmpeg parametreleri
  • Olu kodlar temizlendi
  • Production'a hazir

Neden Onemli? 4 saniye segment, Apple HLS standardina uygun ve tum varyantlar arasinda tutarlilik sagliyor. Bu sayede adaptive bitrate (otomatik kalite gecisi) daha yumusak calisiyor.

🚨 mztest'te Tespit Edilen Sorun: OPcache

Kod degisiklikleri yapilip cache temizlendikten sonra, yeni eklenen 83 sarki hala eski formatla uretildi:

Eski Format (Horizon eski kodu kullanmis)

  • ❌ 10sn segment (4sn olmasi lazim)
  • ❌ VOD tipi yok
  • ❌ Varyant yok (ultralow/low/mid)
  • ❌ MP3 128k yok
  • ❌ master.m3u8 yok
  • ❌ enc.keyinfo storage URL (403 hatasi)

Dogru Format (opcache temizlendikten sonra)

  • ✅ 4sn segment
  • ✅ VOD tipi
  • ✅ 4 varyant (ultralow + low + mid + high)
  • ✅ MP3 128k
  • ✅ master.m3u8 (4 varyant)
  • ✅ enc.keyinfo /hls-key/ URI

Cozum: curl -s -k https://domain.com/opcache-reset.php calistir. Horizon worker'lari yeni kodu gorecek. Production'da ADIM 1'deki opcache-reset adimini ATLAMA!

🔧 Teknik Detaylar (Gelistiriciler Icin)

Yapilan Kod Degisiklikleri

# Dosya Degisiklik
1 ConvertToHLSJob.php FFmpeg'e -profile:a aac_low -ar 48000 -ac 2 eklendi
2a HLSService.php:125 $targetBitrate undefined bug fix
2b HLSService.php:158 buildFFmpegCommand() internal helper olarak isaretlendi
3 AddHlsVariantsCommand.php --re-encode-high flag'i eklendi (high'i 4sn ile yeniden olusturur)
4 ConvertSongToHLS.php Silindi (olu kod)
5 routes/web.php /stream/key/ eski route kaldirildi
6 hls-streaming.blade.php Dokumantasyon guncellendi

Her Sarki Dosya Yapisi

storage/tenant{id}/app/public/muzibu/hls/{song_id}/
├── enc.bin              ← 16 byte AES-128 key (binary)
├── enc.keyinfo          ← 3 satir: URI + path + IV
├── master.m3u8          ← 4 varyant referansi
├── playlist.m3u8        ← high kalite (4sn, VOD, encrypted)
├── segment-*.ts         ← high segment'ler
├── ultralow/            ← 32kbps, mono, 22050Hz
├── low/                 ← 64kbps, mono, 22050Hz
└── mid/                 ← 128kbps, stereo, 44100Hz

storage/tenant{id}/app/public/muzibu/songs/mp3_128/
└── {song_id}.mp3        ← 128kbps MP3 fallback

🚀 Production Deployment (~30K Sarki)

Ana sunucuda adim adim yapilacaklar. Sirasini BOZMA!

1

Kodu Cek + Cache Temizle

cd /var/www/vhosts/muzibu.com/httpdocs

# Kodu cek
git pull origin main

# Cache temizle (route degisti, eski /stream/key/ kaldirildi)
php artisan cache:clear
php artisan route:clear
php artisan config:clear
php artisan view:clear
composer dump-autoload

# KRITIK: OPcache temizle (yoksa Horizon eski kodu calistirir!)
curl -s -k https://muzibu.com/opcache-reset.php

# Route ve config yeniden cache'le
php artisan config:cache
php artisan route:cache

KRITIK UYARI: opcache-reset.php MUTLAKA calistirilmali! mztest'te bu adim atlaninca Horizon eski ConvertToHLSJob kodunu kullanmaya devam etti ve yeni eklenen 83 sarki 10sn segment + VOD'suz + varyant'siz olarak uretildi. Opcache temizlenmezse ayni hata production'da da olur.

Neden? PHP OPcache, dosya degisse bile eski bytecode'u RAM'de tutar. Horizon worker'lari surekli calisan process'ler oldugu icin yeni kodu ancak opcache temizlenince gorur.

2

Dry-Run (Sadece Say, Dokunma)

php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="dry-run=1"

Beklenen cikti: "Toplam HLS: ~30000, Islenecek: ~30000". Hicbir dosyaya dokunmaz, sadece sayar.

3

Kucuk Batch Test (10 Sarki)

php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="limit=10"

Beklenen: "10 basarili, 0 basarisiz". ~3-5 dakika surer.

4

Test Sonucunu Dogrula

HLS_BASE="storage/tenant1001/app/public/muzibu/hls"

# Ilk 10 sarkinin hepsini kontrol et
GOOD=0; BAD=0; COUNT=0
for DIR in $(ls -d $HLS_BASE/*/ | head -10); do
    [ ! -f "$DIR/master.m3u8" ] && continue
    COUNT=$((COUNT + 1))

    # Segment suresi (4.xxx olmali, 6.xxx olmamali)
    MAX=$(grep '#EXTINF:' "$DIR/playlist.m3u8" | sed 's/#EXTINF://' | sed 's/,.*//' | sort -rn | head -1)
    INT=$(echo "$MAX" | cut -d. -f1)

    # 4 varyant olmali
    HAS_ALL=1
    for V in ultralow low mid; do
        [ ! -f "$DIR/$V/playlist.m3u8" ] && HAS_ALL=0
    done

    # VOD olmali
    HAS_VOD=0
    grep -q '#EXT-X-PLAYLIST-TYPE:VOD' "$DIR/playlist.m3u8" && HAS_VOD=1

    if [ "$INT" -le 4 ] && [ "$HAS_ALL" -eq 1 ] && [ "$HAS_VOD" -eq 1 ]; then
        GOOD=$((GOOD + 1))
    else
        BAD=$((BAD + 1))
        echo "SORUN: $(basename $DIR) max=$MAX varyant=$HAS_ALL vod=$HAS_VOD"
    fi
done
echo "Kontrol: $COUNT sarki, $GOOD OK, $BAD SORUNLU"

Beklenen: "10 OK, 0 SORUNLU". Sorun varsa DURMA, once analiz et.

5

Tam Re-encode (3 Paralel Terminal)

~7 SAAT

3 ayri terminal ac. Her birinde farkli offset ile calistir. screen veya tmux kullan ki terminal kapansa da devam etsin!

TERMINAL 1 — Sarki 1 - 10.000

screen -S hls-batch1
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="limit=10000" \
    --option="offset=0"

TERMINAL 2 — Sarki 10.001 - 20.000

screen -S hls-batch2
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="limit=10000" \
    --option="offset=10000"

TERMINAL 3 — Sarki 20.001 - 30.000

screen -S hls-batch3
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="limit=10000" \
    --option="offset=20000"

Tahmini Sure: ~30K sarki x ~20sn/sarki = ~7 saat (3 paralel). mztest'te 66 sarki 22 dakikada bitti.

screen kullanimi: Ctrl+A D = ayir (arka planda calisir), screen -r hls-batch1 = geri baglan

6

Son Dogrulama (3 Batch Bittikten Sonra)

HLS_BASE="storage/tenant1001/app/public/muzibu/hls"

echo "=== GENEL DURUM ==="
echo "Toplam HLS klasoru: $(ls -d $HLS_BASE/*/ 2>/dev/null | wc -l)"
echo "master.m3u8 olan: $(ls $HLS_BASE/*/master.m3u8 2>/dev/null | wc -l)"
echo "MP3 128k: $(ls storage/tenant1001/app/public/muzibu/songs/mp3_128/*.mp3 2>/dev/null | wc -l)"

echo ""
echo "=== RASTGELE 20 SARKI KONTROL ==="
GOOD=0; BAD=0
for DIR in $(ls -d $HLS_BASE/*/ | shuf | head -20); do
    [ ! -f "$DIR/master.m3u8" ] && continue
    MAX=$(grep '#EXTINF:' "$DIR/playlist.m3u8" | sed 's/#EXTINF://' | sed 's/,.*//' | sort -rn | head -1)
    INT=$(echo "$MAX" | cut -d. -f1)
    HAS_ALL=1
    for V in ultralow low mid; do
        [ ! -f "$DIR/$V/playlist.m3u8" ] && HAS_ALL=0
    done
    if [ "$INT" -le 4 ] && [ "$HAS_ALL" -eq 1 ]; then
        GOOD=$((GOOD + 1))
    else
        BAD=$((BAD + 1))
        echo "SORUN: $(basename $DIR)"
    fi
done
echo "Sonuc: $GOOD OK, $BAD SORUNLU"
7

Final Cache Temizligi

php artisan cache:clear
php artisan view:clear
php artisan responsecache:clear

Dogrulama Kontrol Listesi

Kontrol Beklenen Nasil Kontrol?
High segment suresi ~4.0xx sn grep '#EXTINF:' playlist.m3u8 | head -3
master.m3u8 varyant sayisi 4 (ultralow + low + mid + original) cat master.m3u8
Varyant klasorleri ultralow/ + low/ + mid/ mevcut ls -d */
enc.keyinfo URI /hls-key/muzibu/songs/{id} head -1 enc.keyinfo
Playlist tipi #EXT-X-PLAYLIST-TYPE:VOD grep PLAYLIST-TYPE playlist.m3u8
MP3 128k dosyasi mp3_128/{song_id}.mp3 mevcut ls songs/mp3_128/ | wc -l

⚠️ Hata Yonetimi + Guvenlik Garantileri

Durum Ne Olur? Risk
MP3 dosyasi yok Atlar, failed sayar, devam eder Yok
HLS klasoru yok Atlar Yok
FFmpeg hata Log'lar, failed sayar, devam eder Yok
enc.keyinfo yok re-encode atlar, variant eklemeye devam Yok
Zaten variant var Atlar (uzerine yazmaz) Yok
Disk dolu FFmpeg hata verir, log'lanir, devam eder Orta
Terminal kapanirsa screen kullan! Orta
Islem ortasinda durur Ayni komutu tekrar calistir, mevcut olanlari atlar Yok

Onemli Guvenlik Notu

  • • Orijinal MP3'ler HICBIR ZAMAN silinmez veya degistirilmez
  • • enc.bin (encryption key) korunur, sadece segment'ler yeniden uretilir
  • • Islem sirasinda sarkilar calismaya devam eder (mevcut segment'ler silinip yerine yenileri yazilir)
  • • Komut hatada durmaz, devam eder ve sonunda rapor verir

Rollback Plani

En kotu senaryoda geri almak icin:

  1. Kod degisikliklerini geri al: git checkout -- .
  2. Orijinal MP3'ler her zaman mevcut
  3. Yeniden HLS donusumu icin: ConvertToHLSJob zaten 4sn + varyant uretiyor
  4. Tek sarki test: --option="song=12345" ile belirli sarki test et

🤖 Claude Prompt (Production Sunucuya Kopyala-Yapistir)

Asagidaki prompt'u production sunucudaki Claude'a ver. Tum islemleri otomatik yapacak.

KOPYALA
Muzibu HLS sisteminde 4-saniye standardizasyon yapildi. Test sunucusunda (mztest) 66 sarki basariyla tamamlandi. Simdi production sunucuda (~30K sarki) ayni islemi yapman gerekiyor.

## Ne Yapildi (mztest'te)?
1. ConvertToHLSJob.php: FFmpeg'e -profile:a aac_low -ar 48000 -ac 2 eklendi
2. HLSService.php: $targetBitrate undefined bug fix
3. AddHlsVariantsCommand.php: --re-encode-high flag'i eklendi
4. ConvertSongToHLS.php silindi (olu kod)
5. /stream/key/ eski route kaldirildi
6. hls-streaming.blade.php dokumantasyonu guncellendi

## Senin Yapacaklarin (SIRAYLA!)

### 1. Kodu cek + opcache temizle
```bash
cd /var/www/vhosts/muzibu.com/httpdocs
git pull origin main

# Cache temizle
php artisan cache:clear && php artisan route:clear && php artisan config:clear && php artisan view:clear
composer dump-autoload

# KRITIK: OPcache temizle (Horizon eski kodu calistirmasin!)
curl -s -k https://muzibu.com/opcache-reset.php

# Route ve config yeniden cache'le
php artisan config:cache && php artisan route:cache
```
UYARI: opcache-reset ATLANIRSA Horizon eski kodu kullanmaya devam eder ve yeni sarkilar 10sn segment ile uretilir!

### 2. Dry-run (sadece say, hicbir seye dokunma)
```bash
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="dry-run=1"
```
Beklenen: "Toplam HLS: ~30000, Islenecek: ~30000"

### 3. 10 sarki ile test
```bash
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" \
    --option="mp3-128=1" \
    --option="refresh-master=1" \
    --option="re-encode-high=1" \
    --option="limit=10"
```
Beklenen: "10 basarili, 0 basarisiz" (~3-5 dk)

### 4. Test sonucunu dogrula
Ilk 10 sarkiyi kontrol et:
- playlist.m3u8'deki #EXTINF degerleri ~4.0xx olmali (6.xxx OLMAMALI)
- master.m3u8'de 4 varyant olmali (ultralow + low + mid + original)
- enc.keyinfo URI /hls-key/ ile baslamali
- VOD tipi olmali
- Sorun varsa DURMA, analiz et

### 5. Tam re-encode (3 paralel terminal, screen kullan!)
```bash
# Terminal 1
screen -S hls-batch1
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" --option="mp3-128=1" \
    --option="refresh-master=1" --option="re-encode-high=1" \
    --option="limit=10000" --option="offset=0"

# Terminal 2
screen -S hls-batch2
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" --option="mp3-128=1" \
    --option="refresh-master=1" --option="re-encode-high=1" \
    --option="limit=10000" --option="offset=10000"

# Terminal 3
screen -S hls-batch3
php artisan tenants:run hls:add-variants --tenants=1001 \
    --option="quality=all" --option="mp3-128=1" \
    --option="refresh-master=1" --option="re-encode-high=1" \
    --option="limit=10000" --option="offset=20000"
```
Tahmini sure: ~7 saat (3 paralel). screen -r hls-batch1 ile takip et.

### 6. Tamamlaninca dogrulama
Rastgele 20 sarki kontrol et:
- High segment suresi 4sn mi?
- 4 varyant var mi?
- enc.keyinfo URI dogru mu?
- MP3 128k var mi?
Sonucu bana raporla.

### 7. Final cache temizligi
```bash
php artisan cache:clear && php artisan view:clear && php artisan responsecache:clear
```

## ONEMLI NOTLAR
- OPCACHE-RESET MUTLAKA CALISTIR! (Adim 1) Yoksa Horizon eski kodu kullanir
- Orijinal MP3'ler HICBIR ZAMAN silinmez/degistirilmez
- Hata olursa komut durmaz, sayar ve devam eder
- Islem ortasinda kesilirse, ayni komutu tekrar calistir (mevcut olanlari atlar)
- screen kullan ki terminal kapansa da islem devam etsin
- SERVIS RESTART YAPMA (apache, nginx, redis vs.)
- Migration YOK, sadece dosya islemi
- Re-encode sirasinda sarkilar calismaya devam eder
- Yeni eklenen sarkilar da otomatik dogru formatla uretilir (opcache temiz olduktan sonra)

Test Sunucusu Sonuclari (mztest.muzibu.com)

149 sarki (66 eski + 83 yeni), 0 hata

Kontrol Sonuc
High segment suresi 149/149 = 4sn
6sn eski segment 0 (tamamen temizlendi)
master.m3u8 (4 varyant) 149/149
enc.keyinfo URI (/hls-key/) 149/149
VOD tipi 149/149
MP3 128k 66
Basarisiz 0

⚙️ Artisan Command Referansi

php artisan tenants:run hls:add-variants --tenants=1001

Secenekler:
  --option="quality=all"        Tum varyantlar (ultralow + low + mid)
  --option="quality=low"        Sadece low varyant
  --option="mp3-128=1"          128kbps MP3 de uret
  --option="refresh-master=1"   master.m3u8'i yeniden olustur
  --option="re-encode-high=1"   High playlist'i 4sn segment ile yeniden olustur
  --option="song=123"           Belirli bir sarki ID
  --option="limit=100"          Maksimum islenecek sarki
  --option="offset=0"           Atlanacak sarki (paralel batch icin)
  --option="dry-run=1"          Sadece sayilari goster, islem yapma
22 Subat 2026 • Muzibu.com.tr