Moteur vidéo
Un pipeline éprouvé pour transformer des scripts en vidéos finies et publiable avec du code. Il est agnostique en termes de style : le moteur (voix, timing, primitives d'animation, QA, rendu) reste le même ; l'apparence, le rythme, les personnages et le son sont conçus projet par projet à partir du brief et des références du client.
Si l'utilisateur a déjà un projet construit avec ce moteur, lisez-le avant de construire quoi que ce soit de nouveau : son document de structure (VIDEOS.md / SAGAS.md), le contrat du moteur (src/engine/video.ts ou saga.ts), un style (src/styles/<style>/ : kit.ts, Video.tsx) et une scène terminée. Réutilisez son moteur plutôt que de repartir de zéro. Deux structures ont fait leurs preuves :
- Série : épisodes partageant un personnage, une voix et un format (ex. une saga mathématique pour enfants avec TTS et une mascotte).
- Vidéos indépendantes : explicatifs uniques, chacun avec son propre sujet, voix fournie, ressources et peut-être son propre look (ex. explicatifs tech dans un style diagramme sombre, rendus en 16:9 et 9:16).
Principes non négociables
- L'audio est l'horloge. Générer/importer la voix en premier, l'aligner mot par mot, puis animer en fonction des mots. Ne jamais accélérer ou couper la parole pour atteindre une durée.
- Chaque événement visuel est ancré à un mot parlé (
at(block, 'phrase exacte', {word, n})). Si la phrase n'est pas dans l'alignement, échouez bruyamment — n'inventez jamais d'horodatages. - Fonction pure du temps. L'état de la scène = f(t). Pas d'état entre les images → l'aperçu == le rendu à n'importe quelle image, et la QA peut échantillonner n'importe quel instant.
- Textures déterministes. Bruit ensemencé dans les coordonnées locales de l'objet → pas de bouillonnement/clignotement. Mesurez-le (différence d'image dans les zones statiques ≈ 0).
- Valider avant le rendu ; examiner les images avant et après. Les contrôles automatiques détectent les bogues de logique/timing ; une planche contact détecte les bogues de composition (chevauchements, surpeuplement, éléments cachés). Les deux sont obligatoires.
- Dépenser de l'argent uniquement avec consentement. Les appels TTS coûtent des crédits : exécution à sec (blocs + caractères) → demander → générer. Mettre en cache par hachage de chaque entrée qui affecte l'audio.
- Rapporter honnêtement. Indiquer ce qui a été vérifié automatiquement, ce qui a été regardé et ce qui ne l'a PAS été (par exemple « je n'ai pas écouté l'audio »).
- Plusieurs vidéos, un moteur — dès la première vidéo. Moteur partagé + styles réutilisables + un dossier autonome par vidéo (ou par série), avec ses propres scripts, voix, scène, miniature, ressources et composants par vidéo. Le moteur n'importe jamais une vidéo ou un style ; chaque commande prend la vidéo. Voir
references/project-layout.md.
Workflow
- Placer la vidéo dans la structure du projet — nouveau dépôt : configurer la structure multi-vidéos avant d'écrire une scène ; dépôt existant :
npm run video -- new/npm run saga -- new(fonctionne sur un dossier que le client a déjà rempli avec audio + script). Voirreferences/project-layout.md. - Brief & format — audience, objectif, plateforme, durée, rapport d'aspect, langue/locale, contraintes de monétisation (ex. YouTube « made for kids »). Voir
references/formats-and-niches.md. - Bible de style — déduire des références client ou proposer 2–3 directions ; verrouiller la palette, la typographie, la texture, le personnage, le langage de mouvement, la palette sonore dans un
style.json/doc. Voirreferences/style-design.md. - Script en tant que données — blocs avec
tts_text(avec balises vocales),subtitle_text, question/attente optionnelle, instructions visuelles, réponses/faits attendus. Valider avec un schéma JSON. - Voix — ElevenLabs avec horodatages (ou importer des clips manuels + alignement forcé local). Voir
references/voice-and-alignment.md. - Chronologie — placer les clips, les lacunes/attentes mesurées, la piste vocale principale normalisée, l'enveloppe vocale par image, SRT. Voir
references/timeline-and-audio.md. - Script de scène — par vidéo, un constructeur déclaratif utilisant le kit (objets, mouvements, étiquettes, équations/révélations de texte, poses, SFX, décor). Voir
references/animation-remotion.md. - Valider — schéma, attentes, « rien n'est révélé avant d'être dit », comptes/réponses, pas de chevauchements, zones de sécurité, bande de sous-titres libre. Voir
references/qa-and-validation.md. - Révision des images fixes — planche contact de 12 à 15 instants clés ; corriger et répéter.
- Rendu — arrière-plan, journalisé, concurrence économe en mémoire ; vérifier avec ffprobe + loudness. Voir
references/render-and-performance.md. - Livrables — MP4,
<nom>.<lang>_<REGION>.srt, miniature (obligatoire, générée par le pipeline lui-même — jamais une étape séparée facultative ; par format : 1280×720 pour 16:9, 1080×1920 cover pour 9:16 avec le contenu clé centré pour les recadrages 1:1/3:4 ; échouer l'exécution si manquante, vérifier sa taille dans la QA de sortie et la regarder), audio maître, timings des mots, chronologie des événements, rapport QA, métadonnées de téléchargement (titres/descriptions avec chapitres vrais/hashtags/balises).
Stack (par défaut ; justifier les écarts)
- Remotion 4 (React + SVG) pour le rendu d'image déterministe, l'aperçu Studio/Player, le traitement par lots en CLI. Vérifier la licence (gratuit pour les particuliers/≤3 employés).
- Chromium GL
anglesur macOS (≈30 % plus rapide). Les encodeurs matériels aident rarement (le goulot d'étranglement est le dessin) — mesurer. - ElevenLabs
POST /v1/text-to-speech/{voice}/with-timestamps(alignement des caractères). Les voix de bibliothèque nécessitent un plan payant via l'API. - stable-ts (Whisper) dans un venv Python pour l'alignement forcé local des clips manuels ; l'API d'alignement forcé d'ElevenLabs comme alternative précise.
- ffmpeg pour le mixage, la sonie (EBU R128), le remux/faststart, les planches contact, la mesure du scintillement.
- Polices : OFL (Google Fonts) stockées localement avec les fichiers de licence. SFX/musique : synthétiser de manière procédurale ou utiliser des ressources sous licence ; conserver des copies + la table des licences.
Là où les choses tournent mal (appris à la dure)
ctx.at()doit retourner le premier mot d'une phrase par défaut ; les phrases répétées ont besoin den(ex. « una más » dit deux fois).- Les contrôles de chevauchement doivent utiliser la taille mise à l'échelle de l'objet ; un changement d'échelle après validation peut tout casser — tout revalider après les modifications du moteur.
- Les objets créés par les assistants « transfert/sortie » doivent également avoir un temps de
removelorsque la scène change, sinon ils fuient dans les scènes ultérieures. - Déplacer des objets pendant la fenêtre d'attente d'une question casse « freeze pendant l'attente » ; déplacer après la fin de l'attente.
- Ne jamais montrer un nombre/réponse que la narration n'a pas encore dit (dans la scène, les étiquettes, les équations, les sous-titres). Diviser les repères de sous-titres aux mots numériques.
- Concurrence de rendu : ~2,6 Go de RAM par instance Chromium ; 6 sur un Mac 8 Go → échange massif et rendu bloqué. Par défaut,
floor(totalmem/2.6GB). - Les sous-titres incrustés nécessitent une bande réservée ; valider qu'aucun objet n'y pénètre.
- Les titres longs dans des zones de texte fixes débordent — taille automatique en fonction de la longueur.
- Vérifier le contenu de chaque clip (transcrire → comparer au script, mapper les chiffres ↔ mots) avant de faire confiance à l'audio importé ; les clips peuvent être manquants ou dans le désordre. Faire de même pour le TTS généré (« écouter » par proxy : transcription Whisper vs script, tous les nombres présents).
bundle()de Remotion copiepublic/(toutes les voix) dans le répertoire temporaire du système d'exploitation à chaque appel et ne le supprime jamais ; de nombreuses exécutions d'images fixes ont rempli un disque de 460 Go. Toujoursrm -rfle bundle lorsque le script se termine. Surveiller l'espace disque libre pendant les longs lots.- Les filtres SVG utilisent la boîte englobante de l'élément : un chemin parfaitement horizontal ou vertical (boîte englobante de surface nulle) avec un filtre ne rend RIEN. Les bras, les graduations de droite numérique et les lignes de guidage ont disparu de cette façon. Les traits droits alignés sur les axes n'ont pas besoin de filtre.
- Les données d'une question peuvent devoir rester visibles (prix, politique de données) alors que la réponse ne doit pas l'être. Si un prix est égal à la réponse numérique, supprimer le prix avant la question.
- Un dépôt à une seule vidéo doit être refactorisé dès l'arrivée de la deuxième vidéo. Quand cela se produit, capturer d'abord une ligne de base : md5 des images fixes, miniatures, livrables JSON/SRT et md5 de la voix. Après le déplacement, tout doit être identique octet par octet. Déplacer les fichiers et ne jamais les supprimer ; garer les restes dans
_legacy/pour que l'utilisateur les examine. staticFile()n'atteint quepublic/: les médias par vidéo résident dans le dossier vidéo et sont synchronisés danspublic/videos/<slug>/avant chaque bundle. Une nouvelle vidéo a besoin d'une chronologie placeholder (pas de blocs) pour que l'import statique compile.- Les scripts clients mélangent souvent la narration avec les instructions visuelles (par exemple NARRACIÓN / REFERENCIA VISUAL — NO NARRAR). Aligner uniquement la narration et conserver les notes visuelles par section dans
script.json, car elles sont la spécification de fidélité pour la scène. - L'audio fourni peut ne pas dire ce que le script fourni dit (le narrateur a improvisé, une prise ultérieure). Toujours lire la transcription libre avant d'aligner, et aligner par rapport à ce qui est réellement dit dans un fichier séparé (
narracion.md) à côté du script du client. L'alignement forcé sur le mauvais texte produit silencieusement des timings erronés. - Les explicatifs techniques ont besoin de fidélité, pas de décoration. Calculer ce qui peut être calculé : vraies photos sous forme de tenseurs, vraies convolutions, vraie formule de bruit par pixel, une vraie mise à jour de l'échantillonneur. Étiqueter le reste comme illustratif (« esquema didáctico », « salida ilustrativa »), conserver un
references/decisiones.md, et dire la même chose dans la copie de téléchargement. Vérifier les affirmations sur les produits par rapport aux sources primaires avant de les dessiner. Par exemple, Imagen est une diffusion en cascade dans l'espace pixel, pas latente. - Formules : rendre le TeX du client avec MathJax en chemins SVG (aucune dépendance de police) dans une étape du pipeline, puis les dessiner comme un élément
formula. - Les diagrammes qui se construisent de gauche à droite ne sont jamais centrés à moins que le groupe ne glisse en grandissant. Utiliser un recentrage automatique qui glisse avant l'entrée d'un nouveau venu et après la disparition d'un partant. Garder les en-têtes sur CX fixe, et les entrées de groupe espacées d'au moins 0,6 s. Pour les chaînes, dessiner d'abord les emplacements vides.
- Boucles sans couture :
- Ne pas utiliser de fondus.
- Faire en sorte que le début et la fin soient égaux à une pause naturelle.
- Utiliser de la musique générée pour durer exactement la longueur de la vidéo.
- Terminer sur une copie exacte de l'élément d'ouverture : une copie mise à l'échelle diffère par l'anticrénelage.
- Vérifier avec une différence première image vs dernière image sans sous-titres.
- Les images photos raster dans SVG vont dans
<foreignObject><Img/></foreignObject>, car Remotion attend<Img>. Un<image>SVG nu peut rendre des images vides. - Un dispatch de propriétés générique avec des paramètres numériques keyframés (minutes d'horloge, inclinaison, niveau, décalage d'explosion) s'adapte à des dizaines de nouveaux objets sans toucher au moteur de rendu. Construire une feuille de révision des propriétés (image fixe dev) avant d'écrire des scènes.
Démarrer un nouveau projet
- Nouvelle vidéo ou série dans un dépôt moteur existant (recommandé) : utiliser sa commande d'échafaudage (par exemple
npm run video -- new --video <slug>ounpm run saga -- new --saga <slug>). Elle crée le dossier à partir de_template/, l'enregistre et copie éventuellement un style de base danssrc/styles/<new-style>comme point de départ pour restyler. - Nouveau dépôt : configurer la structure multi-vidéos à partir de
references/project-layout.mdavant d'écrire une scène :package.json,tsconfig.json,remotion.config.ts,src/engine/(modèle de scène, repères de mots, formats, sous-titres, le contrat vidéo), un style danssrc/styles/<style>/,scripts/(chronologie, valider, images fixes, rendu, miniatures, vérifier, la commandenew),tools/(alignement, ressources procédurales), un dossier_template/, le registre etRoot.tsx. Ensuitenpm install, et créer un venv Python avec stable-ts uniquement si l'audio fourni doit être aligné. - Adapter le schéma de script à la structure de blocs du créneau (rôles tels que crochet, enseigner, exemple, question/attente, récapitulatif).
- Implémenter la bible de style : palette, polices (locales, sous licence), filtres, texture de fond (générée par un script), personnage ou présentateur, SFX/musique.
- Rendre un échantillon de 12 à 15 secondes à partir d'un vrai audio → approbation de l'utilisateur → puis passer à l'échelle.
- Conserver les règles du projet dans
CLAUDE.mddu projet (coûts/consentement, conventions de nommage, langue, étapes de révision) et la structure dans unVIDEOS.md/SAGAS.md.
Fichiers de référence
references/style-design.md— déduire/proposer une identité visuelle, bible de style, règles de cohérence.references/voice-and-alignment.md— ElevenLabs, mise en cache, erreurs, clips manuels, alignement forcé.references/timeline-and-audio.md— placement des clips, attentes, sonie, ducking de musique, SFX, sous-titres.references/animation-remotion.md— modèle de données de scène, kit de création, rig de personnage, langage de mouvement, aperçu.references/textures-and-rendering-looks.md— recettes de filtres SVG ensemencés pour de nombreux looks.references/qa-and-validation.md— règles automatiques, révision visuelle, contrôles de sortie.references/render-and-performance.md— paramètres de rendu, mémoire, files d'attente, livrables, métadonnées de téléchargement.references/formats-and-niches.md— rapports d'aspect, zones de sécurité, playbooks par créneau.references/project-layout.md— plusieurs vidéos par dépôt : dossiers par vidéo, styles réutilisables, contrat vidéo, synchronisation des ressources, migration d'un dépôt plat.