Que fait REEL-FROM-SCRIPT · v7 ?
Une compétence pour créer un reel 9:16 au rendu art-directed et infaillible — à partir d'un script que vous n'avez pas écrit, d'une référence à rétro-ingénierer et d'une nouvelle session sans mémoire de la précédente.
v5 a livré les mises en page et y a intégré le design en dur. v6 a déplacé chaque nombre dans PARAMS.json et a placé un validateur devant le rendu. v7 est ce que deux vrais reels ont appris à v6 — le cycle de six champs de couleur, l'affiche de couverture, l'animation de carte par scène, les plages de scènes contiguës, les fondus adaptatifs, les pièges audio, et un seul ./build.sh + scripts/qc.py qui refuse de livrer un résultat défectueux.
La promesse : le seul fichier qu'un humain édite est
PARAMS.json. La seule chose autorisée à dire non estprepare.py/qc.py. Tout le reste est généré, et tout ce qui est généré est reproductible à partir d'une seule commande.
0 · Si vous êtes nouveau : les 10 premières minutes
export PATH=/home/user/node22/bin:$PATH # Node >= 22
cd <projet> && ./build.sh --from render # ou suivez §3 depuis le début
Ensuite, lisez dans cet ordre : §1 (comment le look est construit) → §3 (la pipeline) → §6 (guide de design) → §9 (catalogue des échecs). N'inventez pas de mise en page : le squelette est le design.
Ne faites jamais ces quatre choses : taper une durée (mesurez la VO), coller un hex ou un px dans une composition (modifiez PARAMS.json), écrire index.html à la main (générez-le), ou livrer sans regarder la planche contact.
1 · Pourquoi le résultat a l'air conçu (les sept lois)
Ce sont les véritables décisions derrière chaque bonne image de cette série. Ce sont des règles, pas des goûts.
1. Une grille d'ancrage unique, fixée en bas. Accroche → hero → corps → chip → présentateur. La moitié inférieure ne bouge jamais : le chip est toujours à la même position y, le présentateur est toujours recadré par le cadre au même endroit. Seule la moitié supérieure se recompose. C'est pourquoi neuf scènes différentes se lisent comme un seul film.
2. Le hero est un mot, pas une phrase. 1–3 mots, dans une police condensée display à ~17–25 % de la largeur du cadre, interlignage serré (0,88). La ligne complète va dans le chip (3–6 mots, la chose qu'un spectateur en mode silencieux lit), le détail va dans la carte. Si vous ne pouvez pas le dire en 3 mots, le temps est en deux temps.
3. Chaque temps a un arrière-plan différent. Six champs (crème / bordeaux / noir quasi-pur / sauge / marine / lavande) cyclés pour que deux voisins ne correspondent jamais. Le changement de couleur est l'autre moitié de la transition. prepare.py échoue si deux scènes consécutives partagent un champ.
4. Preuve, pas décoration. Une carte existe pour montrer la chose : une liste de fichiers, un diff, un navigateur, un téléchargement, un compteur. Si un temps n'a pas d'artefact, il est de type type-led et n'a pas de carte. Une carte avec deux rangées a l'air cassée ; quatre à six rangées ont l'air délibérées (ou une maquette remplissant ≥ 55 % de la carte).
5. La première image est une affiche. La scène 1 est composée à t=0 (data-cover="1") : accroche, hero, carte et personnage déjà à l'écran, le chip atterrissant à 0,65 s. Un reel qui s'ouvre sur un champ vide perd le défilement.
6. Le mouvement est uniquement une transformation, et il arrive tôt. Les entrées sont de 0,24 à 0,34 s, power2/3/4.out, et se terminent dans la première moitié du temps. N'animez jamais le contenu textuel, n'interpolez jamais un nombre, ne laissez jamais une scène de 1,5 s passer 0,6 s à faire un fondu. Un lent déplacement du hero maintient la dernière seconde vivante.
7. Le son est une ponctuation, pas un papier peint. ≤ 1 signal par seconde : un pop sur chaque coupe, des ticks sur l'interface utilisateur, un crescendo sur les deux plus grands tournants, un carillon sur la révélation, une notification/ping sur l'appel à l'action. Tapis à 0,15 sous une VO à −16 LUFS ; master à −14 LUFS / ≤ −1 dBTP.
2 · Le contrat : ce qui est fixe, ce qui est à vous
Invariant — validé, pas modifiable par intuition
| Invariant | Appliqué par |
|---|---|
| Chaque paire texte/fond lisible | WCAG ≥ 4,5:1 sur 10 paires rendues + 6 paires de champs |
| Le hero est un hero et tient toujours | ≥ 120 px, taille dérivée, doit tenir dans --hero-lines dans --hero-band |
| Le hero ne chevauche pas l'accroche, ne touche jamais la carte | bande dérivée + --gap, échec dur |
| Texte du corps lisible sur un téléphone | ≥ 24 px et ≥ bodyMin |
| Rien ne se cache sous l'interface de la plateforme | bas du chip ≤ bas de la zone de sécurité, ≥ 55 % utilisable |
| Le chip ne peut jamais entrer en collision avec la carte | cardTop + cardHmax ≤ chipTop |
| Présentateur recadré par le cadre, jamais au-dessus du chip | presenterTop + h > 1.0, presenterTop ≥ chipBottom |
| Deux scènes consécutives ne partagent jamais un champ | data-field lu à partir de chaque composition |
| L'image 0 est une couverture | data-cover + une vérification d'instantané |
| Une pose différente dans chaque scène | un fichier de pose par scène, vérifié à la révision |
| Le livrable est lisible et assez fort | qc.py : résolution, fps, images, LUFS, pic vrai, trous silencieux |
Variable — vraiment à vous : valeurs de palette (6 champs + 4 tons papier, contraste permis) · format (9:16, 4:5, 1:1, 720p) · marges de la zone de sécurité · chaque rapport de grille et de type à l'intérieur du sol · archétype par scène · nombre de scènes · mots · durée · ensemble de poses · feuille de signaux · polices sur le disque.
Si vous voulez une mise en page que le validateur ne peut pas vérifier, vous modifiez le squelette et ajoutez la vérification. C'est le prix de la liberté, et c'est pourquoi le résultat ne peut pas être mauvais.
3 · La pipeline (l'ordre n'est pas négociable)
| # | Étape | Commande | Pourquoi ici |
|---|---|---|---|
| 0 | Rétro-ingénierie de la référence | §4 | vous ne pouvez pas reproduire un look que vous n'avez pas mesuré |
| 1 | Faits | — | une affirmation qui arrive tard force un ré-enregistrement |
| 2 | Script → sections | assets/vo/sections.json | une idée par temps, 1,2–9 s |
| 3 | VO d'abord | python3 scripts/process_vo.py | timeline.json est l'horloge ; l'image est coupée dessus |
| 4 | Look | PARAMS.json | palette, format, grille, sol typographique |
| 5 | Porte | python3 scripts/prepare.py | échoue sur le contraste / type / collision / rythme de champ |
| 6 | Scènes | ./scenes.sh | un appel new_scene.py par temps, jetons injectés |
| 7 | Racine | python3 scripts/build_index.py | plages contiguës, fondus adaptatifs, pas de index.html tapé à la main |
| 8 | Lint | npx --yes [email protected] lint | 0 erreurs est une porte |
| 9 | Regardez-le | npx … snapshot --at "0,1.5,4,…" | la seule étape qui attrape "correct mais moche" |
| 10 | Rendu | npx … render --output renders/_raw.mp4 | ~1 m 45 s pour 32 s à 1080×1920, logiciel GL |
| 11 | Mixage | python3 scripts/mix_audio.py | VO + tapis + signaux → renders/master.wav (−14 LUFS) |
| 12 | Mux + livraison | build.sh étape 6–7 | mp4 + .srt + vignettes, puis qc.py |
./build.sh exécute 3 → 12 en une fois. ./build.sh --from render ignore la VO lorsqu'elle est déjà mesurée.
Étape 3 en détail — la VO est l'horloge
# un clip par section, nommé vo1.mp3 … voN.mp3 dans assets/vo/
python3 scripts/process_vo.py
Il supprime le silence, applique atempo uniquement si script_target est défini, normalise le volume de chaque prise à −16 LUFS, puis écrit assets/vo/timeline.json : début/durée/fin par section + root_duration. Rien en aval n'est autorisé à connaître une durée qui n'est pas dans ce fichier.
Écrivez say en devanagari avec des mots techniques anglais en latin (resume, job description, ATS score, DM) — une voix hi-IN obtient la prosodie correcte et dit quand même les mots anglais. caption est ce que le .srt affiche.
Étape 7 en détail — la racine est mécanique
build_index.py trouve compositions/s*.html dans l'ordre numérique, lit les plages mesurées, les rend contiguës (0 → coupé → coupé → … → racine, donc aucun trou noir n'apparaît là où la VO a un écart de 0,30 s), déclenche un fondu 0,36 s avant chaque coupé dans la couleur de la scène arrivante, et maintient la dernière scène jusqu'à la fin de la queue audio. Un fondu est raccourci à 34–62 % de la longueur d'une scène courte — une scène de 1,4 s ne peut pas contenir un fondu de 0,62 s.
Étape 11 en détail — les deux pièges audio
alimiteralevel=truepar défaut : il remonte automatiquement le niveau jusqu'au plafond, donc votre "limiteur" devient un compresseur + gain de compensation et le mixage atterrit à −12,5 LUFS pendant que vous visez −14. Toujourslevel=false.loudnormen un seul passage linéaire dépasse la cible. Mesurez avecebur128, déplacez-vous d'exactementcible − mesuré, puis limitez. Une arithmétique que vous pouvez vérifier bat un filtre qui devine.
4 · Phase 0 — rétro-ingénierie d'une vidéo de référence
Quand le brief est "regarde ça et reproduis-le", mesurez-le. Dix minutes, cinq commandes :
ffprobe -v error -show_entries format=duration:stream=width,height,r_frame_rate,codec_type -of default=nw=1 ref.mp4
ffmpeg -i ref.mp4 -vf "fps=1,scale=400:-1,tile=6x6" -frames:v 1 sheet.jpg # le film entier en une seule image
python3 - <<'P' # la palette de champs, par seconde
from PIL import Image; import glob
for f in sorted(glob.glob("frames/f_*.jpg"))[::2]:
im = Image.open(f).convert("RGB"); w,h = im.size
print(f[-7:-4], im.getpixel((3,3)), im.getpixel((w-4,3)))
P
ffmpeg -i ref.mp4 -vn -ac 1 -ar 16000 -c:a pcm_s16le audio.wav # pour le script
Lisez-en : la durée et le rythme des coupes (combien de temps dure chaque temps), la palette de champs (échantillonnez les coins, pas le milieu), le comportement typographique (capitales condensées ? constructions mot par mot ? boîtes de surbrillance ?), la mise en page (où se trouve le personnage, où se trouve le bloc de texte), les artefacts d'interface (quelles maquettes), le son (densité des signaux). Ces six nombres sont l'ensemble de la direction artistique.
Si le brief vous a donné une référence mais pas de script, la référence est le script : transcrivez l'audio (faster-whisper, int8, modèle base → ~7 s pour 32 s de Hinglish) et lisez le texte à l'écran à partir des images. Ne réécrivez pas le texte — une série a une voix.
Traduisez, ne copiez pas. La référence ici était 1280×720 ; le livrable était 1080×1920. Même palette, même type, mêmes maquettes — mais la bande hero, l'ancre chip et le recadrage du présentateur ont été redérivés sous forme de ratios. En 9:16, les blocs de 8–10 mots de la référence tombent en dessous du sol du corps à 24 px, donc le texte est divisé différemment : hero 1–3 mots, chip la ligne, carte le détail.
5 · Fichiers
PARAMS.json le seul fichier de design
tokens.css reçu généré (ne pas éditer)
index.html généré par build_index.py (ne pas éditer)
SKILL.md · COMPONENTS.md · README.md
build.sh toute la pipeline
scenes.sh chaque scène, de manière reproductible
components/ 7 corps de carte que vous pouvez passer avec --card-body @…
compositions/
_scene-base.html.tmpl LE squelette — zéro hex littéral, zéro px littéral
wipe.html la seule transition
sN-*.html généré par new_scene.py
_examples/ trois scènes travaillées (non montées : build_index lit uniquement compositions/s*.html)
scripts/
process_vo.py VO → timeline.json
prepare.py la porte : sol + injection de jetons
new_scene.py modèle de base → une scène correcte
build_index.py timeline + scènes → racine
mix_audio.py VO + tapis + signaux → master.wav
make_deliverables.py .srt + vignettes
qc.py une commande, PASS/FAIL sur 10 portes
cutout.py · gen_sfx.py ressources
assets/{fonts,presenter,vo,sfx,music}/
6 · Guide de design (quoi choisir concrètement)
Temps → archétype. Preuve → card-led. Un nombre → stat-led (odomètre, --digits). Une déclaration, une transition, une carte de marque → type-led. L'accroche et l'appel à l'action sont presque toujours card-led car les deux ont besoin d'un artefact (la liste de fichiers qui prouve le problème ; le fil de commentaires qui prouve l'appel à l'action).
Temps → champ. Alternez chaud et froid ; ne répétez jamais. Un cycle pratique pour six champs : accent → ground → ink → secondary → tertiary → quaternary. Les champs sombres (ink, tertiary) font disparaître le présentateur, donc le halo passe à 0,20 → 0,42 là (le squelette le fait à partir de data-field) ; utilisez-les pour la révélation de l'outil et pour le temps "l'IA fait le travail", où le drame aide.
Temps → pose. Même personnage, même tenue, une pose par scène, adaptée à l'émotion de la ligne : haussement d'épaules (une question) · facepalm (le problème) · présent (l'offre) · menton (curieux) · mémoire (rappel) · pouce (la victoire) · point (une étape) · idée (le déclic) · CTA (la demande). Générez une pose manquante à partir de l'image de base et détourez-la avec cutout.py ; gardez la règle du fond blanc et le recadrage mi-cuisse pour qu'ils se détachent proprement.
Mots à l'écran. Hero : le verbe émotionnel ou le nombre (MÊME CV ?, CUSTOMIZE KARO, TAILOR, SCORE ATS). Chip : la phrase dont un spectateur en mode silencieux a besoin (har company mein bhej rahe ho?). Titre de la carte : ce qu'est l'artefact (applied / 12 companies). Méta de la carte : un petit fait vrai (this week, matched 3 of 7).
Quand un temps est trop court pour être conçu (1–2 s). Gardez la scène, supprimez la deuxième couche : hero + chip + présentateur, type-led, une seule révélation. Ne tassez pas une carte et une liste décalée en 1,4 s — cela se lit comme un bug.
Quand un temps est long (8–9 s, généralement l'appel à l'action). Échelonnez trois révélations à 1,8–2 s d'intervalle (commentaire → DM → lien) et laissez un lent déplacement porter la fin. Une image statique de 8 s est la cause unique la plus courante du "ça a l'air bon marché".
Transitions. Un seul fondu, 0,34–0,62 s, couleur = le champ de la scène arrivante, direction alternée. Aucun autre type de transition : la cohérence est ce qui fait que huit coupes semblent conçues.
La dernière seconde. L'image finale doit être une image conçue avec la poignée et le site dessus — le spectateur qui s'arrête là doit pouvoir agir.
7 · Guide audio
| Moment | Signal | Gain |
|---|---|---|
| chaque coupe | pop | 0,50 |
| les deux plus grands tournants | riser 0,3 s avant la coupe | 0,28–0,30 |
| un élément d'interface qui atterrit | click, key | 0,38–0,45 |
| une liste qui se défile | key ×N, à 0,12 d'intervalle | 0,40 |
| une révélation / un score | chime | 0,36–0,42 |
| Appel à l'action | notify, puis ping 1,7 s plus tard | 0,32–0,40 |
| Erreur / rejet | error (avec parcimonie — cela se lit comme comique une seule fois) | 0,30 |
Les décalages des signaux sont relatifs à la section dans assets/sfx/cues.json ("vo7+1.68"), donc une VO ré-enregistrée n'invalide pas le design. Ne faites jamais atterrir un signal sur la première syllabe d'un mot ; un tick appartient à 20–60 ms après le début du mot. Le pop de coupe à 0,50 est le seul son qui ne nécessite jamais d'ajustement.