Mon homelab qui génère des vidéos IA la nuit

Comment j’ai construit une pipeline d’automatisation complète pour iartshorts — un orchestrateur Python maison, 100% offline.

🔒 100% offline, zéro cloud. Tout tourne localement : LLMs, génération d’images, vidéo, TTS, recherche Wikipedia. Aucun appel API externe, aucune donnée qui quitte mon serveur.

Le Projet : Donnez Vie aux Tableaux

iartshorts (et aiartshorts en anglais) est une chaîne de shorts verticaux qui transforme des portraits de peintures en vidéos parlantes. Le personnage du tableau s’anime, raconte son histoire, ou celle de l’artiste qui l’a peint — le tout dans un ton un peu décontracté, en première personne.

Le but : une fois mise au point, tout automatiser. De la recherche historique à l’upload sur YouTube Shorts, TikTok et Instagram Reels. La seule intervention humaine pendant le traitement est la validation ou le rejet du résultat.

Mais pour que ça tourne, il faut du matériel.


🖥️ Homelab IA

3 GPUs · 192 GB VRAM · ~1050W Total Homelab sous Proxmox — GPU passthrough vers LXC Ubuntu
📋
Carte Mère
ASRock Rack ROMED8-2T
AMD EPYC single CPU, PCIe 4.0
CPU
AMD EPYC 7763
64 cœurs — choisi pour les lanes PCIe
💾
RAM
128 GB DDR4 ECC Registered
GPUs — 192 GB VRAM Total
🟢
Inférence LLM
2× RTX 4090D
Moddées à 48 GB VRAM chacune · 300W limit · vLLM/SGLANG TP2
🟠
Gén. Image & Vidéo
1× RTX 6000 Pro Blackwell
96 GB VRAM · limitée à 450W · Silencieuse & Efficace · ComfyUI
💡 Pourquoi l’EPYC ? Pas pour la puissance de calcul — pour les lignes PCIe nécessaires pour faire tourner 3 GPUs en simultané sans soucis.

💡 Perf LLM : 2× 4090D en Tensor Parallel 2 ≈ RTX 6000 Pro seule. Mais la 6000 Pro brille en génération image/vidéo et tourne beaucoup plus silencieusement.

La Stack Logicielle

Tout tourne sur Proxmox, puisque c’est aussi mon homelab. Un unique LXC Ubuntu héberge tout ce qui a besoin d’accéder aux GPUs.

Les LLMs

ModèleUsage
Qwen3.6-27B-FP8Daily driver (code + pipeline)
Qwen3.5-122B-AWQAncien daily driver
Gemma4 31BPonctuel

Les modèles sont gérés par llama-swap + un script Python maison qui génère la config depuis mon dossier de stockage de modèles. Les moteurs d’inférences tournent dans des conteneurs Docker (vLLM, SGLANG, llama.cpp).

ComfyUI

Toute la génération image/vidéo passe par ComfyUI, avec :

  • Flux Klein 9b pour la restauration de peinture et la transformation réaliste
  • Qwen TTS pour la synthèse vocale
  • LTX2.3 pour la génération de vidéos lip-sync (AudioSync)
  • Wan2.2 pour les transitions et animations sans paroles

La Pipeline :

10 Étapes

D’une peinture portrait à une vidéo courte prête à être publiée — entièrement automatisé

🖼️ Sélection aléatoire parmi ~30 000 peintures → ~20 par nuit
🔍
Étape 0
Préparation
Vision IA analyse le portrait : genre, détection nudité → filtrage SFW.
Qwen3.6-27B Vision · FFmpeg
📝
Étape 1
Script
Recherche hors-ligne sur Wikipedia ZIM concernant l’auteur du tableau et le personnage représenté (si identifiable). Le LLM extrait les faits clés, anecdotes et contexte → puis génère le script narratif à la 1ère personne (max 150 mots, ton espiègle). Sortie structurée via Pydantic.
Qwen3.6-27B · libzim · Pydantic
🎙️
Étape 2
Audio
Synthèse vocale en français ET en anglais. Voix naturelle du point de vue du portrait.
Qwen TTS · ComfyUI
🎨
Étape 3
Image Restaurée
Restauration IA de la peinture. Répare les fissures, ravive les couleurs, pose inchangée.
Flux Klein · ComfyUI
📸
Étape 4
Image Réaliste
Transformation de la peinture en portrait photo-réaliste — même modèle que l’étape 3.
Flux Klein · ComfyUI
Étape 5
Transition
Vidéo de morphing avec étincelles dorées — la peinture se transforme en version réaliste.
Wan2.2 · ComfyUI
👄
Étape 6
Vidéo Parlante
Lip-sync : le portrait réaliste prononce l’audio généré. Mouvements de tête + expressions faciales.
LTX2.3 · ComfyUI
💬
Étape 7
Sous-titres
Génération et incrustation de sous-titres avec style personnalisé.
Whisper · FFmpeg
👋
Étape 8
Boucle / Outro
Rebondir sur l’image de départ pour générer une vidéo capable de tourner en boucle infinie.
Wan2.2 · ComfyUI
🎬
Étape 9
Vidéo Finale
Concaténation de tous les clips, ajout des calques (titre, artiste, filigrane IArtShorts), musique de fond, extraction de la miniature.
FFmpeg
Exécution nocturne → génération de vidéos → stockage dans un pool prêt à publier
▶️ 🎵 📸
~20 peintures / nuit · ~10 vidéos / matinée
📤 Processus d’Upload Séparé
Tâche de fond · 5 peintures/jour · publication aux horaires optimaux sur toutes les plateformes

L’Astuce du Batch Processing

Plutôt que de traiter chaque peinture de bout en bout, je traite l’étape 1 pour TOUTES les peintures, puis l’étape 2 pour toutes, etc.

Ça réduit drastiquement les temps de chargement sur le GPU : un seul warmup par étape au lieu de 10 × N. C’est un gain important sur le temps total de processing.

Le State Machine

Chaque peinture est trackée dans une base SQLite avec un état précis : PENDING → PROCESSING → COMPLETE / FAILED / ABORTED / REDO.

Le système supporte les retries automatiques (×2) et le résumé depuis n’importe quelle étape. Un crash à l’étape 7 sur 50 vidéos ne signifie pas refaire tout le boulot.

Le Client ComfyUI Maison

Mon pipeline utilise un client HTTP + WebSocket custom pour interagir avec ComfyUI, avec tracking de progression temps réel et fallback polling. Entre les batchs, ComfyUI est redémarré automatiquement via SSH (systemctl restart comfyui) pour éviter les memory leaks.


Le Human-in-the-Loop : Les Chiffres Honnêtes

Contrairement à ce qu’on pourrait croire, le pipeline ne produit pas de contenu « plug-and-play ». Chaque jour, je vérifie manuellement toutes les vidéos, une par une.

Les Taux de Rejet

ÉtapeTaux de rejetRaisons
Pré-filtrage automatique (en étape 0)~30%Plusieurs personnes, corps dénudés
Post-traitement manuel (après les 10 étapes)~30%Animation faciale incorrecte, artefacts visuels, lip-sync raté, transition moche, script incorrecte
Taux de réussite global~49%

Sur 30 000 tableaux en base (photos libre de droits), un tirage aléatoire pioche ~20 tableaux dans une liste prédéfinie censée correspondre à des portraits chaque soir.

Le matin : ~10 vidéos validées sur ~20 lancés.

💡 Le pré-filtrage est aussi critique que la pipeline elle-même. Mieux vaut rejeter 30% avant de gaspiller du temps GPU. L’analyse vision AI couvre une partie du filtrage (nudité, enfant, portrait unique), mais certains critères (flou, taille du personnage, orientation de la tête) nécessitent l’œil humain, mais avec maintenant l’expérience pourrait être aussi automatisé en pré-filtrage.


Pourquoi Local ? L’Argument Énergétique

Les modèles cloud sont plus puissants. Mais ici, je ne suis limité que par le coût de l’électricité.

En France :

  • ✅ Électricité pas chère
  • ✅ Faible carbone (nucléaire)
  • ✅ Les GPUs tournent la nuit quand l’énergie est moins chère
  • ✅ Indépendance totale : pas de crédits API, pas de limites de requêtes

💰 Coût Moyen par Vidéo générée : 0,0193 € (~1,9 ct) – au tarif heure creuse  0,1579€ / kWh (2.9 ct si on prend en compte les 30% de déchets)


Leçons Apprises

  1. Le state management SQLite est indispensable. Sans ça, un crash = refaire tout. Avec ça, on reprend là où on s’est arrêté.
  2. Le batch par étapes = gain important de temps. Un seul warmup GPU par étape au lieu d’un warmup par peinture par étape.
  3. Le restart automatique de ComfyUI. Via SSH entre les batchs, c’est la seule façon fiable d’éviter certains memory leaks sur des runs de plusieurs heures.
  4. La recherche hors-ligne via ZIM. Pas de dépendance réseau pour les données Wikipedia. Plus rapide, plus fiable, plus privé.
  5. 30% de rejet, c’est la réalité actuelle. Les modèles vidéo génèrent encore trop d’artefacts pour une automatisation 100%. Le human-in-the-loop est non-négociable pour du contenu qualité.

Tableau Récapitulatif des Licences

ModèleLicenseUsage commercial
Qwen3.6-27BApache 2.0✅ Libre
Qwen3.5-122BApache 2.0✅ Libre
Gemma4-31BApache 2.0✅ Libre
Qwen TTSApache 2.0✅ Libre
Wan2.2-I2V-A14BApache 2.0✅ Libre
Flux.2 Klein 9BFLUX Non-Commercial License v2.1✅ exploitation des outputs
LTX-2.3LTX-2 License⚠️ Seulement < 10M$

Rapport d’Exécution Pipeline

Batch #0 · iartshorts · 2026-05-22 02:58 → 07:54 · 20 tableaux sélectionnés, 30 vidéos produites (15 FR + 15 EN)

4h 56m
Temps Réel Total
4h 24m
Calcul GPU
89,4%
Efficacité GPU
30
Vidéos Produites

15 tableaux traités → 30 vidéos (français + anglais chacun). 5 tableaux abandonnés à l’étape 0 (Analyse Vision) — tous rejetés en moins de 3 secondes


Efficacité GPU

Sur les 15 tableaux traités, le GPU a été actif à 89,4% du temps réel total. Seulement 31 minutes d’attente en file — un excellent taux d’utilisation pour une pipeline séquentielle.

89,4%
GPU Actif
Calcul GPU : 4h 24m
Attente file : 31m

Répartition du Temps par Étape

Chaque tableau passe par 10 étapes. Chaque étape avec un workflow ComfyUI est exécutée en français ET en anglais. Voici la répartition du temps sur les 15 tableaux traités :

Temps Réel par Étape (15 tableaux)

Étape 0 — Préparation (Vision)
0,9m
0,3%
Étape 1 — Script (LLM + ZIM)
21,6m
7,3%
Étape 2 — Audio (TTS × 2)
28,2m
9,6%
Étape 3 — Image Propre (Flux)
2,3m
0,8%
Étape 4 — Image Réaliste (Flux)
1,6m
0,5%
Étape 5 — Transition Vid (Wan)
22,5m
7,6%
Étape 6 — LipSync Vid (LTX × 2)
164,1m
55,6%
Étape 7 — Sous-titres (Wan)
7,5m
2,5%
Étape 8 — Outro Vid (Wan × 2)
42,8m
14,5%
Étape 9 — Vidéo Finale (FFmpeg)
3,4m
1,2%

Calcul vs Attente par Étape

ÉtapeStageTemps RéelCalcul GPUAttente FileGPU %
0Préparation (Vision)0,9m0,9m
1Script (LLM + ZIM)21,6m21,6m
2Audio (TTS × 2)28,2m27,5m0,8m97,3%
3Image Propre (Flux)2,3m1,5m0,8m66,2%
4Image Réaliste (Flux)1,6m0,8m0,8m51,6%
5Transition Vid (Wan)22,5m21,8m0,8m96,6%
6LipSync Vid (LTX × 2)164,1m163,3m0,8m99,5%
7Sous-titres (Wan)7,5m6,7m0,8m89,3%
8Outro Vid (Wan × 2)42,8m42,0m0,8m98,1%
9Vidéo Finale (FFmpeg)3,4m3,4m

Top 3 des Goulots d’Étranglement

Ces trois étapes représentent 88,3% de tout le temps de calcul GPU :

#ÉtapeModèleCalcul GPU% du TotalMoy. / Tableau
1LipSync VidéoLTX2.3-AudioSync × 22h 43m62,0%10,9 min
2Outro VidéoWan2.2 × 242 min15,9%2,8 min
3Audio (TTS)Qwen TTS × 228 min10,4%1,8 min

🐌 Le LipSync (LTX2.3) est le goulot d’étranglement principal avec 62% du temps GPU. Chaque tableau nécessite 2 vidéos lip-sync (FR + EN), d’environ 5,4 minutes chacune. Réduire la durée de cette étape aurait le plus grand impact sur le débit global.


Détail par Tableau (15 Traités)

TableauArtisteTemps RéelCalcul GPUGPU %Étape la + Longue
Young_Girl_Holding_a_BasketBerthe Morisot22,5m21,9m97,3%LipSync 7,6m
Thomas_Howard_2nd_Earl_of_ArundelAnthony van Dyck23,2m22,7m97,8%LipSync 7,9m
The_Spanish_GuitaristPierre-Auguste Renoir25,5m25,2m98,8%LipSync 10,0m
Woman_in_a_Flowered_HatPierre-Auguste Renoir26,2m25,9m98,8%LipSync 10,3m
Woman_in_a_GardenBerthe Morisot26,5m26,2m98,9%LipSync 10,6m
Young_Girl_with_an_ApronBerthe Morisot26,9m26,5m98,5%LipSync 10,8m
Woman_with_Red_HairAlice Pike Barney27,2m26,9m98,9%LipSync 10,9m
Young_Woman_with_a_Water_PitcherJohannes Vermeer27,2m26,8m98,5%LipSync 11,1m
Woman_in_Tulle_BlousePierre-Auguste Renoir27,5m27,1m98,6%LipSync 11,2m
The_EmbroidererJean Siméon Chardin27,6m27,2m98,6%LipSync 11,3m
The_Stroller_Suzanne_HoschedéClaude Monet27,8m27,4m98,6%LipSync 11,4m
Young_Woman_with_RosesAlice Pike Barney29,0m28,6m98,6%LipSync 12,2m
Woman_Seated_under_the_WillowsClaude Monet29,3m28,9m98,6%LipSync 12,5m
Young_Girl_in_a_Pink-and-Black_HatPierre-Auguste Renoir29,7m29,3m98,7%LipSync 12,7m
The_Red_KerchiefClaude Monet31,6m31,1m98,4%LipSync 13,6m

💡 Tableau le + rapide : « Young Girl Holding a Basket » de Berthe Morisot — 22,5 min total. Le + lent : « The Red Kerchief » de Claude Monet — 31,6 min total. Écart de 9 minutes, principalement dû aux différences de durée du lip-sync.