Backend Go: - Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN. - Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError). - Sécurisation de config.go, CORS, statuts de santé et monitoring. - Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles). - Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés. - Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*. Chat server (Rust): - Refonte du pipeline JWT + sécurité, audit et rate limiting avancé. - Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing). - Nettoyage des panics, gestion d’erreurs robuste, logs structurés. - Migrations chat alignées sur le schéma UUID et nouvelles features. Stream server (Rust): - Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core. - Transactions P0 pour les jobs et segments, garanties d’atomicité. - Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION). Documentation & audits: - TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services. - Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3). - Scripts de reset et de cleanup pour la lab DB et la V1. Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
8.9 KiB
🌐 API REST - Documentation complète
Date: 2025-01-27
Version: 0.2.0
Base URL: http://localhost:8082
Vue d'ensemble
L'API REST du stream-server permet de:
- Soumettre des fichiers audio pour transcodage
- Récupérer l'état des jobs
- Servir les fichiers HLS générés
Endpoints
POST /v1/stream/transcode
Soumet un fichier audio pour transcodage en HLS.
Request:
- Method:
POST - Content-Type:
multipart/form-data - Body:
file(required): Fichier audio (WAV, MP3, FLAC, etc.)codec(optional): Codec cible (aac,mp3,opus,flac)bitrate(optional): Bitrate en bps (ex:192000)quality_profile(optional): Profil (hi_res,high,medium,low)priority(optional): Priorité (urgent,normal,background)
Response (200 OK):
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"message": "Job submitted successfully"
}
Erreurs:
400 Bad Request: Fichier manquant ou invalide500 Internal Server Error: Erreur serveur
Exemple cURL:
curl -X POST http://localhost:8082/v1/stream/transcode \
-F "file=@audio.wav" \
-F "quality_profile=high" \
-F "priority=normal"
Exemple JavaScript:
const formData = new FormData();
formData.append('file', audioFile);
formData.append('quality_profile', 'high');
const response = await fetch('http://localhost:8082/v1/stream/transcode', {
method: 'POST',
body: formData
});
const { job_id, status } = await response.json();
GET /v1/stream/job/{id}
Récupère l'état d'un job de transcodage.
Request:
- Method:
GET - Path Parameter:
id(UUID du job)
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"track_id": "my_track",
"status": "processing",
"progress": 45.5,
"created_at": "SystemTime { tv_sec: 1737979200, tv_nsec: 0 }",
"started_at": "Some(SystemTime { tv_sec: 1737979205, tv_nsec: 0 })",
"completed_at": null,
"error": null
}
Statuts possibles:
"Pending": Job en attente dans la queue"Processing": Job en cours de traitement"Completed": Job terminé avec succès"Failed(String)": Job échoué (le message d'erreur est danserror)"Cancelled": Job annulé
Erreurs:
404 Not Found: Job introuvable
Exemple cURL:
curl http://localhost:8082/v1/stream/job/550e8400-e29b-41d4-a716-446655440000
Exemple JavaScript:
const response = await fetch(`http://localhost:8082/v1/stream/job/${jobId}`);
const status = await response.json();
if (status.status === 'Completed') {
console.log('Job terminé!');
} else if (status.status.startsWith('Failed')) {
console.error('Erreur:', status.error);
}
GET /v1/stream/hls/{job_id}/index.m3u8
Sert le manifest HLS pour un job terminé.
Request:
- Method:
GET - Path Parameter:
job_id(UUID du job) - Headers: Aucun requis
Response (200 OK):
- Content-Type:
application/vnd.apple.mpegurl - Body: Contenu du fichier
index.m3u8
Exemple de contenu:
#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
#EXTINF:6.0,
segment_00003.ts
#EXT-X-ENDLIST
Erreurs:
404 Not Found: Job introuvable ou manifest non généré400 Bad Request: Job non terminé
Exemple cURL:
curl http://localhost:8082/v1/stream/hls/550e8400-e29b-41d4-a716-446655440000/index.m3u8
Exemple JavaScript:
const manifestUrl = `http://localhost:8082/v1/stream/hls/${jobId}/index.m3u8`;
// Utiliser avec hls.js
import Hls from 'hls.js';
const hls = new Hls();
hls.loadSource(manifestUrl);
hls.attachMedia(audioElement);
GET /v1/stream/hls/{job_id}/{segment}
Sert un segment HLS (.ts).
Request:
- Method:
GET - Path Parameters:
job_id: UUID du jobsegment: Nom du segment (ex:segment_00001.ts)
Response (200 OK):
- Content-Type:
video/mp2t - Body: Contenu binaire du segment
Erreurs:
404 Not Found: Segment introuvable
Exemple cURL:
curl http://localhost:8082/v1/stream/hls/550e8400-e29b-41d4-a716-446655440000/segment_00001.ts \
--output segment_00001.ts
Note: Généralement appelé automatiquement par le player HLS lors du parsing du manifest.
Workflow complet
1. Soumettre un job
const formData = new FormData();
formData.append('file', audioFile);
formData.append('quality_profile', 'high');
const submitResponse = await fetch('http://localhost:8082/v1/stream/transcode', {
method: 'POST',
body: formData
});
const { job_id } = await submitResponse.json();
console.log('Job soumis:', job_id);
2. Poller l'état
async function pollJobStatus(jobId) {
while (true) {
const response = await fetch(`http://localhost:8082/v1/stream/job/${jobId}`);
const status = await response.json();
console.log(`Statut: ${status.status}, Progression: ${status.progress}%`);
if (status.status === 'Completed') {
return status;
} else if (status.status.startsWith('Failed')) {
throw new Error(status.error);
}
// Attendre 2 secondes avant le prochain poll
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
const completedJob = await pollJobStatus(jobId);
3. Charger le manifest HLS
const manifestUrl = `http://localhost:8082/v1/stream/hls/${jobId}/index.m3u8`;
// Avec hls.js
import Hls from 'hls.js';
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(manifestUrl);
hls.attachMedia(audioElement);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
console.log('Manifest chargé, prêt à jouer');
audioElement.play();
});
} else if (audioElement.canPlayType('application/vnd.apple.mpegurl')) {
// Support natif (Safari)
audioElement.src = manifestUrl;
audioElement.addEventListener('loadedmetadata', () => {
audioElement.play();
});
}
Codes d'erreur
400 Bad Request
- Fichier manquant dans la requête
- Format de fichier invalide
- Paramètres invalides
404 Not Found
- Job introuvable
- Manifest HLS introuvable
- Segment introuvable
500 Internal Server Error
- Erreur serveur interne
- Échec de soumission du job
- Erreur de traitement
Rate limiting
Actuellement non implémenté (P0). À ajouter en P1.
Authentification
Actuellement non requise (P0). À ajouter en P1 avec JWT.
CORS
CORS configuré pour:
http://localhost:5176(Vite dev)http://localhost:3000(React dev)
Configurable via variable d'environnement ALLOWED_ORIGINS.
Exemples complets
Python
import requests
import time
import uuid
# 1. Soumettre un job
with open('audio.wav', 'rb') as f:
response = requests.post(
'http://localhost:8082/v1/stream/transcode',
files={'file': f},
data={'quality_profile': 'high'}
)
job_id = response.json()['job_id']
# 2. Poller l'état
while True:
response = requests.get(f'http://localhost:8082/v1/stream/job/{job_id}')
status = response.json()
print(f"Statut: {status['status']}, Progression: {status['progress']}%")
if status['status'] == 'Completed':
break
elif status['status'].startswith('Failed'):
raise Exception(status['error'])
time.sleep(2)
# 3. URL du manifest
manifest_url = f'http://localhost:8082/v1/stream/hls/{job_id}/index.m3u8'
print(f"Manifest HLS: {manifest_url}")
Node.js
const FormData = require('form-data');
const fs = require('fs');
const fetch = require('node-fetch');
async function transcodeAudio(filePath) {
// 1. Soumettre
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
form.append('quality_profile', 'high');
const submitRes = await fetch('http://localhost:8082/v1/stream/transcode', {
method: 'POST',
body: form
});
const { job_id } = await submitRes.json();
// 2. Poller
while (true) {
const statusRes = await fetch(`http://localhost:8082/v1/stream/job/${job_id}`);
const status = await statusRes.json();
if (status.status === 'Completed') {
return `http://localhost:8082/v1/stream/hls/${job_id}/index.m3u8`;
} else if (status.status.startsWith('Failed')) {
throw new Error(status.error);
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
// Usage
transcodeAudio('./audio.wav')
.then(manifestUrl => console.log('Manifest:', manifestUrl))
.catch(console.error);
Changelog
v0.2.0 (2025-01-27)
- ✅ Ajout endpoints
/v1/stream/transcode - ✅ Ajout endpoint
/v1/stream/job/{id} - ✅ Ajout endpoints HLS
/v1/stream/hls/{job_id}/... - ✅ Support multipart/form-data pour upload
- ✅ Gestion des erreurs et statuts
Prochaine étape: Voir STREAM_PIPELINE.md pour l'architecture interne.