# 🎯 DESIGN - Pipeline d'encodage audio minimal mais robuste

**Date**: 2025-01-27  
**Mission**: P0 - Rendre le stream-server fonctionnel

---

## 1. ARCHITECTURE

### 1.1 Vue d'ensemble

```
┌─────────────────┐
│   API Routes    │
│  /transcode     │
│  /job/{id}      │
│  /hls/{id}/...  │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ TranscodingEngine│
│  - Queue         │
│  - JobManager    │
│  - WorkerPool    │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Worker Pool    │
│  (N workers)    │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  FFmpeg Process │
│  (HLS output)   │
└─────────────────┘
```

### 1.2 Composants principaux

#### **TranscodingEngine**
- **Responsabilité**: Orchestrer le transcodage
- **Composants**:
  - `PriorityQueue`: File d'attente des jobs
  - `JobManager`: Stockage et suivi des jobs
  - `WorkerPool`: Pool de workers parallèles

#### **JobManager**
- **Responsabilité**: Stocker et suivre l'état des jobs
- **Stockage**: `HashMap<Uuid, TranscodingJob>` (en mémoire pour P0)
- **Méthodes**:
  - `enqueue(job) -> Uuid`
  - `get_status(job_id) -> Option<JobStatus>`
  - `update_status(job_id, status)`

#### **WorkerPool**
- **Responsabilité**: Traiter les jobs en parallèle
- **Implémentation**: Tokio tasks avec canal async
- **Workers**: N workers (configurable, défaut: `num_cpus()`)

#### **Pipeline**
- **Responsabilité**: Exécuter FFmpeg et gérer les erreurs
- **Fonction**: `transcode_to_hls(input_path, output_dir, codec, bitrate) -> Result<TranscodeResult>`

---

## 2. PIPELINE D'ENCODAGE

### 2.1 Fonction principale

```rust
async fn transcode_to_hls(
    input_path: &Path,
    output_dir: &Path,
    codec: AudioCodec,
    bitrate: u32,
    profile: &QualityProfile,
) -> Result<TranscodeResult, TranscodeError>
```

**Étapes**:
1. Créer le répertoire de sortie `{output_dir}/{job_id}/`
2. Construire la commande FFmpeg
3. Exécuter FFmpeg avec timeout
4. Vérifier que `index.m3u8` et segments existent
5. Retourner `TranscodeResult` avec chemins

### 2.2 Structure de sortie HLS

```
{output_dir}/
  {job_id}/
    index.m3u8          # Master playlist HLS
    segment_00001.ts
    segment_00002.ts
    segment_00003.ts
    ...
```

### 2.3 Format du manifest HLS

```m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:6.0,
segment_00001.ts
#EXTINF:6.0,
segment_00002.ts
...
#EXT-X-ENDLIST
```

---

## 3. COMMAND BUILDER FFMPEG

### 3.1 Arguments par codec

#### **AAC**
```bash
ffmpeg -i input.wav \
  -c:a aac \
  -b:a 192k \
  -ar 44100 \
  -ac 2 \
  -f hls \
  -hls_time 6 \
  -hls_playlist_type vod \
  -hls_segment_filename segment_%05d.ts \
  index.m3u8
```

#### **MP3**
```bash
ffmpeg -i input.wav \
  -c:a libmp3lame \
  -b:a 192k \
  -ar 44100 \
  -ac 2 \
  -f hls \
  -hls_time 6 \
  -hls_playlist_type vod \
  -hls_segment_filename segment_%05d.ts \
  index.m3u8
```

#### **Opus**
```bash
ffmpeg -i input.wav \
  -c:a libopus \
  -b:a 192k \
  -ar 48000 \
  -ac 2 \
  -f hls \
  -hls_time 6 \
  -hls_playlist_type vod \
  -hls_segment_filename segment_%05d.ts \
  index.m3u8
```

#### **FLAC**
```bash
ffmpeg -i input.wav \
  -c:a flac \
  -compression_level 5 \
  -ar 44100 \
  -ac 2 \
  -f hls \
  -hls_time 6 \
  -hls_playlist_type vod \
  -hls_segment_filename segment_%05d.ts \
  index.m3u8
```

### 3.2 Améliorations du builder

- ✅ Ajouter `-hls_list_size 0` pour VOD (liste complète)
- ✅ Valider que FFmpeg est installé au démarrage
- ✅ Gérer les erreurs de construction de commande

---

## 4. GESTION DES ERREURS

### 4.1 Types d'erreurs

```rust
#[derive(Debug, thiserror::Error)]
pub enum TranscodeError {
    #[error("Input file not found: {0}")]
    InputNotFound(PathBuf),
    
    #[error("FFmpeg execution failed: {0}")]
    FfmpegError(String),
    
    #[error("Transcoding timed out after {0} seconds")]
    Timeout(u64),
    
    #[error("Output directory creation failed: {0}")]
    OutputDirError(String),
    
    #[error("HLS manifest not generated")]
    ManifestMissing,
    
    #[error("Insufficient disk space")]
    DiskSpaceError,
}
```

### 4.2 Gestion du timeout

- **Timeout**: 5 minutes par défaut
- **Action**: Tuer le processus FFmpeg si timeout
- **Implémentation**: Utiliser `Command::kill()` sur le child process

### 4.3 Retry logic

- **Max retries**: 3
- **Conditions de retry**:
  - Erreur temporaire (timeout, IO error)
  - Pas de retry sur erreur permanente (fichier corrompu)

---

## 5. API REST

### 5.1 POST `/v1/stream/transcode`

**Request**:
```json
{
  "file": "<multipart file>",
  "codec": "aac",
  "bitrate": 192000,
  "quality_profile": "high"
}
```

**Response**:
```json
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "message": "Job submitted successfully"
}
```

### 5.2 GET `/v1/stream/job/{id}`

**Response**:
```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "progress": 45.5,
  "created_at": "2025-01-27T10:00:00Z",
  "started_at": "2025-01-27T10:00:05Z",
  "completed_at": null,
  "error": null
}
```

### 5.3 GET `/v1/stream/hls/{job_id}/index.m3u8`

**Response**: Contenu du fichier `index.m3u8` avec `Content-Type: application/vnd.apple.mpegurl`

### 5.4 GET `/v1/stream/hls/{job_id}/{segment}`

**Response**: Contenu binaire du segment `.ts` avec `Content-Type: video/mp2t`

---

## 6. INTÉGRATION DANS APPSTATE

### 6.1 Ajout de TranscodingEngine

```rust
pub struct AppState {
    // ... existing fields ...
    pub transcoding_engine: Arc<TranscodingEngine>,
}
```

### 6.2 Initialisation dans `AppState::new()`

```rust
let transcoding_engine = Arc::new(
    TranscodingEngine::new(num_cpus::get())
);
transcoding_engine.start();
```

---

## 7. LOGS STRUCTURÉS

### 7.1 Événements à logger

- `job_queued`: Job soumis
- `job_started`: Worker commence le traitement
- `job_progress`: Progression (toutes les 10%)
- `job_completed`: Job terminé avec succès
- `job_failed`: Job échoué avec erreur

### 7.2 Format des logs

```rust
tracing::info!(
    job_id = %job.id,
    status = "queued",
    priority = ?job.priority,
    "Job queued for transcoding"
);
```

---

## 8. TESTS

### 8.1 Tests unitaires

- ✅ Test command builder pour chaque codec
- ✅ Test pipeline avec fichier WAV de test
- ✅ Test job manager en mémoire

### 8.2 Tests d'intégration

- ✅ Upload fichier → job → index.m3u8 généré
- ✅ Vérification existence segments
- ✅ Test timeout FFmpeg

---

## 9. LIMITATIONS P0

- ❌ Pas de multi-bitrate adaptatif (ABR)
- ❌ Pas de DRM
- ❌ Pas de persistance en base de données (mémoire uniquement)
- ❌ Pas de métriques Prometheus détaillées
- ❌ Pas de cleanup automatique des anciens jobs

---

**Prochaine étape**: Phase 3 - Implémentation

