feat(server): file d'attente + téléchargement (vidéo/audio/miniature) #2

Merged
kyuno merged 1 commit from feature/download-queue into feature/channel-discovery 2026-09-16 09:30:00 +02:00
Owner

Résumé

Empilée sur #1 (réutilise et étend ytDlpRunner.ts) — à merger après elle, base ajustée automatiquement par Forgejo une fois #1 mergée.

Cœur du pipeline décrit pour l'app : file d'attente de téléchargements (vidéo/audio/miniature), exécutés avec une concurrence bornée, fichier livré au navigateur (pas de dépôt durable côté serveur).

Détails

  • server/src/services/downloadPlan.ts : fonctions pures construisant les arguments yt-dlp par mode — vidéo (sous-titres fr/en + miniature embarquée en option), audio (mp3/m4a/opus), miniature seule. Toujours un séparateur -- avant l'URL. Parsing de la progression ([download] NN.N% ...) depuis stdout.
  • server/src/services/videoUrl.ts : valide qu'une URL cible bien youtube.com/youtu.be (watch/shorts/live/court) avant de la transmettre à yt-dlp — ferme le risque de relais SSRF via l'extracteur générique de yt-dlp (qui sait suivre des centaines de sites) si une URL arbitraire était acceptée.
  • server/src/services/QueueService.ts : file en mémoire, MAX_CONCURRENT_DOWNLOADS téléchargements simultanés (défaut 2), annulation via AbortSignal, dossier de sortie par élément supprimé après échec/annulation ou après livraison du fichier au client.
  • server/src/services/ytDlpRunner.ts : étendu (signature en objet d'options) pour le suivi ligne par ligne de stdout (progression) et l'annulation.
  • server/src/routes/queue.ts : POST /api/queue, GET /api/queue, DELETE /api/queue/:id, GET /api/queue/:id/file (streaming, nettoyage après envoi).
  • spec/architecture.md mis à jour.

Tests

45 nouveaux tests (59 au total) sur 3 niveaux : fonctions pures (downloadPlan, videoUrl), service avec ytDlpRunner mocké mais un vrai système de fichiers temporaire (plus réaliste qu'un mock fs — couvre concurrence, annulation, nettoyage), routes via app.inject().

Vérifié aussi en conditions réelles (serveur démarré localement, pas seulement les tests) : validation d'URL rejetée en 400, ajout en file, et passage propre à failed + nettoyage du dossier quand le binaire yt-dlp est absent (ENOENT) — pas de crash serveur.

Vérifications locales

  • npm run lint (Biome, racine) : clean
  • npm run typecheck + npm test + npm run build (server) : clean, 59/59 tests passent

🤖 Generated with Claude Code

## Résumé Empilée sur #1 (réutilise et étend `ytDlpRunner.ts`) — à merger après elle, base ajustée automatiquement par Forgejo une fois #1 mergée. Cœur du pipeline décrit pour l'app : file d'attente de téléchargements (vidéo/audio/miniature), exécutés avec une concurrence bornée, fichier livré au navigateur (pas de dépôt durable côté serveur). ## Détails - `server/src/services/downloadPlan.ts` : fonctions pures construisant les arguments yt-dlp par mode — vidéo (sous-titres fr/en + miniature embarquée en option), audio (mp3/m4a/opus), miniature seule. Toujours un séparateur `--` avant l'URL. Parsing de la progression (`[download] NN.N% ...`) depuis stdout. - `server/src/services/videoUrl.ts` : valide qu'une URL cible bien `youtube.com`/`youtu.be` (watch/shorts/live/court) avant de la transmettre à yt-dlp — ferme le risque de relais SSRF via l'extracteur générique de yt-dlp (qui sait suivre des centaines de sites) si une URL arbitraire était acceptée. - `server/src/services/QueueService.ts` : file en mémoire, `MAX_CONCURRENT_DOWNLOADS` téléchargements simultanés (défaut 2), annulation via `AbortSignal`, dossier de sortie par élément supprimé après échec/annulation ou après livraison du fichier au client. - `server/src/services/ytDlpRunner.ts` : étendu (signature en objet d'options) pour le suivi ligne par ligne de stdout (progression) et l'annulation. - `server/src/routes/queue.ts` : `POST /api/queue`, `GET /api/queue`, `DELETE /api/queue/:id`, `GET /api/queue/:id/file` (streaming, nettoyage après envoi). - `spec/architecture.md` mis à jour. ## Tests 45 nouveaux tests (59 au total) sur 3 niveaux : fonctions pures (`downloadPlan`, `videoUrl`), service avec `ytDlpRunner` mocké mais un **vrai** système de fichiers temporaire (plus réaliste qu'un mock fs — couvre concurrence, annulation, nettoyage), routes via `app.inject()`. Vérifié aussi en conditions réelles (serveur démarré localement, pas seulement les tests) : validation d'URL rejetée en `400`, ajout en file, et passage propre à `failed` + nettoyage du dossier quand le binaire yt-dlp est absent (`ENOENT`) — pas de crash serveur. ## Vérifications locales - `npm run lint` (Biome, racine) : clean - `npm run typecheck` + `npm test` + `npm run build` (server) : clean, 59/59 tests passent 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kyuno added 1 commit 2026-09-16 09:02:56 +02:00
Cœur du pipeline : ajoute une file d'attente exécutant les téléchargements
yt-dlp avec une concurrence bornée, et livre le fichier produit au
navigateur (pas de dépôt durable côté serveur).

- downloadPlan.ts : construction des arguments yt-dlp par mode (vidéo avec
  sous-titres/miniature en option, audio dans un format courant, miniature
  seule), toujours avec séparateur `--` avant l'URL. Parsing de la
  progression depuis stdout (`[download] NN.N%`).
- videoUrl.ts : valide qu'une URL cible bien youtube.com/youtu.be avant de
  la passer à yt-dlp - ferme le risque de relais SSRF via l'extracteur
  générique de yt-dlp (des centaines de sites supportés) si une URL
  arbitraire était acceptée.
- QueueService.ts : file en mémoire, N téléchargements simultanés
  (MAX_CONCURRENT_DOWNLOADS), annulation via AbortSignal, nettoyage du
  dossier de sortie après échec/annulation ou après livraison du fichier.
- ytDlpRunner.ts : étendu pour le suivi ligne par ligne de stdout
  (progression) et l'annulation (AbortSignal passé à child_process.spawn).
- routes/queue.ts : POST/GET /api/queue, DELETE /api/queue/:id,
  GET /api/queue/:id/file (streaming + nettoyage après envoi).

45 nouveaux tests (59 au total) : fonctions pures, services (vrai système
de fichiers temporaire, yt-dlp mocké), routes. Vérifié aussi en conditions
réelles (serveur démarré localement) : validation d'URL, ajout en file,
et passage correct à l'état "failed" + nettoyage quand le binaire yt-dlp
est absent (ENOENT).

Empilée sur feature/channel-discovery (réutilise ytDlpRunner.ts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
kyuno merged commit 6881c89568 into feature/channel-discovery 2026-09-16 09:30:00 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: kyuno/youtubeDownloader#2
No description provided.