Frontend Player System

Muzibu Player Sistemi

Frontend Müzik Çalar Detaylı Analizi

⚡ Hızlı Özet

~7.9k

Satır (Player Core)

1.1MB

JS Dosyaları

2

UI Modu (Mobile/Desktop)

HLS

Encryption Streaming

📝 Basit Anlatım (Herkes İçin)

Player Sistemi Nedir?

Muzibu'nun player sistemi, sayfanın altında sabit duran müzik çalar barıdır. Spotify veya YouTube Music gibi modern platformlardaki player'a benzer şekilde çalışır. Kullanıcı sayfalarda gezerken müzik kesintisiz devam eder ve player her zaman ekranda görünür kalır.

Bu sistem tamamen JavaScript ile çalışır. Sayfa yenilemeden müzik dinlenebilir, şarkı değiştirilebilir, kuyruk yönetilebilir.

Kullanıcı Nasıl Kullanır?

  1. 1 Şarkı seç: Ana sayfadan veya listelerden bir şarkıya tıkla
  2. 2 Player açılır: Altta player bar belirir, şarkı yüklenmeye başlar
  3. 3 Kontroller: Play/pause, ileri/geri, progress bar ile ilerleme kontrol edilir
  4. 4 Kuyruk: Sıradaki şarkılar listesi açılır, drag & drop ile sıralama değiştirilir
  5. 5 Sayfa geçişi: Başka sayfaya gidilse bile müzik devam eder

Ana Özellikler

📱 Responsive Tasarım

Mobilde farklı, masaüstünde farklı görünüm. Mobilde progress ring (halka), masaüstünde linear bar. Her iki modda da kullanımı kolay ve şık.

🎨 Dinamik Renkler

Her şarkının kendine özel renk paleti var. Player, şarkı değiştikçe gradient renkleri değişir. Progress bar, ring, border - hepsi şarkıya özel renklerle uyumlu.

🔒 Güvenli Streaming

Müzikler HLS formatında şifrelenmiş. Browser'da görünen URL'ler bile blob URL olarak maskelenmiş. Kullanıcı Network tab'ı açsa bile gerçek müzik URL'ini göremez.

Kesintisiz Müzik

Sayfa değişse bile müzik durmaz. SPA (Single Page Application) router sistemi ile sayfa geçişleri JavaScript ile yapılır, player state korunur.

🎯 Akıllı Kuyruk

Infinite queue: Kuyruk bitince backend'den otomatik yeni şarkılar eklenir. Drag & drop ile sıralama. Duplicate kontrolü, queue context (playlist, album, genre) takibi.

⌨️ Klavye Kısayolları

Space = Play/Pause, ← → = İleri/Geri, Shift+↑↓ = Volume, K = Toggle Play, L = 10sn İleri, J = 10sn Geri. YouTube benzeri kısayollar.

Neden Önemli?

  • Modern UX: Spotify seviyesinde kullanıcı deneyimi
  • Performans: Alpine.js ile hafif ve hızlı, sayfa yenileme yok
  • Güvenlik: Blob URL + HLS encryption ile müzik koruması
  • Mobil uyumlu: Touch gesture'lar, swipe, responsive tasarım

🔧 Teknik Detaylar (Geliştiriciler İçin)

Teknoloji Stack

Core Framework

  • Alpine.js 3.x - Reactive state
  • • Livewire 3.5+ (Alpine provider)
  • • Tailwind CSS v4 - Styling
  • • FontAwesome Pro 7.1.0 - Icons

Audio Libraries

  • HLS.js 1.4.12 - HLS playback
  • Howler.js 2.2.4 - MP3 fallback
  • • Native HTML5 Audio API
  • • MediaSource Extensions (MSE)

UI Libraries

  • SortableJS - Drag & Drop
  • • Custom CSS animations
  • • SVG Progress Rings
  • • Touch gesture handlers

Dosya Yapısı

public/themes/muzibu/js/                        (1.1MB)
├── player/
│   ├── core/
│   │   ├── player-core.js              (7,883 satır - Ana player mantığı)
│   │   └── safe-storage.js            (localStorage wrapper)
│   └── features/
│       ├── play-helpers.js            (1,015 satır - Queue, play functions)
│       ├── api.js                     (API çağrıları)
│       ├── session.js                 (331 satır - Session check)
│       ├── spa-router.js              (687 satır - SPA navigation)
│       └── spot-player.js             (564 satır - Corporate spot ads)
├── context-menus/
│   ├── actions/                       (8 action handler)
│   ├── handlers/                      (5 feature handler)
│   ├── utils/
│   └── menu-builder.js
├── ai/
│   └── tenant1001-ai-chat.js
└── alpine-apps.js                     (Dashboard, Corporate, Playlist Editor)

resources/views/themes/muzibu/
├── components/
│   ├── player.blade.php               (19KB - Player UI component)
│   ├── queue-overlay.blade.php        (21KB - Queue modal)
│   ├── lyrics-overlay.blade.php
│   ├── context-menu.blade.php
│   └── keyboard-shortcuts-overlay.blade.php
└── layouts/
    └── app.blade.php                  (41KB - Main layout + Alpine init)
                        

Alpine.js Mimarisi

Pattern: Alpine.store() ile global state management

Alpine.store('player')

State:

  • currentSong - Şu an çalan şarkı
  • queue - Sıradaki şarkılar array'i
  • isPlaying - Çalıyor mu boolean
  • currentTime - Geçen süre (saniye)
  • duration - Toplam süre (saniye)
  • isMuted - Sessiz mod
  • isSongLoading - Yükleniyor mu
  • playContext - { type, id, data }

Methods:

  • playSong(songId)
  • togglePlayPause()
  • nextTrack()
  • previousTrack()
  • seekTo(time)
  • addToQueue(songs, next)
  • removeFromQueue(index)
  • reorderQueue(oldIndex, newIndex)
  • playPlaylist(id)
  • playAlbum(id)
  • playRadio(id)

Alpine.store('contextMenu')

Sağ tık menüsü için global state. Song, album, playlist için farklı menüler.

Alpine.store('playlistModal')

"Playlist'e Ekle" modal state. Kullanıcının playlist'lerini listeler.

Alpine.store('sidebar')

Sağ sidebar state. Preview info (hover), entity info (click), quick access list.

HLS Streaming Akışı

1. Şarkı Seçimi

  • • Kullanıcı playSong(songId) tetikler
  • GET /api/muzibu/songs/{id} ile şarkı detayları çekilir
  • • Response: { song_id, title, artist, hls_url, cover_url, color_hues: [30, 350, 320] }

2. Blob URL Oluşturma

  • createHlsBlobUrl(originalHlsUrl) fonksiyonu çalışır
  • • .m3u8 playlist fetch edilir
  • • Segment URL'leri absolute path'e çevrilir
  • • Encryption key URL'i düzeltilir
  • • Blob URL oluşturulur: blob:https://muzibu.com/abc-123
  • • Bu blob URL, gerçek HLS URL'ini maskeler (DevTools'ta görünmez)

3. HLS.js İnit

  • new Hls() instance oluşturulur
  • hls.loadSource(blobUrl) - m3u8 yüklenir
  • hls.attachMedia(audioElement) - Audio element'e bağlanır
  • • HLS.js, AES-128 encrypted segment'leri otomatik decrypt eder
  • MANIFEST_PARSED event'i tetiklenince audio.play()

4. Playback Events

  • audio.ontimeupdatecurrentTime güncellenir
  • audio.onendednextTrack() tetiklenir
  • audio.onerror → Hata toast gösterilir
  • audio.oncanplay → Loading spinner gizlenir

5. Cleanup

  • • Şarkı değişirken hls.destroy() çağrılır
  • URL.revokeObjectURL(blobUrl) - Blob memory temizlenir
  • audio.pause(); audio.removeAttribute('src'); audio.load()

⚠️ Güvenlik Katmanları

  • • ✓ HLS AES-128 encryption (backend'de şifreleme)
  • • ✓ Signed URLs (token + expiry + signature)
  • • ✓ Blob URL maskeleme (gerçek URL görünmez)
  • • ✓ XOR URL encryption (backend'den gelen URL'ler XOR ile şifreli)
  • • ✓ Device check (API her istekte cihaz kontrolü)

Queue (Sıra) Sistemi

Queue State

queue: [] - Sıradaki şarkılar array'i

queueIndex: 0 - Şu an çalan index

playContext: {} - Playlist/Album/Genre context

Örnek:

queue: [
  { song_id: 1, title: "Song 1", ... },
  { song_id: 2, title: "Song 2", ... },
  { song_id: 3, title: "Song 3", ... }
]
queueIndex: 0 // "Song 1" çalıyor
                                    

Queue Operations

  • addToQueue(songs, next)
  • → Sıraya ekle (next=true ise sonraki olarak)
  • removeFromQueue(index)
  • → Kuyruktan çıkar
  • reorderQueue(old, new)
  • → Drag & drop ile sıralama değiştir
  • clearQueue()
  • → Kuyruğu temizle

🔁 Infinite Queue

Kuyruk bitince otomatik yeni şarkılar eklenir. Backend'e istek atılır:

POST /api/muzibu/queue/refill
Body: { context: { type: 'playlist', id: 5 }, count: 10 }

🎯 Context Tracking

Queue her zaman bir context'e bağlı: Playlist, Album, Genre, Sector, Radio. Bu sayede "sonraki şarkılar" aynı context'ten gelir.

Drag & Drop (SortableJS)

Queue overlay'de SortableJS ile sürükle-bırak özelliği. Hem mobile hem desktop uyumlu.

Initialization

Sortable.create(queueContainer, {
    animation: 200,
    ghostClass: 'sortable-ghost',
    chosenClass: 'sortable-chosen',
    dragClass: 'sortable-drag',
    handle: '.queue-drag-handle',
    onEnd: function(evt) {
        reorderQueue(evt.oldIndex, evt.newIndex);
    }
});
                            

CSS Animations

  • .sortable-drag - Sürüklenen item (havada asılı efekt)
  • .sortable-ghost - Bırakılacak yer (dashed border placeholder)
  • .sortable-chosen - Seçilen item (highlight)
  • @keyframes queue-item-drop - Bırakıldığında parlama

Mobile vs Desktop UI

📱 Mobile Player (< 1024px)

  • Progress Ring: Albüm kapağı etrafında halka progress
  • Compact Layout: 3 alan grid [Cover+Info] [Controls] [Menu]
  • Time Badge: Ring üzerinde kalan süre badge'i
  • Three Dots Menu: Tüm ek özellikler menüde
  • Swipe Menu: Menü aşağı kaydırılarak kapatılabilir
  • Touch Progress: Progress bar'da touch drag ile ilerleme
  • Bottom Nav: Fixed bottom navigation bar

🖥️ Desktop Player (>= 1024px)

  • Linear Progress: Yatay progress bar (Spotify style)
  • Full Width: Tüm kontroller tek satırda
  • Hover Effects: Button hover animasyonları
  • Time Display: Geçen / Toplam süre yanyana
  • Volume Button: Mute/Unmute toggle
  • Queue Button: Direkt queue açma
  • Lyrics Button: Şarkı sözleri overlay

✨ Ortak Özellikler

  • • Dinamik gradient border (şarkıya göre renk değişimi)
  • • Gradient animasyonu (@keyframes gradientShift)
  • • Smooth color transition (1s ease)
  • • Responsive cover image loading
  • • Fallback coral gradient (cover yoksa)

API Integration

File: public/themes/muzibu/js/player/features/api.js

GET /api/muzibu/songs/{id}

Şarkı detaylarını çeker

Response: {
    song_id, title, slug, artist_title, album_title, album_cover,
    genre_title, duration, hls_url, lyrics, is_favorite,
    color_hues: [30, 350, 320], // Dinamik renkler
    ...
}
                                

POST /api/muzibu/songs/{id}/play

Dinleme kaydı oluşturur (song_plays tablosuna insert)

POST /api/muzibu/queue/refill

Infinite queue için yeni şarkılar getirir

GET /api/muzibu/playlists/{id}

Playlist detayı + songs eager load

POST /api/favorites/toggle

Favori ekleme/çıkarma (polymorphic relation)

Session Management

File: public/themes/muzibu/js/player/features/session.js (331 satır)

Auto Session Check

Her 2 dakikada bir GET /api/auth/check-session çağrılır.

  • • Session geçersizse → Auto logout + modal göster
  • • Device limit aşılmışsa → Device selection modal
  • • Token expire → Refresh veya re-login iste

Page Visibility API

Kullanıcı tab'ı gizlediğinde session check durur, tab aktif olunca devam eder. Battery saver mode.

SPA Router Sistemi

File: public/themes/muzibu/js/player/features/spa-router.js (687 satır)

Nasıl Çalışır?

  1. 1. Tüm <a> link'leri intercept edilir
  2. 2. event.preventDefault() ile normal navigation engellenir
  3. 3. fetch(url) ile HTML çekilir
  4. 4. DOM'da sadece #main-content alanı değiştirilir
  5. 5. history.pushState() ile URL güncellenir
  6. 6. Player state korunur, müzik devam eder

Özellikler

  • • ✓ Back/Forward button desteği (popstate event)
  • • ✓ Progress bar animasyonu (0% → 50% → 100%)
  • • ✓ Scroll to top (sayfa değişince)
  • • ✓ Meta tag update (title, description, OG tags)
  • • ✓ Google Analytics page view tracking

Exceptions (SPA Bypass)

  • • External links (target="_blank")
  • • Download links
  • • Admin panel (/admin/*)
  • • API endpoints (/api/*)

Klavye Kısayolları

Playback Controls

  • Space - Play/Pause
  • K - Play/Pause (YouTube style)
  • - Önceki şarkı
  • - Sonraki şarkı
  • J - 10 saniye geri
  • L - 10 saniye ileri

Volume & UI

  • Shift + - Volume up
  • Shift + - Volume down
  • M - Mute/Unmute
  • Q - Queue overlay toggle
  • F - Favorite toggle
  • ? - Show shortcuts overlay

⚠️ Context-aware

Input, textarea içinde iken kısayollar devre dışı kalır. Sadece player focused iken aktif.

LocalStorage Persistence

File: public/themes/muzibu/js/player/core/safe-storage.js

Saklanan Veriler

  • muzibu_volume - Son ses seviyesi
  • muzibu_queue - Son kuyruk state
  • muzibu_current_song - Son çalan şarkı
  • muzibu_play_context - Son context (playlist/album/genre)
  • muzibu_queue_index - Kuyrukta konum

Sayfa yenilense bile player state korunur. Kullanıcı kaldığı yerden devam eder.

Safe Storage Wrapper

localStorage hatası (quota exceeded, private mode) tetiklerse fallback olarak memory'de tutar. Hata fırlatmaz, graceful degradation.

✨ Öne Çıkan Özellikler

🎨 UI/UX

  • • Dinamik gradient renkleri (şarkıya özel)
  • • Progress ring (mobile) & linear bar (desktop)
  • • Smooth transitions ve animasyonlar
  • • Touch gesture support (swipe, drag)
  • • Responsive tasarım (< 1024px farklı UI)
  • • Hover effects & active states

⚡ Performans

  • • Alpine.js ile hafif (bundle size küçük)
  • • Lazy loading (HLS segment'ler ihtiyaç olunca)
  • • Blob URL caching (memory sızıntısı yok)
  • • LocalStorage persistence (state korunuyor)
  • • SPA routing (full page reload yok)
  • • Debounced API calls

🔒 Güvenlik

  • • HLS AES-128 encryption
  • • Blob URL maskeleme
  • • XOR URL decryption
  • • Signed URLs (token + expiry + sig)
  • • Device limit check
  • • Session validation (2 dakikada bir)

🎯 Kullanılabilirlik

  • • Keyboard shortcuts (YouTube-style)
  • • Context menu (sağ tık)
  • • Drag & drop queue reordering
  • • Infinite queue (otomatik doldurma)
  • • Lyrics overlay
  • • Volume control

📈 Kod İstatistikleri

~11k

Satır JS (Player)

~60KB

Blade Components

1.1MB

Toplam JS

Core Files

  • • player-core.js - 7,883 satır
  • • play-helpers.js - 1,015 satır
  • • spa-router.js - 687 satır
  • • spot-player.js - 564 satır
  • • session.js - 331 satır

Blade Components

  • • player.blade.php - 19KB
  • • queue-overlay.blade.php - 21KB
  • • app.blade.php - 41KB
  • • sidebar-right.blade.php - 75KB
  • • header.blade.php - 73KB

💡 Geliştirme Notları

✅ İyi Pratikler

  • • Alpine.store pattern ile global state management
  • • Modüler JS dosya yapısı (core, features ayrımı)
  • • Safe cleanup functions (memory leak önleme)
  • • Graceful error handling (toast notifications)
  • • LocalStorage fallback (private mode support)

📌 Dikkat Edilmesi Gerekenler

  • • HLS.js destroy() çağrılmazsa memory leak olur
  • • Blob URL revoke edilmezse garbage collect yapılamaz
  • • Event listener cleanup gerekli (audio.onerror = null)
  • • Queue size kontrolü (çok büyükse LocalStorage quota)
  • • SPA router'da script tag execute edilmeli

⚠️ Bilinen Limitasyonlar

  • • iOS Safari'de autoplay kısıtlaması (user interaction gerekli)
  • • Private mode'da LocalStorage çalışmayabilir
  • • HLS.js IE11'de desteklenmiyor (fallback yok)
  • • SortableJS mobile'da bazen gesture conflict
  • • Session check 2 dk interval (gerçek zamanlı değil)

🚀 İyileştirme Fikirleri

  • • Service Worker ile offline playback cache
  • • WebSocket ile gerçek zamanlı session sync
  • • Canvas visualizer (audio waveform)
  • • Lyrics karaoke sync (time-coded lyrics)
  • • Media Session API (lock screen controls)