Communitygithub.com

reels-maker

Créez et rendez un film, un reel ou une animation sous forme de code. Une page HTML dessine n’importe quelle image à la demande avec window.seek(t), et un navigateur sans tête rend chaque image en 2x dans un MP4 avec son.

Qu'est-ce que reels-maker ?

Cette compétence transforme la création vidéo en un processus programmatique et déterministe. Au lieu d'utiliser un éditeur vidéo classique, chaque film est une page HTML unique où `window.seek(t)` dessine exactement l'image correspondant au temps `t`, sans jamais lire l'horloge réelle. Un moteur de rendu parcourt ensuite chaque image à 30 ips, capture l'écran en 2x et la transmet à ffmpeg pour produire un MP4. Cela garantit qu'un re-rendu est identique (à quelques pixels près), qu'une image fixe à 17,3 s est exactement l'image que la vidéo montrera, et que chaque vérification (film-audit) peut examiner n'importe quel moment sans lire la vidéo entière. Elle prend en charge les formats 9:16, 4:5, 1:1 et 16:9, et intègre le son avec une normalisation −14 LUFS, un limitateur et un encodage H.264 sans marquage couleur. La compétence est conçue pour fonctionner avec Claude Code, Cursor, Codex et d'autres agents, et elle suit un parcours structuré en neuf étapes : du brief signé à l'envoi de l'aperçu téléphone, en passant par la maquette, la construction, les contrôles qualité, le rendu, l'audio et le mixage. Elle est agnostique en termes de style et s'appuie sur un kit (`template/` et `tools/`) que l'agent utilise pour générer des vidéos à partir de zéro ou d'un pack de style existant comme `voxel-walk`.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/thativanng/reels-maker/tree/HEAD/skills/film-engine

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

film-engine : des films dessinés à partir du code, image par image

Où se trouve le kit : exécutez chaque commande de cette compétence depuis le dossier reels-maker (le clone de github.com/thativanng/reels-maker qui contient template/ et tools/). Si le projet n'en a pas, configurez-le d'abord en suivant le SETUP.md de ce dépôt.

L'idée en un paragraphe

Un film ici est une page HTML avec une règle : window.seek(t) doit dessiner exactement l'image pour le temps t, à chaque fois, à partir de rien d'autre que t. Rien dans l'image ne peut lire une horloge réelle. Un moteur de rendu parcourt ensuite t à 30 ips, capture chaque image en 2x et la transmet à ffmpeg. Comme la page est déterministe, un re-rendu correspond (en moyenne à une fraction de niveau près ; le bruit GPU peut déplacer des pixels uniques jusqu'à environ 60 niveaux), une image fixe à 17,3 s est l'image que la vidéo montrera, et chaque vérification (film-audit) peut examiner n'importe quel moment sans lire le film.

Le parcours (ne sautez aucune étape)

  1. D'abord le brief et le look. reel-intake se termine par un brief et un storyboard signés (format, durée, son, ce qui n'apparaît jamais) ; reel-style se termine par un look choisi. N'ouvrez pas les étapes de construction de cette compétence sans les deux.
  2. Storyboard. reel-intake l'écrit (temps · mots à l'écran · son et légende · pourquoi ; references/brief.md), et la personne le signe avant que vous ne construisiez. Un style avec une bannière ajoute une colonne de bannière.
  3. Bande d'essai. Construisez environ les 10 premières secondes dans le look choisi (un film de style walk peut nécessiter 15 à 30 s pour montrer un chapitre), prenez des images fixes, obtenez un oui. Une construction complète sur un look non signé est du travail perdu.
  4. Construisez le film complet (le pack de style indique comment construire les scènes).
  5. Portes (film-audit) : la vérification de collision à 40 ips, les sondes de pixels, puis un auditeur indépendant. Rien ne va à la personne avant cela.
  6. Rendu : node tools/render.mjs --page reels/<nom>/page.html --out reels/<nom>/out/film-silent.mp4 (images 2x, réduites avec lanczos, sans marquage couleur).
  7. Audio : python3 template/audio.py out/film.wav (une liste de repères sur la même horloge que le film).
  8. Finalisation : zsh tools/mux.sh out/film-silent.mp4 out/film.wav out/film.mp4. Cela donne −14 LUFS, un limiteur, un fichier H.264 sans balise et un aperçu téléphone de la même forme que le film (petit côté 720 px).
  9. Couverture : node tools/cover.mjs --page reels/<nom>/page.html --out reels/<nom>/out/cover.jpg. Une page avec un mode couverture (le ?cover du starter, à partir de la config cover) dessine l'image fixe conçue ; toute autre page donne l'image à T=. Elle est enregistrée dans la forme propre du film et maintenue sous 2 Mo, plus le recadrage 3:4 centré pour un film 9:16 (la grille Instagram, rapportée). LinkedIn prend une couverture uniquement au moment de la publication : après, seul le texte d'un post peut être modifié (Aide LinkedIn, « Modifier un post partagé », https://www.linkedin.com/help/linkedin/answer/a522811). Sa spécification de miniature, JPG ou PNG dans la forme de la vidéo et au maximum 2 Mo, provient de l'aide de LinkedIn telle que citée par un résumé de recherche ; la page elle-même ne se chargerait pas, donc traitez-la comme non vérifiée.
  10. Envoyez d'abord l'aperçu téléphone, puis le fichier complet et la couverture.

Le contrat de la page

  • window.seek(T) : dessine l'image T. C'est le seul endroit qui anime quoi que ce soit.
  • window.ready : une promesse qui se résout après les polices, les textures et la première image.
  • window.DUR : la durée du film en secondes.
  • window.FILM = { w, h, format, safe } : la taille de l'image et la zone de dégagement en pixels. Chaque outil dimensionne sa fenêtre à partir de cela, donc la page possède son format.
  • Optionnel : window.cover() dessine la couverture au lieu d'une image, et FILM.coverAt nomme le moment où elle se trouve (tools/cover.mjs utilise les deux ; sans eux, il prend l'image à T=).
  • window.collide(T) et window._dbg : hooks pour film-audit (voir cette compétence).
  • Les outils servent le dossier du kit via http sur leur propre compte (les modules ES ne se chargent pas depuis file://). Pour regarder une page en direct dans un navigateur, npm run serve et ouvrez http://127.0.0.1:8765/template/starter.html.

Formats, le starter et autres langues

  • template/formats.json contient les quatre tailles (9:16 1080×1920 · 4:5 1080×1350 · 1:1 1080×1080 · 16:9 1920×1080), la carte plateforme → format, et la zone de dégagement de chaque plateforme avec sa source. La ligne de format du brief la choisit.
  • Chaque reel vit dans son propre dossier, reels/<nom>/ (gitignoré) : son brief, storyboard, page.html (une copie du starter ou de film.html), son reel.json ou career.json, et son out/. Les pages chargent les polices et formats.json depuis la racine du kit, donc une copie fonctionne à partir de là. Pointez les outils vers elle : PAGE=reels/<nom>/page.html.
  • template/starter.html + template/reel.json est le squelette pour tous les looks sauf le voxel walk. Ses mots et minutages vivent dans la configuration, il se dimensionne à partir de ?fmt= ou de la configuration, et il maintient chaque mot à l'intérieur du cœur de dégagement de la plateforme. ?guides montre les zones couvertes en rouge, pour vérification uniquement ; ne rendez jamais avec cela activé. C'est un squelette, pas un look : reel-style réécrit ses jetons et sa disposition.
  • template/film.html (le modèle voxel) est uniquement 4:5, et il refuse les zones de dégagement (safe vaut 0) : sa bannière et ses sous-titres sont près des bords par conception, donc la sonde safe passe toujours là et l'œil de l'auditeur est la vérification. Ses caméras sont paramétrées pour 4:5 ; un autre ratio signifie les re-paramétrer et réexécuter chaque porte.
  • Chinois, japonais, coréen : le starter charge Noto Sans TC depuis Google Fonts au moment du rendu (seulement les caractères que la configuration utilise), et exécute le texte CJK à environ 0,72× de la taille latine (leurs caractères font un em complet). Écrivez \n là où une ligne doit se couper : le chinois se coupe entre deux caractères quelconques, donc une longue ligne a besoin d'une coupure que vous choisissez. template/reel.zh.json est un exemple fonctionnel. Tout autre script nécessite sa propre police dans la pile.

Horloges et minutage

  • Une seule horloge de film pilote les scènes, la caméra, la bannière, les sous-titres et le son. Lorsque vous insérez un beat plus tard sans tout re-timer, utilisez un remappage : l'horloge de la scène s'arrête au point d'insertion tandis que les superpositions gardent l'horloge réelle :
    const INS = [[24.0, 5.0, 'detail']];   // au temps de scène 24.0, joue un beat inséré de 5 s
    function remap(T) { let sh = 0; for (const [a, len, id] of INS) { if (T < a + sh) return { t: T - sh, ins: null }; if (T < a + sh + len) return { t: a, ins: id, u: T - sh - a, len }; sh += len; } return { t: T - sh, ins: null }; }
    
    Le script audio a besoin de la même table : écrivez un RT(t) qui ajoute les longueurs insérées à un temps de scène, et placez chaque repère à RT(t), ou chaque repère après l'insertion dérive. (Le modèle n'a pas d'insertions, donc son audio.py n'en a pas besoin.)
  • Easing : eio pour les mouvements de caméra, eo pour les choses qui arrivent, trap (vitesse trapézoïdale) pour la marche et la conduite, afin qu'un mouvement ne « clique » pas aux extrémités.
  • Les clés de caméra sont absolues A(pos, target) ou suivent F(offset, targetOffset) depuis le point de sol du héros. Mélangez entre les clés avec eio. Tenez sur un beat qui compte ; un plan qui bouge tout le temps donne une impression de nervosité.

Les superpositions (dans le DOM, au-dessus du canvas)

  • Bannière : année, puis entreprise, puis la pastille de rôle, plus une timeline dont le point respire sur l'année courante. La bannière change quand la nouvelle scène est À L'ÉCRAN (son décor est levé, la tenue a changé, le héros est arrivé), jamais quand le code commence à la construire. Vérifiez cela sur une feuille d'images à ±1 s autour de chaque changement.
  • Sous-titres : une ligne d'histoire par beat, avec la phrase clé en gras et en accent. Utilisez text-wrap: balance. Donnez au lecteur environ 3 mots par seconde, et fondez un sous-titre avant qu'un mouvement rapide de caméra ne découvre le sujet derrière lui.
  • Une bulle de parole qui suit un personnage : projetez le point de la tête et verrouillez la bulle à ≥24 px à l'intérieur du cadre.
  • La carte de fin : nom, une ligne d'accroche, ce dans quoi ils sont bons, une citation. La scène se floute derrière.

Audio

  • Les repères sont écrits sur l'horloge du film, à côté du moment auquel ils appartiennent (pas par étape de marche, un carillon quand une chose apparaît, un bruit sourd quand elle atterrit).
  • Pas de sons de whoosh sur les transitions ; ils donnent une impression de bas de gamme. Utilisez des carillons, des tics et des impacts doux.
  • Le lit sonore par défaut dans template/audio.py est généré à partir d'ondes sinusoïdales, donc il est libre d'utilisation partout. Si quelqu'un apporte une piste générée par IA, vérifiez sa licence : certains poids de modèles n'autorisent qu'un usage non commercial.
  • Volume : normalisation deux passes loudnorm à −14 LUFS (mesurer, puis appliquer linéairement), puis un limiteur. Une seule passe dépasse.

Faits de rendu qui nous ont coûté des jours (plus dans references/gotchas.md)

  • Rendez en 2x et réduisez. EffectComposer supprime l'anti-aliasing du canvas, donc un rendu 1x a des bords irréguliers partout.
  • Pas de marquage couleur sur le MP4. Un pipe JPEG le marque comme pleine plage, et certains lecteurs décalent alors les couleurs. setparams=...=unknown dans le filtre.
  • Deux visages dans le même plan scintillent (z-fighting). Donnez à celui de devant un décalage de profondeur.
  • Les polices doivent être chargées (document.fonts.load) avant que tout texte du canvas ne soit dessiné, sinon il tombe silencieusement en secours.
  • GPU activé dans Chromium sans tête (--use-angle=metal sur macOS). Sans cela, un rendu est environ 10x plus lent.

Travailler sans demande à chaque étape

La personne a dit oui aux règles d'autorisation du kit une fois (SETUP.md étape 4) ; restez à l'intérieur, sinon on lui redemande encore et encore :

  • Écrivez et modifiez les fichiers avec les outils Write et Edit : pages, reel.json, brief, storyboard, AUDIT.md. Ne les générez pas avec un script Python ou shell, un heredoc ou sed -i ; chacun de ces éléments est une demande d'approbation.
  • Mesurez avec les outils du kit (stills, probe, sheet, collide, render, cover), pas avec des extraits python3 -c ponctuels.
  • Pas besoin de mkdir, boucles ou chaînes : chaque outil crée son propre dossier de sortie et prend une liste de temps en un seul appel (stills.mjs … 1.5,6,12).
  • Les scripts propres à un reel (son script sonore, une aide) vivent dans reels/<nom>/ et s'exécutent avec python3 reels/<nom>/audio.py ou node reels/<nom>/x.mjs, ce que les règles couvrent.

Commandes

Exécutez chaque outil comme une seule commande simple (drapeaux, pas de VAR=… en tête, pas de boucles, pas de chaînes &&). Ainsi, les règles d'autorisation de la personne (node tools/*) les couvrent et on ne lui demande pas d'approuver chaque étape. Les variables d'environnement fonctionnent toujours pour les scripts.

npm run doctor                                  # vérifie cette machine d'abord
npm run demo                                    # la preuve de 12 secondes : out/demo/
node tools/stills.mjs "2,8.5,15"                # images fixes 2x → out/stills (le modèle voxel)
node tools/stills.mjs --page template/starter.html --format 16:9 1.6        # le starter à un autre ratio
node tools/stills.mjs --page template/starter.html --cfg reel.zh.json 1.6   # une autre config (ici : chinois)
node tools/stills.mjs --dsf 1 --out out/chk 2,8.5                           # images rapides 1x pour une feuille
python3 tools/sheet.py out/chk/sheet.jpg 6 300 out/chk/t*.jpg
node tools/render.mjs --page reels/<nom>/page.html --out reels/<nom>/out/film-silent.mp4
python3 template/audio.py out/film.wav
zsh tools/mux.sh out/film-silent.mp4 out/film.wav out/film.mp4

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

thativanng/reels-maker

The gates every code-rendered film passes before anyone sees it. A 40 fps collision pass (no mover touches a solid or another mover), pixel probes (nothing sits over or behind a face, a head, a subtitle or the frame edge), then an independent auditor (a fresh agent) who reads frame sheets at ≥2 fps and signs off. The builder never signs off their own film. Use it before sending ANY render, after every fix round, and whenever someone says "check the film", "audit this", "is it ready", or "why does this frame look wrong".

thativanng/reels-maker

The interview before any video is built. It reads what the person already gave (source text, CV, links, brand files), then asks the rest in a few short rounds of numbered questions with a recommended answer marked, always including the format (platform, reel or video, ratio, layout, length, sound). It ends in a one-screen brief that splits "you said" from "I assumed", plus a storyboard, and builds nothing until the person says yes. Use it whenever someone asks for a reel, a video, an explainer, a career film, an animation or a "make a video about X", before film-engine or any style pack, and again when a request changes its purpose, platform or audience mid-way.

thativanng/reels-maker

Picks the look of a reel or film before it is built. It shows three genuinely different looks as stills of the same opening frame with the same words, so the person judges the look and not the content. It keeps a log of every look ever shown, so no look comes back unless asked for, and it locks one look on purpose for a series. Use it after reel-intake's brief is signed and before any test strip, whenever someone says "what should it look like", "give me options", "make it look different from last time", "it looks cheap", or starts a new reel or a new series.

thativanng/reels-maker

The voxel career-film style. A blocky 3D version of the person walks, without ever vanishing, through one scene per role. Their outfit changes as they walk, each scene rises out of the floor ahead of them, and a dark banner tracks year, company and role. Use it when someone wants their career, a journey or a "how I got here" told as a short 3D film for LinkedIn or a portfolio, says "make my career film", "turn my CV into a video", "voxel film", or wants a new chapter added to an existing one. It runs on film-engine (render, audio, finish) and must pass film-audit before anything is sent.

Skills associés