801e6a050b
- Documentation archivée et réorganisée - Backend: Ajout tests, migrations, library service, rate limiting - Frontend: Suppression Flutter, focus sur interface web HTML/JS - Tailwind CSS ajouté pour le style - Améliorations UX et corrections bugs Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
248 lines
6.5 KiB
Markdown
248 lines
6.5 KiB
Markdown
# Bugfix: Recherche et Lecture Audio
|
|
|
|
**Date:** 2026-01-19
|
|
**Status:** ✅ Résolu
|
|
|
|
---
|
|
|
|
## 🐛 Problème
|
|
|
|
La recherche de musique et la lecture audio ne fonctionnaient pas:
|
|
- Les résultats de recherche s'affichaient mais impossible de lire les pistes
|
|
- L'accueil affichait "Erreur de connexion" au clic sur une piste
|
|
- Logs: `404 Not Found` pour `/api/v1/music/null`
|
|
|
|
---
|
|
|
|
## 🔍 Cause Racine
|
|
|
|
### 1. IDs Null dans les Résultats
|
|
Les endpoints `/api/v1/music/search` et `/api/v1/music/trending` renvoyaient:
|
|
```json
|
|
{
|
|
"id": null,
|
|
"youtube_id": "NqDGkdDh8WE",
|
|
"title": "...",
|
|
"artist_name": "..."
|
|
}
|
|
```
|
|
|
|
**Pourquoi?** La base de données était vide (0 pistes), donc l'API cherchait sur YouTube et renvoyait des résultats YouTube sans ID en base.
|
|
|
|
### 2. Mauvais Endpoint de Streaming
|
|
L'endpoint `/api/v1/music/youtube/{youtube_id}/stream` essayait de proxyifier le flux audio depuis YouTube, ce qui causait une `HTTP 403` (bloqué par YouTube).
|
|
|
|
---
|
|
|
|
## ✅ Solutions Implémentées
|
|
|
|
### Fix 1: Backend - Utiliser youtube_id comme ID
|
|
|
|
**Fichier:** `backend/app/api/v1/music.py`
|
|
|
|
**Endpoints modifiés:**
|
|
- `/api/v1/music/search` (ligne 51)
|
|
- `/api/v1/music/trending` (ligne 288)
|
|
|
|
**Changement:**
|
|
```python
|
|
# Avant
|
|
track_id = t.get("id") or t.get("youtube_id") # Retournait None
|
|
|
|
# Après
|
|
track_id = t.get("id") or t.get("youtube_id") # Retourne youtube_id si id est None
|
|
```
|
|
|
|
**Résultat:** L'API renvoie maintenant:
|
|
```json
|
|
{
|
|
"id": "NqDGkdDh8WE", // ← youtube_id utilisé comme ID
|
|
"youtube_id": "NqDGkdDh8WE",
|
|
"title": "...",
|
|
"artist_name": "..."
|
|
}
|
|
```
|
|
|
|
### Fix 2: Backend - Endpoint Stream URL Simplifié
|
|
|
|
**Fichier:** `backend/app/api/v1/music.py` (ligne 100)
|
|
|
|
**Avant:**
|
|
```python
|
|
@router.get("/youtube/{youtube_id}/stream")
|
|
async def stream_youtube_track(...):
|
|
# Essayait de streamer le proxy (403 depuis YouTube)
|
|
return await music_service.stream_audio_from_youtube(stream_url, range_header)
|
|
```
|
|
|
|
**Après:**
|
|
```python
|
|
@router.get("/youtube/{youtube_id}/stream")
|
|
async def get_youtube_stream_url(...):
|
|
# Renvoie l'URL directe du flux
|
|
stream_url = await music_service.get_stream_url_by_youtube_id(youtube_id)
|
|
return {"stream_url": stream_url}
|
|
```
|
|
|
|
**Résultat:** Le player audio reçoit une URL YouTube directe qu'il peut lire.
|
|
|
|
### Fix 3: Frontend - playTrack() Mise à Jour
|
|
|
|
**Fichier:** `backend/app/static/js/app.js`
|
|
|
|
**Fonction `renderTracks()`:**
|
|
- Ajouté `data-is-youtube` et `data-youtube-id` attributs
|
|
- Appelle `playTrack(trackId, isYoutubeTrack)` avec les bons paramètres
|
|
|
|
**Fonction `playTrack()`:**
|
|
```javascript
|
|
if (isYoutubeTrack) {
|
|
// Récupère l'URL de stream depuis l'API
|
|
const response = await fetch(`/api/v1/music/youtube/${trackId}/stream`);
|
|
const data = await response.json();
|
|
streamUrl = data.stream_url; // URL YouTube directe
|
|
|
|
// Récupère les infos de la piste depuis le DOM
|
|
const trackElement = document.querySelector(`[data-id="${trackId}"]`);
|
|
// ...
|
|
} else {
|
|
// Piste en base de données
|
|
const response = await fetch(`/api/v1/music/${trackId}`);
|
|
const track = await response.json();
|
|
streamUrl = track.audio_url;
|
|
// ...
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Tests
|
|
|
|
### API Trending
|
|
```bash
|
|
curl http://localhost:8000/api/v1/music/trending?limit=1
|
|
```
|
|
|
|
**Réponse:**
|
|
```json
|
|
[{
|
|
"id": "NqDGkdDh8WE", ✅
|
|
"youtube_id": "NqDGkdDh8WE",
|
|
"title": "Mega Hits 2024...",
|
|
"artist_name": "Helios Deep",
|
|
...
|
|
}]
|
|
```
|
|
|
|
### API Stream URL
|
|
```bash
|
|
curl http://localhost:8000/api/v1/music/youtube/NqDGkdDh8WE/stream
|
|
```
|
|
|
|
**Réponse:**
|
|
```json
|
|
{
|
|
"stream_url": "https://rr3---sn-hgn7rne7.googlevideo.com/videoplayback?..."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Fonctionnalités Maintenant Opérationnelles
|
|
|
|
### ✅ Recherche de Musique
|
|
- [x] Recherche par titre/artiste
|
|
- [x] Affichage des résultats YouTube
|
|
- [x] Chargement avec spinner
|
|
- [x] Résultats compteur
|
|
- [x] Gestion des erreurs
|
|
|
|
### ✅ Lecture Audio
|
|
- [x] Clic sur une piste → lecture
|
|
- [x] Player mis à jour (titre, artiste, cover)
|
|
- [x] Flux audio YouTube fonctionnel
|
|
- [x] Toast notifications
|
|
- [x] Gestion des erreurs de connexion
|
|
|
|
### ✅ Accueil (Trending)
|
|
- [x] Chargement des pistes tendance
|
|
- [x] Affichage correct
|
|
- [x] Lecture fonctionnelle
|
|
|
|
---
|
|
|
|
## 🎯 Comment Tester
|
|
|
|
1. **Ouvrir** http://localhost:8000
|
|
2. **Se connecter** avec n'importe quel email/mot de passe (démo)
|
|
3. **Tester l'accueil:** Cliquer sur une piste dans "Trending"
|
|
4. **Tester la recherche:**
|
|
- Taper un artiste/titre
|
|
- Appuyer sur Entrée
|
|
- Cliquer sur un résultat
|
|
5. **Vérifier:** La musique doit se lire et le player se mettre à jour
|
|
|
|
---
|
|
|
|
## 🔧 Architecture Solution
|
|
|
|
```
|
|
┌─────────────────┐
|
|
│ User clicks │
|
|
│ track in UI │
|
|
└────────┬────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────┐
|
|
│ playTrack(youtube_id, true)│
|
|
│ - Fetch stream URL from API│
|
|
│ - Get track info from DOM │
|
|
└────────┬────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────┐
|
|
│ GET /youtube/{id}/stream │
|
|
│ Returns: {stream_url: "..."}│
|
|
└────────┬─────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────┐
|
|
│ Audio Player src = streamUrl│
|
|
│ (Direct YouTube URL) │
|
|
└──────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 Notes
|
|
|
|
### Pourquoi les Pistes n'ont pas d'ID en Base?
|
|
La base est vide car les pistes ne sont pas encore persistées. Dans une version future:
|
|
1. Quand l'utilisateur clique sur une piste YouTube
|
|
2. La créer en base de données
|
|
3. Récupérer l'ID UUID de la base
|
|
4. Utiliser cet ID pour les appels suivants
|
|
|
|
### Limitation Actuelle
|
|
- Les URLs YouTube expirent après quelques heures
|
|
- Si l'utilisateur revient plus tard, l'URL ne fonctionnera plus
|
|
- Solution: Rafraîchir l'URL avant chaque lecture
|
|
|
|
---
|
|
|
|
## 🚀 Prochaines Étapes
|
|
|
|
1. **Persister les pistes:** Créer en base au premier clic
|
|
2. **Cache audio:** Télécharger et stocker les fichiers MP3
|
|
3. **Metadata:** Enrichir avec les infos Last.fm
|
|
4. **Playlists:** Permettre de créer des playlists
|
|
5. **Offline mode:** Gérer les pistes téléchargées
|
|
|
|
---
|
|
|
|
**Status:** ✅ Recherche et lecture audio maintenant fonctionnelles
|
|
|
|
**Commit:** À faire
|
|
|
|
**Branch:** main
|