0d46a9a0995fbb919f43c33097b6bdee8332f93f
Ombrora YTDLP
Interface web de téléchargement de vidéos via yt-dlp, avec file d'attente persistante, suivi en base de données et liens de téléchargement sécurisés.
Fonctionnement
- L'utilisateur colle une URL dans l'interface web. Elle est immédiatement analysée via un probe
yt-dlp -J(POST /api/probe), qui détermine les qualités, sous-titres et durée réellement disponibles pour cette vidéo. - Les options de téléchargement (format, qualité, sous-titres, découpe, qualité audio MP3) affichées à l'utilisateur sont dérivées de ce probe — la soumission est bloquée tant qu'il n'a pas réussi.
- La demande est enregistrée en base (statut
PENDING). - Le worker (Node.js, arrière-plan, supervisé par pm2) dépile les jobs et exécute
yt-dlpen parallèle (concurrence configurable). - Le fichier téléchargé est stocké localement ; un token signé (24h) est généré.
- L'utilisateur est redirigé vers une page de statut qui se rafraîchit jusqu'à ce que le fichier soit prêt.
- Un cron quotidien supprime les fichiers expirés et marque les entrées
FILE_DELETED— la DB conserve l'historique complet.
Stack technique
| Couche | Technologie |
|---|---|
| Framework | Next.js 16 (App Router) |
| Base de données | MariaDB 11 via Prisma 7 |
| Frontend | React 19, TypeScript, Tailwind CSS v4 |
| i18n | next-intl (EN, FR, ES, IT), routing par [locale] |
| Thème | next-themes (clair/sombre) |
| Analytics | PostHog (cookieless) |
| Worker | Node.js (tsx), supervisé par pm2 |
| Conteneur (dev) | Docker Compose |
Prérequis
- Node.js 20+
- Docker & Docker Compose (pour MariaDB en développement)
yt-dlp,ffmpegetffprobe(binaires précompilés dans./bin/ou dans lePATH)
Démarrage rapide
# 1. Cloner le dépôt
git clone <url> ombrora-ytdlp && cd ombrora-ytdlp
# 2. Copier et remplir les variables d'environnement
cp .env.example .env
# 3. Démarrer MariaDB
docker-compose up -d
# 4. Installer les dépendances
npm install
# 5. Appliquer les migrations Prisma
npm run db:migrate
# 6. Lancer le serveur Next.js
npm run dev
# 7. Dans un autre terminal, lancer le worker
npm run worker
L'interface est accessible sur http://localhost:3000.
Variables d'environnement
| Variable | Requis | Exemple | Description |
|---|---|---|---|
DATABASE_URL |
oui | mysql://ombrora:ombrora@localhost:3306/ombrora |
Connexion MariaDB |
STORAGE_PATH |
oui | /var/www/ombrora/storage |
Répertoire de stockage des fichiers téléchargés |
NEXT_PUBLIC_BASE_URL |
oui | https://example.com |
URL publique du site, utilisée pour le SEO (canonical, OpenGraph, JSON-LD, sitemap) |
BIN_DIR |
non | ./bin |
Répertoire contenant yt-dlp, ffmpeg et ffprobe (défaut : ./bin) — absent de .env.example, à ajouter manuellement si le défaut ne convient pas |
Scripts npm
| Script | Description |
|---|---|
npm run dev |
Serveur de développement Next.js |
npm run build |
Build de production |
npm start |
Serveur de production |
npm test |
Tests Jest |
npm run worker |
Worker de téléchargement (boucle de polling, exécution directe/dev) |
npm run worker:pm2:start |
Démarre le worker sous pm2 (ecosystem.config.cjs), avec auto-restart |
npm run worker:pm2:stop |
Arrête le worker géré par pm2 |
npm run worker:pm2:restart |
Redémarre le worker géré par pm2 |
npm run worker:pm2:status |
Affiche l'état du process ombrora-worker |
npm run worker:pm2:logs |
Affiche les logs du worker géré par pm2 |
npm run worker:cleanup |
Expire et supprime les fichiers anciens (usage cron) |
npm run db:migrate |
Crée et applique les migrations Prisma (dev, interactif) |
npm run db:migrate:deploy |
Applique les migrations en attente (production, non interactif) |
npm run db:generate |
Régénère le client Prisma |
npm run deploy |
Déploiement complet sur o2switch (voir section ci-dessous) |
Configuration
Les paramètres applicatifs sont centralisés dans config/app.config.ts :
DOWNLOAD_LINK_TTL_HOURS: 24 // Durée de validité du token de téléchargement
WORKER_CONCURRENCY: 3 // Téléchargements parallèles maximum
WORKER_POLL_INTERVAL_MS: 10000 // Intervalle de polling du worker (ms)
RATE_LIMIT_MAX: 5 // Soumissions max par IP par fenêtre
RATE_LIMIT_WINDOW_MS: 3600000 // Fenêtre de rate-limit des soumissions (1h)
PROBE_RATE_LIMIT_MAX: 20 // Analyses (probe) max par IP par fenêtre
PROBE_RATE_LIMIT_WINDOW_MS: 3600000 // Fenêtre de rate-limit du probe (1h)
PROBE_TIMEOUT_MS: 20000 // Timeout du probe yt-dlp -J (ms)
API
| Méthode | Endpoint | Description |
|---|---|---|
POST |
/api/probe |
Analyse une URL via yt-dlp -J. Corps JSON : { url }. Retourne les qualités, sous-titres et durée réellement disponibles pour la vidéo, ou une erreur (422 si l'analyse échoue, 429 si rate-limit dépassé). |
POST |
/api/downloads |
Soumet une URL. Corps JSON : { url, format, quality, subtitles, subtitleLangs?, clipStart?, clipEnd?, audioQuality?, extraArgs? }. Retourne { uuid }. |
GET |
/api/downloads/:uuid |
Statut d'un téléchargement. Retourne { status, fileName, fileSize, downloadToken?, tokenExpiresAt?, errorMsg? }. |
GET |
/api/download/:token |
Téléchargement du fichier (token à usage unique, 24h). |
Architecture
src/
├── app/
│ ├── [locale]/
│ │ ├── layout.tsx # Header, thème, next-intl, JSON-LD, PostHog
│ │ ├── page.tsx # Accueil (hero, formulaire, sections SEO)
│ │ ├── [slug]/page.tsx # Pages SEO par plateforme (youtube-downloader, etc.)
│ │ ├── status/[uuid]/page.tsx # Page de suivi
│ │ └── supported-sites/page.tsx # Liste des sites supportés par yt-dlp
│ ├── sitemap.ts # Génération du sitemap.xml
│ └── api/
│ ├── downloads/route.ts # POST — création
│ ├── downloads/[uuid]/route.ts # GET — statut
│ ├── download/[token]/route.ts # GET — téléchargement
│ └── probe/route.ts # POST — analyse yt-dlp -J
├── components/
│ ├── SubmitForm.tsx # Formulaire de soumission (options dérivées du probe)
│ ├── StatusView.tsx # Vue de suivi (polling)
│ ├── Header.tsx, LanguageSwitcher.tsx, ThemeToggle.tsx
│ ├── HowItWorksSection.tsx, ReassuranceSection.tsx, SupportedPlatformsSection.tsx
│ └── FaqSection.tsx, FaqAccordion.tsx, SupportedSitesBrowser.tsx
├── i18n/
│ ├── routing.ts # Locales, préfixes d'URL
│ └── request.ts # Config next-intl côté serveur
├── proxy.ts # Middleware next-intl (détection/routage locale)
└── lib/
├── prisma.ts # Client Prisma (singleton)
├── rate-limit.ts # Factory createRateLimiter (downloads + probe)
├── token.ts # Génération/validation de tokens
├── ytdlp.ts # Construction des arguments/commande yt-dlp
├── ytdlp-options.ts # Formats/qualités/langues proposés
├── ytdlp-probe.ts # Analyse yt-dlp -J d'une URL
├── downloader-platforms.ts # Données des pages SEO par plateforme
└── supported-sites.ts # Liste des sites supportés par yt-dlp
worker/
├── index.ts # Boucle de polling principale
├── processor.ts # Exécution de yt-dlp, mise à jour DB
└── cron-cleanup.ts # Nettoyage des fichiers expirés
messages/ # Traductions (en.json, fr.json, es.json, it.json)
ecosystem.config.cjs # Config pm2 du process "ombrora-worker"
prisma/
└── schema.prisma # Modèles : Download, DownloadToken
Déploiement (o2switch / Passenger)
Contraintes spécifiques à l'hébergement mutualisé
- Pas de compilation sur le serveur :
yt-dlp,ffmpegetffprobedoivent être des binaires précompilés pour la plateforme cible, placés dansBIN_DIR. node_modulesunique : Passenger ne crée qu'un seulnode_modulesà la racine. Le projet n'a qu'un seulpackage.json(pas de sous-dossier frontend séparé à synchroniser).- Worker : Passenger ne supervise que l'app Next.js. Le worker est un process à part, maintenu vivant par pm2 (auto-restart en cas de crash), à la manière de Passenger pour l'app web.
Étapes de déploiement
- Uploader les sources (hors
node_modules,.env,storage/). - Déposer
yt-dlpetffmpegdansBIN_DIR. - Remplir
.env.prodavec les valeurs de production (non versionné, à créer/mettre à jour manuellement sur le serveur). - Via cPanel > "Setup Node.js App" : créer l'app Node une première fois pour que Passenger et le nodevenv soient configurés (pointer sur le dépôt).
- En SSH, dans l'environnement Node fourni par cPanel (celui activé par le lien "Enter to the virtual environment" de cPanel) :
Ce script (
npm run deployscripts/deploy.sh) enchaîne : copie de.env.prodvers.env,npm install, génération du client Prisma, application des migrations en attente (prisma migrate deploy),npm run build, puis démarrage/redémarrage du worker sous pm2 (pm2 startOrRestart+pm2 save, pour persister la liste des process en vue d'unpm2 resurrectaprès reboot). - Redémarrer l'app Next.js via le bouton "Restart" de cPanel > "Setup Node.js App" pour que Passenger recharge le nouveau build (le script ne pilote pas Passenger, qui est géré en dehors du SSH/nodevenv).
- Configurer un cron cPanel pour
npm run worker:cleanupune fois par jour (suppression des fichiers expirés). pm2 gère lui-même le redémarrage du worker en cas de crash ; il n'y a donc plus besoin de cron de supervision dédié. - Si l'hébergeur redémarre le serveur, relancer
pm2 resurrect(ounpm run worker:pm2:startsi la sauvegardepm2 saven'a pas été faite) pour reprendre le worker.
Pour les déploiements suivants, seule l'étape 5 (npm run deploy) et l'étape 6 (redémarrage Passenger) sont nécessaires.
Tests
npm test
Tests Jest (environnement Node, transpilation SWC). Les fichiers de test sont dans **/__tests__/**/*.test.ts.
Licence
Usage interne — non distribué.
Languages
TypeScript
98.8%
JavaScript
0.6%
Shell
0.5%
CSS
0.1%