Outil web pour télécharger une vidéo (ou son audio en MP3) depuis YouTube, Instagram,
TikTok, X, Vimeo et les 1000+ sites gérés par yt-dlp. Matt colle un lien, choisit la
qualité, le serveur télécharge, puis il enregistre le fichier sur son appareil. Créé le
2026-09-24 parce que les outils en ligne ne marchaient plus et que YouTube bloque l'IP
du VPS sur certaines vidéos (d'où la gestion de cookies intégrée).
aios-ytdl.service (fichier versionné dans l'app : apps/ytdl/aios-ytdl.service, installé par systemctl link, Restart=always)
/root/workspace/apps/ytdl/backend/root/workspace/Telechargements/ (visible dans l'espace de travail)/root/aios/data/ytdl/ (jobs.json = historique, cookies.txt = cookies YouTube chmod 600, access_code = code d'accès chmod 600)
backend/downloader.py : coeur yt-dlp (info, download avec progression, cookies). Appelle le binaire yt-dlp (donc la config globale /root/.config/yt-dlp/config
s'applique : --remote-components ejs:github + clients par défaut).
backend/app.py : FastAPI (API JSON + sert l'UI), file d'attente à 1 worker(un téléchargement à la fois), historique persistant, anti brute-force sur le code.
backend/dl.py : CLI pour l'AIOS (même coeur).backend/static/index.html : UI une page (vanilla JS), mobile-first, thème auto clair/sombre.GET / : l'UI. GET /api/health : {ok, jobs, active, cookies, yt_dlp, access_code_set}.POST /api/login {code} : pose le cookie ytdl_auth (180 jours). POST /api/logout. GET /api/me.POST /api/info {url} : titre, miniature, durée, qualities (hauteurs dispo + taille estimée), client_profile, used_cookies. Erreur 400 {error, needs_cookies, cookies_rejected}.
POST /api/jobs {url, mode: video|audio, height: 2160|1440|1080|720|480|360|null, ...} : crée un téléchargement (201). GET /api/jobs, GET /api/jobs/{id}, POST /api/jobs/{id}/retry.
GET|HEAD /api/jobs/{id}/file : le fichier (Content-Disposition attachment).DELETE /api/jobs/{id}[?keep_file=1] : annule si en cours, efface l'entrée (et le fichier).GET /api/cookies, POST /api/cookies (multipart file), DELETE /api/cookies.```bash
cd /root/workspace/apps/ytdl/backend
python3 dl.py info "<url>" # métadonnées + qualités (JSON)
python3 dl.py get "<url>" # mp4 1080p max (H.264 + AAC) dans Telechargements/
python3 dl.py get "<url>" --height 720 # 720p
python3 dl.py get "<url>" --max # meilleure qualité (4K possible, mp4)
python3 dl.py get "<url>" --audio # mp3
python3 dl.py get "<url>" --out /chemin/dossier # ailleurs
python3 dl.py cookies # statut du cookies.txt
```
Code de sortie 3 = bloqué par YouTube (cookies requis ou à renouveler) : demander à Matt
un cookies.txt (voir ci-dessous), ne pas insister en boucle.
1. Profils de clients essayés dans l'ordre, SANS cookies d'abord :
default (= visionos,web au 2026-09-24) puis tv_simply,web_embedded.
Le client web seul est plafonné à 360p (expérience SABR), tv échoue.
Réglable par env YTDL_CLIENTS_ANON / YTDL_CLIENTS_AUTH (; entre profils).
2. Si l'erreur est un blocage de connexion ("Sign in to confirm you're not a bot",
LOGIN_REQUIRED, vidéo privée, limite d'âge, membres) et qu'un cookies.txt est
présent : nouvel essai AVEC cookies (profils default puis web_embedded,mweb).
Sans cookies : erreur needs_cookies et l'UI ouvre la section Cookies avec le mode
d'emploi (extension Get cookies.txt LOCALLY, fenêtre privée, compte secondaire,
fermer sans se déconnecter). Cookies présents mais refusés : cookies_rejected.
3. Format vidéo : bv*[height<=H][vcodec^=avc1]+ba[acodec^=mp4a] puis replis, fusion mp4
(H.264 + AAC, lisible partout). "Max" = bv*+ba/b (AV1/VP9 + Opus dans mp4, ffmpeg
6.1 sait le muxer). Audio = ba/b converti en mp3 (qualité 0).
4. Le PO token provider (Docker bgutil-provider, port 4416) et deno restent nécessaires
pour YouTube : voir mémoire yt-dlp-youtube-deno-fix.
5. yt-dlp réécrit cookies.txt à chaque run (rotation) : un verrou empêche deux processus
dessus en même temps, et le worker unique sérialise les téléchargements.
YTDL_ACCESS_CODE dans /root/aios/.env si présent, sinon le fichier data/ytdl/access_code. Le changer invalide toutes les sessions (redémarrer le service).
app.py / downloader.py : systemctl restart aios-ytdl (l'UI est relue à chaque requête, pas besoin de restart pour index.html).
proxy_buffering off et client_max_body_size 5m ajoutés à la main dans /etc/nginx/sites-enabled/dl.panelbay.com.conf (gros fichiers en streaming, upload cookies).
Telechargements/ : le bouton Supprimer de l'UI efface aussile fichier serveur. Rien n'est purgé automatiquement.
jamais le copier dans le workspace ni le citer dans le chat.
queued/running au moment d'un restart passe en erreur "Interrompu" (relancer).aios-ytdl (8370),exposé sur https://dl.panelbay.com. Gestion cookies YouTube (repli automatique). Testé :
info + mp4 480p + mp3 sur vidéo de contrôle. Config yt-dlp globale corrigée en parallèle
(player_client=default,tv_simply au lieu de web,tv qui plafonnait à 360p).