Serveur Streaming Rust (veza-stream-server)

Architecture du serveur audio haute performance basé sur Axum. Source : veza-stream-server/src/

Vue d'ensemble

Le stream server est un service Rust autonome qui gère :

Il communique avec le backend Go via RabbitMQ (événements asynchrones) et des callbacks REST internes.

Stack technique

Composant Technologie
Framework HTTP Axum (async Rust)
Runtime Tokio
Auth JWT (validation)
Audio FFmpeg (transcoding), HLS.js (côté client)
Messaging RabbitMQ (consommateur)
Cache In-memory (playlists HLS)
Monitoring Prometheus
Stockage S3/MinIO
Base de données PostgreSQL (requêtes directes)

Structure des modules

veza-stream-server/src/
├── main.rs                      # Point d'entrée, initialisation Axum
├── routes/
│   └── api.rs                   # Définition de toutes les routes
├── streaming/
│   ├── websocket.rs             # Handler WebSocket avec protocole de sync
│   ├── hls.rs                   # Génération de playlists HLS
│   └── adaptive.rs              # Sélection adaptative du bitrate
├── transcoding/
│   └── mod.rs                   # Orchestration transcoding FFmpeg
├── codecs/
│   └── mod.rs                   # Wrappers FFmpeg
├── audio/
│   └── mod.rs                   # Utilitaires audio
├── middleware/
│   ├── logging.rs               # Logs structurés
│   ├── security.rs              # Headers de sécurité
│   └── rate_limit.rs            # Rate limiting par IP
├── auth/
│   └── mod.rs                   # Validation JWT
├── config/
│   └── mod.rs                   # Configuration depuis env
├── health/
│   └── mod.rs                   # Health checks
├── monitoring/
│   └── mod.rs                   # Métriques Prometheus
├── cache/
│   └── mod.rs                   # Cache mémoire playlists
└── database/
    └── mod.rs                   # Requêtes PostgreSQL

Routes

Santé & monitoring

Méthode Route Description
GET / Message racine (info serveur)
GET /health Health check détaillé
GET /healthz Liveness probe (Kubernetes)
GET /readyz Readiness probe
GET /metrics Métriques Prometheus

Streaming audio

Méthode Route Description Auth
GET /stream/{filename} Stream fichier audio Signature URL
GET /hls/{track_id}/master.m3u8 Playlist master HLS JWT
GET /hls/{track_id}/{quality}/playlist.m3u8 Playlist par qualité JWT
GET /hls/{track_id}/{quality}/{segment} Segment HLS JWT
WS /ws WebSocket streaming temps réel JWT (query param)

Transcoding

Méthode Route Description Auth
POST /internal/jobs/transcode Lancer job transcoding Clé API interne
POST /v1/stream/transcode Initier transcoding JWT
GET /v1/stream/job/{id} Statut du job JWT
GET /v1/stream/hls/{job_id}/index.m3u8 Playlist du job JWT
GET /v1/stream/hls/{job_id}/{segment} Segment du job JWT
GET /api/streams/jobs/{id}/status Statut détaillé JWT

Protocole WebSocket

Le WebSocket (/ws?track_id=...) utilise un protocole personnalisé pour la lecture synchronisée.

Commandes client → serveur

Commande Payload Description
play { position: float } Démarrer la lecture à la position
pause Mettre en pause
seek { position: float } Sauter à une position
sync { position: float } Synchroniser (co-écoute)
heartbeat Maintenir la connexion
error { message: string } Signaler une erreur client

Réponses serveur → client

Réponse Payload Description
ready { duration, bitrates } Serveur prêt à streamer
chunk { data, position, bitrate } Chunk audio avec métadonnées
sync_ack { position } Accusé de réception sync
error { code, message } Erreur serveur

Cycle de vie d'une connexion

Client                          Serveur
  │                                │
  │── WS Connect ─────────────────▶│
  │   (track_id, JWT en query)     │
  │                                │── Validation JWT
  │                                │── Chargement playlist HLS
  │◀── ready ──────────────────────│
  │   (duration, bitrates)         │
  │                                │
  │── play { position: 0 } ──────▶│
  │                                │── Sélection bitrate adaptatif
  │◀── chunk ──────────────────────│
  │◀── chunk ──────────────────────│
  │◀── chunk ──────────────────────│
  │                                │
  │── heartbeat ──────────────────▶│  (toutes les 30s)
  │                                │
  │── seek { position: 120 } ────▶│
  │◀── chunk ──────────────────────│
  │                                │
  │── pause ──────────────────────▶│
  │                                │
  │── WS Close ───────────────────▶│

Streaming HLS adaptatif

Le serveur génère et sert des playlists HLS multi-bitrate avec sélection adaptative.

Qualités disponibles

Le transcoding produit plusieurs qualités à partir du fichier source :

Qualité Bitrate Usage
low 64 kbps Mobile / réseau faible
medium 128 kbps Standard
high 256 kbps Haute qualité
lossless Original Audiophile

Fonctionnement

  1. Upload : Le backend Go reçoit le fichier audio et le stocke sur S3
  2. Événement : track.uploaded publié sur RabbitMQ
  3. Transcoding : Le stream server consomme l'événement, transcode via FFmpeg
  4. Stockage : Les segments HLS et playlists sont stockés sur S3
  5. Callback : POST /internal/tracks/:id/stream-ready vers le backend
  6. Lecture : Le client demande le master playlist, le serveur sert les segments

Structure des fichiers HLS sur S3

hls/{track_id}/
├── master.m3u8            # Master playlist (liste les qualités)
├── low/
│   ├── playlist.m3u8      # Playlist 64 kbps
│   ├── segment_000.ts     # Segments audio
│   ├── segment_001.ts
│   └── ...
├── medium/
│   ├── playlist.m3u8      # Playlist 128 kbps
│   └── ...
├── high/
│   ├── playlist.m3u8      # Playlist 256 kbps
│   └── ...
└── lossless/
    ├── playlist.m3u8
    └── ...

Pile de middlewares

Appliqués dans l'ordre à toutes les routes :

  1. CORS — Restrictif par défaut, origines configurables
  2. Timeout — 30 secondes par requête
  3. Compression — gzip
  4. Security Headers — X-Content-Type-Options, X-Frame-Options, etc.
  5. Rate Limiting — Par IP
  6. Request Logging — Logs JSON structurés

Configuration

pub struct Config {
    port: u16,                        // PORT (default: 18082)
    database_url: String,             // DATABASE_URL
    rabbit_mq: RabbitMQConfig,        // RABBITMQ_URL
    s3_bucket: String,                // S3_BUCKET
    s3_region: String,                // S3_REGION
    log_level: String,                // LOG_LEVEL
    allowed_origins: Vec<String>,     // ALLOWED_ORIGINS
}

Toute la configuration provient des variables d'environnement (voir CONFIGURATION_ENVIRONNEMENT).

Communication inter-services

Événements RabbitMQ consommés

Événement Action
track.uploaded Lance le transcoding HLS
track.deleted Supprime les segments HLS de S3

Callbacks REST vers le backend Go

Callback Description
POST /internal/tracks/:id/stream-ready Notifie que le transcoding est terminé
POST /internal/stream-events Envoie des événements de streaming

Header d'authentification : X-Stream-Secret

Dockerfiles

Fichier Base Usage
Dockerfile rust:latest Développement (avec debug symbols)
Dockerfile.production debian:bookworm-slim Production (binaire optimisé, minimal)

Documents liés