Transcodage systématique MP3 128kbps
J'ai implémenté une solution complète pour optimiser ton système audio : 1. Backend - Transcodage & Waveforms Nouveau module de transcodage (transcoder.py): Transcodage automatique en MP3 128kbps via FFmpeg Stockage dans dossier transcoded/ Compression ~70-90% selon format source Waveforms pré-calculées (waveform_generator.py): Génération lors du scan (800 points) Stockage JSON dans dossier waveforms/ Chargement instantané Schema BDD mis à jour (schema.py): filepath : fichier original (download) stream_filepath : MP3 128kbps (streaming) waveform_filepath : JSON pré-calculé Scanner amélioré (scanner.py): Transcode automatiquement chaque fichier Pré-calcule la waveform Stocke les 3 chemins en BDD 2. API - Endpoints Endpoint /api/library/scan (library.py): POST pour lancer un scan Tâche en arrière-plan Statut consultable via GET /api/library/scan/status Streaming optimisé (audio.py): Utilise stream_filepath (MP3 128kbps) en priorité Fallback sur fichier original si absent Waveform chargée depuis JSON pré-calculé 3. Frontend - Interface Bouton Rescan (page.tsx): Dans le header à droite Icône qui tourne pendant le scan Affichage progression en temps réel Reload automatique après scan 4. Base de données Migration appliquée (20251223_003_add_stream_waveform_paths.py): ALTER TABLE audio_tracks ADD COLUMN stream_filepath VARCHAR; ALTER TABLE audio_tracks ADD COLUMN waveform_filepath VARCHAR; CREATE INDEX idx_stream_filepath ON audio_tracks (stream_filepath); 🚀 Utilisation Via l'interface web Clique sur le bouton "Rescan" dans le header Le scan démarre automatiquement Tu vois la progression en temps réel La page se recharge automatiquement à la fin Via CLI (dans le container) docker-compose exec backend python -m src.cli.scanner /music 📊 Avantages ✅ Streaming ultra-rapide : MP3 128kbps = ~70-90% plus léger ✅ Waveform instantanée : Pré-calculée, pas de latence ✅ Download qualité : Fichier original préservé ✅ Rescan facile : Bouton dans l'UI ✅ Prêt pour serveur distant : Optimisé pour la bande passante
This commit is contained in:
@@ -22,6 +22,9 @@ async def stream_audio(
|
||||
):
|
||||
"""Stream audio file with range request support.
|
||||
|
||||
Uses the transcoded MP3 128kbps file for fast streaming if available,
|
||||
otherwise falls back to the original file.
|
||||
|
||||
Args:
|
||||
track_id: Track UUID
|
||||
request: HTTP request
|
||||
@@ -38,21 +41,29 @@ async def stream_audio(
|
||||
if not track:
|
||||
raise HTTPException(status_code=404, detail="Track not found")
|
||||
|
||||
file_path = Path(track.filepath)
|
||||
# Prefer stream_filepath (transcoded MP3) if available
|
||||
if track.stream_filepath and Path(track.stream_filepath).exists():
|
||||
file_path = Path(track.stream_filepath)
|
||||
media_type = "audio/mpeg"
|
||||
logger.debug(f"Streaming transcoded file: {file_path}")
|
||||
else:
|
||||
# Fallback to original file
|
||||
file_path = Path(track.filepath)
|
||||
|
||||
if not file_path.exists():
|
||||
logger.error(f"File not found: {track.filepath}")
|
||||
raise HTTPException(status_code=404, detail="Audio file not found on disk")
|
||||
if not file_path.exists():
|
||||
logger.error(f"File not found: {track.filepath}")
|
||||
raise HTTPException(status_code=404, detail="Audio file not found on disk")
|
||||
|
||||
# Determine media type based on format
|
||||
media_types = {
|
||||
"mp3": "audio/mpeg",
|
||||
"wav": "audio/wav",
|
||||
"flac": "audio/flac",
|
||||
"m4a": "audio/mp4",
|
||||
"ogg": "audio/ogg",
|
||||
}
|
||||
media_type = media_types.get(track.format, "audio/mpeg")
|
||||
# Determine media type based on format
|
||||
media_types = {
|
||||
"mp3": "audio/mpeg",
|
||||
"wav": "audio/wav",
|
||||
"flac": "audio/flac",
|
||||
"m4a": "audio/mp4",
|
||||
"ogg": "audio/ogg",
|
||||
}
|
||||
media_type = media_types.get(track.format, "audio/mpeg")
|
||||
logger.debug(f"Streaming original file: {file_path}")
|
||||
|
||||
return FileResponse(
|
||||
path=str(file_path),
|
||||
@@ -121,6 +132,8 @@ async def get_waveform(
|
||||
):
|
||||
"""Get waveform peak data for visualization.
|
||||
|
||||
Uses pre-computed waveform if available, otherwise generates on-the-fly.
|
||||
|
||||
Args:
|
||||
track_id: Track UUID
|
||||
num_peaks: Number of peaks to generate
|
||||
@@ -144,7 +157,14 @@ async def get_waveform(
|
||||
raise HTTPException(status_code=404, detail="Audio file not found on disk")
|
||||
|
||||
try:
|
||||
waveform_data = get_waveform_data(str(file_path), num_peaks=num_peaks)
|
||||
# Use pre-computed waveform if available
|
||||
waveform_cache_path = track.waveform_filepath if track.waveform_filepath else None
|
||||
|
||||
waveform_data = get_waveform_data(
|
||||
str(file_path),
|
||||
num_peaks=num_peaks,
|
||||
waveform_cache_path=waveform_cache_path
|
||||
)
|
||||
return waveform_data
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user