17 KiB
Dr Nexum — pipeline image→vidéo (Atlas Cloud, Seedance 2.0 Fast)
Sphère : Nyora / Dr Nexum
Script : hermes-nabil VPS, /data/dr_nexum/atlas_i2v.py
Statut : PIPELINE VALIDÉ — 3/3 clips confirmés harmonieux (480p/4s, generate_audio=False). Prêt pour production.
Config gagnante
- 480p, 4s,
generate_audio=False - Prompt minimal et littéral : décrire uniquement le mouvement physique observable dans l'image, ne jamais mentionner un objet ou un détail absent/ambigu
Piège identifié : prompt trop détaillé → hallucination
Testé en 720p/5s avec un prompt plus détaillé : le modèle a fait "surgir" des t-shirts qui n'étaient pas dans l'image d'origine. Cause probable : un prompt qui décrit des éléments non ancrés visuellement pousse Seedance à les générer plutôt qu'à les ignorer. Rester strictement descriptif du mouvement visible corrige le problème.
Coûts réels confirmés (facturation Atlas Cloud)
| Config | Tokens | Coût |
|---|---|---|
| 720p / 5s | 108 900 | 0,79 $ |
| 480p / 4s | 40 594 | ~0,30 $ (ratio proportionnel) |
480p/4s est nettement plus économique pour un ratio qualité déjà jugé satisfaisant. Sur un budget PAYG de 25 $, largement de quoi itérer en 480p/4s (~80 clips possibles).
Reste à faire
TesterFAIT le 21/07, validéhq720.jpgetimages__3_.jpeg- Bascule en production sur hermes-nabil : le script y tourne déjà nativement, aucune étape supplémentaire nécessaire — utiliser mcp-vps +
docker execpour chaque nouvel épisode plutôt que le sandbox Claude - Nettoyage : images/clips de test hébergés temporairement sur filebin.net (bin
nabil-dr-nexum-test, expire automatiquement le 28/07) — contenu Dr Nexum non encore publié, accessible publiquement jusqu'à expiration. Aucune action requise si le contenu n'est pas sensible, sinon supprimer manuellement avant expiration.
Contexte d'exécution
Faute de connecteur mcp-vps disponible lors des tests, l'appel à l'API Atlas Cloud a été fait en direct depuis un sandbox Claude plutôt que via SSH sur le VPS. Le script atlas_i2v.py reste néanmoins déployé et fonctionnel sur hermes-nabil pour la bascule en production.
Piège : /data est un chemin container, pas host
En SSH direct sur le VPS (hors container), /data/dr_nexum/... n'existe pas — c'est le chemin vu depuis l'intérieur du container hermes-nabil (bind-mount host réel : /home/claude-oversight/hermes-nabil/data, appartenance root). Éditer avec nano /data/... sur l'hôte ouvre un buffer vide sans jamais pouvoir sauvegarder, et un cat >> direct échoue en No such file or directory.
Fix : toute lecture/écriture sous /data sur hermes-nabil passe par docker exec :
docker exec -i hermes-nabil bash -c "mkdir -p /data/dr_nexum && cat >> /data/dr_nexum/JOURNAL.md" << 'EOF'
...
EOF
Cohérent avec la règle déjà connue pour SOUL.md sur ce même container ("root, via docker exec").
Incident résolu : connecteur mcp-vps déconnecté (21/07/2026)
Sphère : infra transverse (Contabo VPS, linux-mcp-vps + cloudflared-mcp-vps)
Symptôme
Connecteur mcp-vps affiché "déconnecté" côté réglages Claude, tentative de connexion échouant systématiquement. Une alerte Telegram (NewSessionAlertMiddleware, déjà en place) confirmait qu'une tentative de handshake démarrait bien côté serveur, sans jamais se finaliser côté Claude.
Diagnostic (dans l'ordre, fausses pistes incluses — utile pour ne pas les rejouer)
- Fausse piste : nom du container.
docker logs mcp-vps→No such container. Les vrais noms sontlinux-mcp-vps(serveur MCP) etcloudflared-mcp-vps(tunnel). - Fausse piste : piège lifespan façon mcp-nas. Testé
/mcpdirectement → 404, mais c'était un test au mauvais chemin (le endpoint réel est préfixé parMCP_PATH_SECRET, jamais/mcpnu). Les logs montraient déjà des200 OKsur le vrai chemin — pas de piège lifespan ici. - Piste réelle mais insuffisante : tunnel Cloudflare instable.
docker logs cloudflared-mcp-vpsmontrait des échecs QUIC récurrents ("Application error 0x0", "no recent network activity") sur 9 jours d'uptime, version 2026.7.1 obsolète. Undocker restart cloudflared-mcp-vpsa stabilisé le tunnel (4 connexions QUIC propres, aucune erreur) — nécessaire mais pas suffisant, la connexion échouait encore après. - Cause racine : flux OAuth incomplet côté serveur MCP. Les endpoints
/.well-known/oauth-authorization-serveret/.well-known/oauth-protected-resourceétaient corrects (bon hostname public), mais :- Pas de
registration_endpointdéclaré → Claude ne peut pas faire de Dynamic Client Registration (RFC 7591) /authorizeet/tokenn'existaient pas du tout comme routes (seul/registerexistait, en stub)- Message d'erreur Claude explicite reçu à ce moment : "L'enregistrement automatique du client n'est pas pris en charge par mcp-vps. Modifiez le connecteur et ajoutez un OAuth Client ID."
- Pas de
Fix appliqué
Client OAuth statique (client_id = claude-vps-mcp, token_endpoint_auth_method: none) plutôt que du DCR dynamique — cohérent avec la vraie protection du serveur qui est le chemin secret MCP_PATH_SECRET dans l'URL, pas un token vérifié en base. Ajout dans /app/linux_mcp_server.py :
/authorize(GET) : auto-approuve (single-user), émet un code éphémère (TTL 5 min), redirige avec PKCE (S256) supporté/token(POST) : échangeauthorization_code/refresh_tokencontre unaccess_token(TTL 30j) — token jamais vérifié ailleurs dans le code, sert uniquement à faire aboutir le flux OAuth- Métadonnées
oauth-authorization-servercomplétées :grant_types_supported,code_challenge_methods_supported,token_endpoint_auth_methods_supported - Client ID
claude-vps-mcprenseigné dans le connecteur côté réglages Claude
Patch appliqué en live via docker exec + script Python (remplacement de bloc par chaîne exacte) — fonctionne, mais vit uniquement dans la couche writable du container.
⚠️ Action restante obligatoire
Le patch n'est PAS dans l'image Docker ni dans le repo source — un docker restart simple le garde (couche writable persistante), mais un rebuild ou --force-recreate l'effacera. À reporter dans le fichier source du repo (probablement bolbol/linux-mcp-vps ou équivalent sur Gitea) dès que le NAS est de retour, puis rebuild l'image proprement avec le patch inclus en dur.
Piège méthodologique à retenir
Toute commande sed/cat/edition de fichier sur ce VPS doit systématiquement passer par docker exec linux-mcp-vps ... ou docker exec hermes-nabil ... — jamais directement sur l'hôte. Un assert de correspondance de texte exacte peut échouer sur un détail invisible (ligne vide manquante, \r\n vs \n) : toujours vérifier avec cat -A avant de retenter un patch par remplacement de chaîne.
Piège : Atlas Cloud ne suit pas les redirections HTTP sur --image URL
Testé le 21/07 en passant une URL de partage temporaire (filebin.net) directement en --image : échec systématique en 400 InvalidParameter.FormatUnsupported. Le script ne fait que transmettre l'URL telle quelle à l'API (submit() ne télécharge rien lui-même quand c'est déjà une URL http/https) — c'est donc Atlas Cloud qui va chercher l'image, et son fetcher ne suit pas les redirections 302. Un hébergeur qui redirige vers une URL S3 signée (filebin.net, et probablement d'autres) fait échouer la requête : Atlas Cloud lit la petite réponse de redirection au lieu du JPEG.
Fix : toujours résoudre la redirection en amont et passer l'URL finale (ex. l'URL S3 signée) directement en --image, jamais l'URL de la page d'hébergement. Vérifiable en amont avec curl -o /dev/null -w '%{redirect_url}' <url>.
Limite à connaître : une URL S3 signée expire vite (900s observé chez filebin.net) — à générer juste avant l'appel, pas à l'avance.
3 clips testés en 480p/4s — coûts identiques
hq720.jpg et images__3_.jpeg testés le 21/07 avec la config gagnante (via mcp-vps, sans upload manuel — images hébergées temporairement puis passées en URL). Coût confirmé identique au premier test : 40 594 tokens par clip en 480p/4s, peu importe l'image source — cohérent avec une tarification basée sur la durée/résolution, pas sur le contenu.
Validé par Nabil le 21/07 : les 2 clips confirmés harmonieux, cohérents avec le premier test. Les 3 tests (1 sandbox + 2 via mcp-vps) sont concluants. Pipeline prêt pour bascule en production sur hermes-nabil.
Montage test final (21/07)
Les 2 clips validés (clip_hq720.mp4, clip_images3.mp4) partagent exactement les mêmes specs de sortie Seedance (h264, 864×496, 24fps) — concaténation directe possible via ffmpeg -f concat -c copy, sans ré-encodage, donc sans perte de qualité ni temps de calcul.
docker exec hermes-nabil bash -c "printf \"file '/data/dr_nexum/out/clip_hq720.mp4'\nfile '/data/dr_nexum/out/clip_images3.mp4'\n\" > /data/dr_nexum/out/concat_list.txt && ffmpeg -y -f concat -safe 0 -i /data/dr_nexum/out/concat_list.txt -c copy /data/dr_nexum/out/dr_nexum_test_final.mp4"
Résultat : dr_nexum_test_final.mp4, 8s, 2,6 Mo — validé comme premier montage test bout-en-bout du pipeline Dr Nexum.
Note montage final réel : ce concat brut (-c copy, cut sec) est suffisant pour un test. Le montage définitif (transitions, étalonnage, sous-titres, voix ElevenLabs) reste porté par video-use — encore à installer, cf. pipeline prévu à l'origine (étape 4, non démarrée).
Voix Dr Nexum — ElevenLabs (21/07)
Clé : ELEVENLABS_API_KEY ajoutée à /data/.env sur hermes-nabil (déposée par Nabil via /tmp/ELEVENLABS.apikey sur l'hôte VPS, transférée dans le container sans jamais transiter en clair dans les logs/outputs). ⚠️ Fichier /tmp/ELEVENLABS.apikey toujours présent sur l'hôte (root-owned, claude-oversight n'a pas de sudo NOPASSWD sur ce host contrairement à une note antérieure — à corriger dans la mémoire). Nabil doit le supprimer manuellement (rm /tmp/ELEVENLABS.apikey).
Voix retenue pour ce test : Michael (voice_id IbTlccXlWxGVwnbGUHEd), parisienne, chaude/confiante, taggée "idéal pour assistants IA" dans la bibliothèque partagée ElevenLabs — pas encore validée par Nabil comme voix définitive Dr Nexum, juste un premier choix cohérent. Modèle utilisé : eleven_multilingual_v2.
API : POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id}, header xi-api-key, body {text, model_id, voice_settings:{stability, similarity_boost}} → réponse = bytes MP3 direct (pas de polling comme Atlas Cloud).
Piège : décalage audio/vidéo (attendu, pas encore résolu proprement)
Le script de test (~45 mots) dure 17,45s en voix, contre 12s de vidéo (3 clips × 4s). Pas de synchronisation réelle à ce stade — fix temporaire appliqué : étirer le dernier plan en image fixe via ffmpeg -filter_complex tpad=stop_mode=clone:stop_duration=Ns pour couvrir la durée audio, avec -shortest pour ne pas dépasser.
ffmpeg -y -i dr_nexum_test_final.mp4 -i voix_test.mp3 \
-filter_complex '[0:v]tpad=stop_mode=clone:stop_duration=6[v]' \
-map '[v]' -map 1:a -c:v libx264 -pix_fmt yuv420p -c:a aac -shortest \
dr_nexum_test_with_voice.mp4
Ce n'est pas la solution finale. Le plan d'origine (voir en-tête du pipeline) prévoit video-use + ElevenLabs Scribe pour un montage guidé par la transcription word-level (coupes calées sur le texte, pas un simple gel d'image). Toujours à installer — reste la vraie prochaine étape avant tout épisode réel.
Leçon capitalisée : toujours persister un clip généré immédiatement
Le premier clip validé "harmonieux" (image xiaomi-robotics-1-01-hero.jpg, prompt "The robotic arm continues its packing motion into the open suitcase, smooth mechanical movement, static camera, realistic robotics demo footage", 480p/4s) avait été généré dans le sandbox Claude d'une session précédente et jamais copié sur /data/dr_nexum/out/ — perdu à la fin de cette session, récupéré seulement parce que Nabil l'avait sauvegardé localement. Règle à suivre désormais : tout clip Atlas Cloud validé doit être docker cp/transféré vers /data/dr_nexum/out/ sur hermes-nabil immédiatement, jamais laissé uniquement dans un sandbox Claude éphémère.
Piège capitalisé : accents manquants dans le texte envoyé à ElevenLabs
Le premier essai de voix (voir plus haut) a été généré avec un texte sans accents français ("Generer", "quantite", "entrepot"...) — erreur introduite par Claude en construisant le script d'appel API, pas une limite d'ElevenLabs. Résultat : articulation dégradée, syllabes qui sautent. Même famille de bug que celui déjà corrigé sur les SOUL.md Hermes (priming ASCII), mais réapparu ici dans un contexte différent (script ponctuel, pas un prompt système).
Règle à appliquer systématiquement : tout texte français destiné à un TTS (ElevenLabs ou autre) doit être écrit avec les accents corrects, transmis en UTF-8 de bout en bout, et vérifié avant l'appel API (grep ou cat du fichier script juste avant exécution, pas seulement après).
Réglages voice_settings ajustés en même temps (à valider sur écoute, pas encore confirmé si ça a un effet mesurable séparé de la correction des accents) : stability 0.5→0.65, style 0.0 explicite, use_speaker_boost True.
Piste future (Mac M5 Pro, septembre) : avatar Dr Nexum open-source
Recherche du 21/07 suite à l'abandon de HeyGen (crédits limités + coût API automatisation imprévisible).
Repo identifié : github.com/PunithVT/ai-avatar-system — plateforme avatar IA 100% open-source et self-hosted. Pipeline : photo → clone de voix → Whisper (STT) → Claude/GPT/Ollama (LLM) → Chatterbox TTS (multilingue, 23 langues) → MuseTalk (lip-sync). Correspond exactement au besoin (identité fixe Dr Nexum + voix, zéro abonnement).
Blocage confirmé : MuseTalk nécessite un GPU Nvidia (benchmark officiel sur Tesla V100). Le VPS Contabo actuel (6 vCPU, 12 Go RAM, pas de GPU) ne peut pas le faire tourner en temps utile — même conclusion que le test Bonsai 27B (LLM local CPU-only inutilisable).
Décision (21/07) : attendre le MacBook M5 Pro (septembre) plutôt que de louer du GPU cloud ou repartir sur une solution SaaS. ⚠️ À vérifier à l'arrivée du Mac : ces outils ciblent CUDA/Nvidia en priorité, la compatibilité Apple Silicon (MPS) n'est pas confirmée — tester avant de construire dessus, ne pas supposer que ça marche.
Approfondissement (21/07) : explication des briques + piste low-cost immédiate
Rôle de chaque composant identifié
- Whisper (OpenAI) : speech-to-text. Utile pour transcription live ou timestamps mot-par-mot. Inutile pour Dr Nexum (script déjà écrit, ElevenLabs a sa propre fonction équivalente).
- Claude/GPT/Ollama (dans
ai-avatar-system) : LLM conversationnel pour chat en direct. Hors-sujet pour Dr Nexum (script déjà généré via Bifrost/DeepSeek). - Chatterbox TTS (Resemble AI) : TTS open-source, clonage de voix zero-shot, 23 langues. Alternative gratuite à ElevenLabs — besoins matériels non vérifiés, à tester avant d'en dépendre.
- MuseTalk (Tencent) : lip-sync temps réel, bouche uniquement, exige GPU Nvidia (V100 en benchmark officiel, fonctionne aussi RTX 20/30 séries).
- InfiniteTalk (MeiGen-AI, Apache 2.0) : génération vidéo parlante plus complète (tête, épaules, expressions, pas juste bouche), longueur illimitée sans dérive d'identité. Basé sur Wan2.1 (modèle vidéo 14B). Testé avec succès en conditions réelles sur RTX 3090 (30s de génération pour un clip 3s).
Correction architecturale importante
ai-avatar-system (présenté précédemment comme "le plus complet") est conçu pour la conversation en temps réel (streaming, interruption, WebRTC) — inadapté à un besoin "script écrit à l'avance → fichier vidéo". Pour Dr Nexum, utiliser InfiniteTalk directement en mode batch (image + audio → .mp4), sans la couche conversationnelle, est la bonne forme d'outil.
Piste low-cost immédiate (pas besoin d'attendre le Mac)
Location GPU à l'usage, facturée à la seconde : RunPod, RTX 3090 (24 Go) ≈ 0,46$/heure, zéro coût GPU éteint. Estimation réaliste par épisode Dr Nexum (démarrage pod + chargement modèles 2-5 min + génération 1-3 min/clip + extinction) : 15-30 min de location, quelques centimes à <1$/épisode. Nettement sous le coût HeyGen, sans risque d'abonnement.
Coût réel = temps d'ingénierie, pas le GPU : nécessite une image Docker (CUDA/PyTorch/flash_attn compatibles — piège connu signalé dans le README InfiniteTalk), un stockage réseau persistant RunPod pour les poids du modèle (éviter re-téléchargement à chaque run), et un script d'orchestration (probablement piloté depuis hermes-nabil via l'API RunPod) : spin up → génération → récupération → extinction immédiate.
Décision (21/07) : chantier identifié et documenté, mais pas démarré cette session — en attente de décision de Nabil (lancer maintenant vs garder pour le Mac de septembre).