v3 Yeni Özellikler
İçindekiler
Mevcut Sistem Analizi
Backend altyapısı ve mevcut koruma mekanizmaları
Basit Anlatım
Muzibu şu an şöyle çalışıyor:
- Şarkılar sunucuda - Kullanıcı dinlerken anlık olarak sunucudan çekiyor
- İndirme yok - Şarkı dosyasını telefona kaydetme özelliği mevcut değil
- HLS şifrelemesi var - Şarkılar parçalara bölünüp şifreleniyor (AES-128)
- Premium kontrolü - Kullanıcının üyelik bitiş tarihi kontrol ediliyor
Teknik Detaylar
Dosya Saklama Yapısı
/storage/tenant1001/app/public/muzibu/
├── songs/ # MP3 dosyaları
│ ├── mp3_128/ # 128kbps encode
│ ├── mp3_64/ # 64kbps encode
│ └── SONG_*.mp3 # Orijinal dosyalar
├── hls/ # HLS streaming
│ └── {songId}/
│ ├── master.m3u8 # Ana playlist
│ ├── ultralow/ # 32kbps
│ ├── low/ # 64kbps
│ ├── mid/ # 128kbps
│ ├── high/ # Orijinal
│ └── enc.bin # AES-128 key
Mevcut Premium Kontrolü
// User Model
public function isPremium(): bool {
// 5 dakika Redis cache
return Cache::remember("premium:{$this->id}", 300, function () {
return $this->subscription_expires_at?->isFuture() ?? false;
});
}
Sorun: 5 dakika cache = Premium bitince 5 dakika daha dinleyebilir
Mevcut Streaming Endpoints
| Endpoint | Amaç | Koruma |
|---|---|---|
| /api/muzibu/songs/{id}/stream | Stream URL al | Auth + Premium |
| /hls/muzibu/songs/{id}/master.m3u8 | HLS playlist | Signed URL |
| /hls-key/muzibu/songs/{id} | Şifre anahtarı | Signed Token |
| /api/.../download | İndirme | YOK! |
Offline İndirme Sistemi
Şarkıları telefona indirip internet olmadan dinleme
Basit Anlatım
Ne yapacağız?
- Kullanıcı beğendiği şarkıyı "İndir" butonuyla telefonuna kaydedecek
- İnternet olmadan bile indirdiği şarkıları dinleyebilecek
- İndirilen dosyalar şifreli olacak - başka uygulamalar açamaz
- Premium bitince indirilen şarkılar kilitlenecek
Teknik Mimari
İndirme Akış Diyagramı
Yeni Backend Endpoint
// POST /api/muzibu/songs/{id}/download-token
public function downloadToken(int $songId): JsonResponse
{
$user = auth()->user();
// 1. Premium kontrolü
if (!$user->isPremium()) {
return response()->json([
'status' => 'subscription_required'
], 402);
}
// 2. User-specific encryption key oluştur
$userKey = hash('sha256', $user->id . config('app.key') . $songId);
// 3. Download token (1 saat geçerli)
$token = Crypt::encryptString(json_encode([
'user_id' => $user->id,
'song_id' => $songId,
'user_key' => $userKey,
'expires' => now()->addHour()->timestamp,
'subscription_expires' => $user->subscription_expires_at
]));
// 4. İndirme kaydı oluştur
UserDownload::create([
'user_id' => $user->id,
'song_id' => $songId,
'downloaded_at' => now(),
'subscription_expires_at' => $user->subscription_expires_at
]);
return response()->json([
'status' => 'ready',
'download_url' => "/api/muzibu/songs/{$songId}/download?token={$token}",
'user_key' => $userKey, // Mobil uygulama saklar
'expires_at' => $user->subscription_expires_at
]);
}
Flutter İndirme Servisi
// download_service.dart
class DownloadService {
final _dio = Dio();
final _db = OfflineDatabase();
final _crypto = CryptoService();
Future<void> downloadSong(Song song) async {
// 1. Token al
final tokenResponse = await _dio.post(
'/api/muzibu/songs/${song.id}/download-token'
);
final userKey = tokenResponse.data['user_key'];
final downloadUrl = tokenResponse.data['download_url'];
final expiresAt = tokenResponse.data['expires_at'];
// 2. Dosyayı indir (chunk by chunk)
final tempPath = await _downloadFile(downloadUrl);
// 3. Şifrele ve .mzb olarak kaydet
final encryptedPath = await _crypto.encryptFile(
sourcePath: tempPath,
userKey: userKey,
songId: song.id,
);
// 4. Local DB'ye kaydet
await _db.insertDownload(DownloadedSong(
songId: song.id,
title: song.title,
artist: song.artist,
filePath: encryptedPath,
userKey: userKey,
downloadedAt: DateTime.now(),
subscriptionExpiresAt: DateTime.parse(expiresAt),
));
// 5. Temp dosyayı sil
await File(tempPath).delete();
}
}
.mzb Dosya Formatı
Dosya Yapısı
┌─────────────────────────┐ │ Magic Bytes (4 byte) │ "MZB\x01" ├─────────────────────────┤ │ Header Length (4 byte) │ uint32 ├─────────────────────────┤ │ Header (JSON, encrypted)│ │ - user_id │ │ - song_id │ │ - subscription_expires │ │ - checksum │ ├─────────────────────────┤ │ IV (16 byte) │ AES-256 IV ├─────────────────────────┤ │ Encrypted Audio Data │ AES-256-CBC │ (variable length) │ └─────────────────────────┘
Güvenlik Özellikleri
-
User-Specific KeyHer kullanıcı için farklı şifreleme anahtarı
-
Custom Uzantı.mzb uzantısı - sistem tanımıyor
-
Embedded User IDDosya içinde kullanıcı kimliği gömülü
-
Expiry CheckAbonelik tarihi dosya içinde
DRM / Kopyalama Koruması
İndirilen dosyaların PC'ye kopyalanmasını engelleme
Basit Anlatım
Neden önemli?
Kullanıcı şarkıyı indirip USB ile PC'ye kopyalarsa, abonelik bitse bile dinlemeye devam edebilir. Bunu engellemek için:
- Dosyalar şifreli - Sadece bizim uygulama açabilir
- Her kullanıcı farklı anahtar - Başkası açamaz
- Dosya PC'ye kopyalansa bile çalışmaz
- Premium bitince kilit - Şifreli dosya açılamaz
DRM Seçenekleri Karşılaştırması
| Yöntem | Güvenlik | Zorluk | Maliyet | Öneri |
|---|---|---|---|---|
|
Widevine + FairPlay
Google + Apple DRM
|
Çok Yüksek | Zor | $$$ | |
|
Custom Encryption
AES-256 + User Key
|
Yüksek | Kolay | $ | ÖNERİLEN |
|
No Protection
Düz MP3
|
Yok | En Kolay | Ücretsiz |
Önerilen Çözüm: Custom Encryption
4 Katmanlı Koruma
Neden Widevine Değil?
Neden Flutter?
React Native yerine Flutter tercih etme sebepleri
Flutter vs React Native
| Kriter | Flutter | React Native | Kazanan |
|---|---|---|---|
| Audio Kütüphaneleri | just_audio (native gapless) | react-native-track-player | Flutter |
| Bellek Yönetimi | Dart GC + Native ARM | JS Bridge overhead | Flutter |
| 15 Saat Oturum | Stabil | Memory leak riski | Flutter |
| Eski Cihaz Desteği | iOS 12+, Android 6+ | iOS 13+, Android 6+ | Flutter |
| Background Audio | audio_service (isolate) | 3rd party bağımlı | Flutter |
| Performans | 60fps native render | Bridge latency | Flutter |
| Öğrenme Eğrisi | Dart (yeni dil) | JavaScript/TypeScript | React Native |
Müzik Uygulaması İçin Kritik Avantajlar
In-App Purchase
Google Play ve App Store ödeme entegrasyonu
- Subscription (aylık/yıllık)
- Real-time Developer Notifications
- Server-side doğrulama
- %15-30 komisyon
- Auto-renewable subscriptions
- StoreKit 2
- Server-to-Server notifications
- %15-30 komisyon
Subscription Sync Akışı
Kesintisiz Müzik Sistemi
Donma olmadan 15 saat kesintisiz müzik
Fallback Zinciri (Graceful Degradation)
İnternet kötüleşince kalite düşer, donma yerine kalite fedası yapılır
Gapless Playback (Boşluksuz Geçiş)
// Flutter - just_audio ile gapless playback
final playlist = ConcatenatingAudioSource(
useLazyPreparation: true, // Sadece sıradaki hazırla
children: [
AudioSource.uri(Uri.parse(song1.streamUrl)),
AudioSource.uri(Uri.parse(song2.streamUrl)),
AudioSource.uri(Uri.parse(song3.streamUrl)),
],
);
// Preload: Şarkı bitmeden 30 saniye önce sonrakini hazırla
player.positionStream.listen((position) {
final remaining = player.duration - position;
if (remaining < Duration(seconds: 30)) {
preloadNextSong();
}
});
15 Saat İçin Bellek Yönetimi
API Endpoints
Mobil uygulama için gerekli API'ler
| Endpoint | Method | Amaç | Durum |
|---|---|---|---|
| /api/login | POST | Email/şifre girişi | Mevcut |
| /api/muzibu/songs/{id}/stream | GET | Şarkı stream URL | Mevcut |
| /api/muzibu/playlists | GET | Playlist listesi | Mevcut |
| /api/auth/social | POST | Social login (Google/Facebook/Apple) | Yeni |
| /api/user/subscription-status | GET | Anlık premium durumu | Yeni |
| /api/muzibu/songs/{id}/download-token | POST | İndirme token al | Yeni |
| /api/muzibu/songs/{id}/download | GET | Şifreli dosya indir | Yeni |
| /api/webhooks/google-play | POST | Google Play bildirim | Yeni |
| /api/webhooks/app-store | POST | App Store bildirim | Yeni |
Yol Haritası (7 Faz)
Adım adım geliştirme planı
Temel Altyapı
Flutter proje kurulumu, tema sistemi (dark mode), Dio HTTP client, interceptors, email/şifre login, token storage (secure), GoRouter navigasyon
Müzik Player Çekirdeği
just_audio + audio_service entegrasyonu, HLS adaptive streaming, gapless playback, queue yönetimi, background playback, lock screen controls
UI/UX Katmanı
Ana sayfa, arama, playlist detay, şarkı detay, mini player, full player, genre/artist sayfaları, animasyonlar
Offline + DRM Sistemi (YENİ)
Şarkı indirme, AES-256 şifreleme, .mzb formatı, offline playback, SQLite local DB, indirme yönetimi UI
Premium + Auth Genişletme (YENİ)
Real-time premium kontrolü, social login (Google/Facebook/Apple), subscription status sync, push notifications
In-App Purchase (YENİ)
Google Play Billing, App Store entegrasyonu, subscription yönetimi, webhook endpoints, receipt validation
Test & Yayın
Unit/widget testleri, integration testleri, beta test, store listing hazırlığı, App Store / Google Play yayını
Riskler ve Çözümler
Potansiyel sorunlar ve önlemler
Memory Leak (15 Saat)
Uzun oturumlarda bellek sızıntısı
Çözüm: Playlist limiti, buffer cleanup, isolate kullanımı
Kötü İnternet
Yavaş bağlantıda şarkı takılması
Çözüm: HLS ABR, fallback zinciri, preload sistemi
Premium Gecikmesi
Ödeme sonrası premium aktif olmama
Çözüm: Webhook + push notification + polling fallback
Dosya Kopyalama
İndirilen dosyaların PC'ye kopyalanması
Çözüm: AES-256 + user key + device binding + custom format
Flutter Paketleri
Kullanılacak ana paketler
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
# Audio
just_audio: ^0.9.36 # Müzik player
audio_service: ^0.18.12 # Background playback
audio_session: ^0.1.18 # Audio session yönetimi
# Network
dio: ^5.4.0 # HTTP client
connectivity_plus: ^5.0.2 # Bağlantı durumu
# Storage
flutter_secure_storage: ^9.0.0 # Token saklama
sqflite: ^2.3.0 # Local database
path_provider: ^2.1.1 # Dosya yolları
# Encryption (YENİ)
encrypt: ^5.0.3 # AES-256 şifreleme
crypto: ^3.0.3 # Hash fonksiyonları
# Auth (YENİ)
google_sign_in: ^6.2.1 # Google login
flutter_facebook_auth: ^6.1.1 # Facebook login
sign_in_with_apple: ^5.0.0 # Apple login
# Payments (YENİ)
in_app_purchase: ^3.1.13 # IAP unified
purchases_flutter: ^6.17.0 # RevenueCat (opsiyonel)
# Push
firebase_messaging: ^14.7.9 # Push notifications
# UI
cached_network_image: ^3.3.0 # Image cache
go_router: ^12.1.1 # Navigation
flutter_riverpod: ^2.4.9 # State management
Social Login
Google, Facebook ve Apple ile giriş