code-video : Faites écrire du code par un LLM pour générer, image par image, des vidéos de vulgarisation
L'image n'est pas générée par un modèle vidéo ni filmée : le LLM écrit une page web (Canvas / SVG / Three.js / WebGL),
la page expose __render(t), un script capture chaque image en fonction du numéro d'image, puis ffmpeg les encode en mp4.
L'avantage est que c'est reproductible, modifiable, les textes et les chiffres sont absolument exacts, et le coût de génération est nul.
L'ensemble tient en trois étapes : Choisir un style → Rédiger un prompt détaillé → Vérifier avec quelques images, puis lancer le rendu complet.
0. Préparation (première utilisation)
cd <répertoire_skill>
npm install # installe playwright-core
npx playwright-core install chromium-headless-shell # ou définir CHROME=/path/to/chrome
# ffmpeg / ffprobe doivent être dans le PATH ; police chinoise : Noto Sans CJK recommandé (fonts-noto-cjk / noto-fonts-cjk)
pip install edge-tts numpy scipy # optionnel : narration, sous-titres, musique
1. Choisir un style : le style suit le sujet
Regardez d'abord dans quelle catégorie se situe le sujet, puis lisez le fichier de style correspondant dans references/styles/ (chaque fichier contient : sujets adaptés,
prompt simplifié, prompt complet, notes de production, références factuelles, et un exemple de code dans examples/<nom>/).
| Sujet | Essayer d'abord | Alternative |
|---|---|---|
| Allusions, histoires | Théâtre d'ombres piying | Pixel pixel, Bande dessinée comic |
| Vulgarisation pour enfants, croissance naturelle | Album illustré picturebook | Animation plate flatmg |
| Texte, objets, dynasties | Évolution des sinogrammes hanzi | Encre ink |
| Routes, missions, migrations | Carte ancienne oldmap | Procédé isométrique isometric |
| Structures mécaniques, éclatés de produits | 3D éclatée explode3d | Tableau blanc whiteboard |
| Processus, chaînes de production | Procédé isométrique isometric | Animation plate flatmg |
| Taille, profondeur, distance | Échelle scale | Infographie de données infographic |
| Époques, ordres de grandeur | Infographie de données infographic | Échelle scale |
| Théorèmes, formules | Visualisation mathématique math | Dessin au trait lineart |
| Principe unique, cause-effet | Tableau blanc whiteboard | Dessin au trait lineart |
| Slogans, génériques | Typographie cinétique kinetic | — |
Les 16 styles complets sont dans references/styles/README.md. Si l'utilisateur nomme un style, lisez directement ce fichier.
2. Rédiger un prompt détaillé : une phrase ne définit que le style
Une phrase comme "fais un théâtre d'ombres de 10 secondes" ne donne au LLM que le style, pas le contenu, les données, ni la durée de chaque segment. Suivez le schéma ci-dessous pour clarifier quatre choses (les prompts complets dans les fichiers de style suivent cette structure) :
Utilise Canvas pour dessiner image par image une animation de vulgarisation de style « style », en 1920×1080, 30fps, environ 12 secondes : définis la palette, la texture et la police.
Le sujet est « … » : découpe en plusieurs plans, ce que montre chaque plan, quel texte s'affiche à l'écran, et la conclusion en une phrase.
Les chiffres à utiliser : …, leurs sources dans notes.txt ; ne pas préciser à l'unité les chiffres non vérifiés.
Chaque image n'est déterminée que par t (pas de minuteur, les nombres aléatoires utilisent une graine fixe).
Capture d'abord 4 à 6 images pour vérifier si les sous-titres sont assez grands, si les étiquettes se chevauchent ou sortent du cadre, puis rends toute la vidéo.
Ajoutez les règles physiques / factuelles du sujet qui pourraient être mal interprétées. Exemple : dans l'histoire de Cao Chong pesant l'éléphant, le tirant d'eau du bateau doit tenir compte de la charge, sinon la marque et la ligne d'eau ne correspondent pas ; si cette règle n'est pas écrite, le LLM la dessinera de travers.
3. Écrire la page : contrat de page obligatoire
Chaque vidéo a son propre répertoire <work>/<nom>/, contenant au moins index.html. Il est recommandé d'écrire aussi prompt.txt (le prompt utilisé)
et notes.txt (sources des chiffres et faits). On peut partir de templates/canvas/index.html.
- Page fixe en 1920×1080,
overflow:hidden. - Doit contenir cette ligne (read par render.sh avec une regex) :
const FPS = 30, DUR = 12; window.__info = { fps: FPS, duration: DUR, frames: Math.round(FPS * DUR) };window.__render = t => { ...; return { seg: '<nom_plan>', tau: t.toFixed(2) }; }Chaque image n'est déterminée que par t : pas de CSS animation/transition, setTimeout, requestAnimationFrame,Date.now(),Math.random(); les nombres aléatoires utilisent une graine fixe (ex. mulberry32) ; particules, vibrations, physique doivent pouvoir être calculés directement à partir de t, sans accumuler d'état entre les images.- Les polices et ressources sont chargées puis on définit
window.__ready = true(pour les pages WebGL, après le rendu de la première image). - Pas d'accès réseau (le script de capture bloquera toutes les requêtes externes). Utilisez les polices système installées.
- Lisible sur mobile : étiquettes de texte ≥ 36px, titres ≥ 64px, petit texte en bas à gauche optionnel.
- Page Three.js :
scripts/fetch_three.sh <nom>télécharge dans<nom>/vendor/, puis<script type="importmap">{ "imports": { "three": "./vendor/three.module.js", "three/addons/": "./vendor/jsm/" } }</script>; le renderer doit avoirpreserveDrawingBuffer: true, et dans__render(t)appelerrenderer.render()(ou composer) de manière synchrone.
Détails et pièges courants dans references/page-contract.md.
4. D'abord capturer quelques images pour vérifier, puis lancer le rendu complet
scripts/render.sh <work>/<name> 30,120,210,300 # ne capture que ces images -> <work>/_preview/<name>/
Examinez chaque image avec un visualiseur, repérez les problèmes selon cette liste, corrigez, puis recapturez (au moins une itération) :
- Texte : assez grand ? chevauchement ? sortie du cadre ? masqué ? les sinogrammes sont-ils affichés avec la vraie police (pas de carrés) ?
- Faits : les chiffres, années, noms de lieux, formules sur l'image correspondent-ils à notes.txt ? Les illustrations schématiques sont-elles étiquetées "schéma" ?
- Composition : le sujet est-il assez grand (le personnage au loin fait au moins 1/4 de la hauteur de l'image) ? L'image est-elle trop vide ? La palette correspond-elle au sujet ?
- Animation : les actions clés se produisent-elles vraiment (comparez deux images adjacentes) ? Les transitions sont-elles brutales ?
- WebGL : y a-t-il des blocs noirs / taches noires, des scintillements ?
Si tout va bien, lancez le rendu complet :
scripts/render.sh <work>/<name> # -> <work>/<name>.mp4
N=8 scripts/render.sh <work>/<name> # nombre de processus de capture parallèles (défaut : min(6, nb_cœurs/2))
GPU_ANGLE=vulkan scripts/render.sh ... # WebGL utilise la carte graphique (plus rapide, mais peut produire des taches noires en capture continue ; vérifiez d'abord avec quelques images)
L'encodeur est choisi automatiquement : si NVENC est disponible, utilise h264_nvenc, sinon libx264.
La capture est principalement CPU ; le goulot d'étranglement est généralement "le LLM écrit la page, on regarde les captures, on modifie le code", pas le rendu lui-même.
5. Optionnel : narration, sous-titres, musique, vignette
# Narration + sous-titres (edge-tts gratuit par défaut ; toute la narration synthétisée d'un coup pour une voix cohérente)
python3 scripts/tts.py script.txt -o out/narration --voice zh-CN-YunyangNeural --rate -5%
# Musique : générée soi-même (pas de droits d'auteur), ou utiliser une bibliothèque libre de droits (voir references/narration.md)
python3 scripts/chiptune.py out/bgm.wav 30 # Musique chip 8-bit
python3 scripts/beat.py out/beat.wav --bpm 120 --beats 20 # Rythmes, alignés sur les images
# Assemblage : la musique s'ajuste automatiquement pour laisser place à la voix, normalisation à -16 LUFS ; --burn grave les sous-titres dans l'image
scripts/mux.sh out/<name>.mp4 out/<name>.final.mp4 --voice out/narration.mp3 --music out/bgm.wav --srt out/narration.srt --burn
# GIF de prévisualisation / image de couverture
scripts/gif.sh out/<name>.mp4 2.5 4 # 4 secondes à partir de 2.5 s
scripts/gif.sh --poster out/<name>.mp4 6.0 # capture une image jpg
Pour graver les sous-titres, laissez le 1/5 inférieur de la page vide, ne dessinez pas vos propres barres de sous-titres (ou utilisez SUB_MARGIN=60 pour les remonter) ;
objectif de volume : -16 LUFS, un peu plus bas si le pic vocal est élevé (limite de vrai pic : -1.5 dBTP).
Les choix sonores, l'intégration de TTS personnalisé et l'alignement des rythmes sont détaillés dans references/narration.md.
6. Faire plusieurs vidéos à la fois (comparaison de styles, série)
Chaque vidéo a son propre répertoire et son propre prompt, indépendants. On peut les confier à plusieurs sous-agents qui écrivent et vérifient en parallèle, et l'agent principal ne fait que le rendu final, l'assemblage et la vérification. Dans les instructions de chaque sous-agent, précisez : le contrat de page, les conventions de répertoire, la liste de vérification par capture, les faits à écrire dans notes.txt, et le rapport de durée + auto-évaluation après terminaison.
À clarifier avant de commencer
- Les chiffres factuels doivent être réels et vérifiables ; pour les actualités / sujets de nouvelle catégorie, ne dessinez que les informations publiques et étiquetez "schéma" dans un coin.
- Ne réutilisez pas les chiffres d'un exemple comme faits généraux ; vérifiez à nouveau si le sujet change.
- Les musiques générées par modèle (ex. MusicGen) sont souvent sous licence non commerciale ; pour une publication commerciale, utilisez votre propre musique ou une musique sous licence explicite.