Que fait What-If Reel Maker ?
L’utilisateur donne UNE ligne (par exemple « et si la Lune disparaissait pendant 5 secondes »). Vous faites tout le reste et fournissez final.mp4 (1080×1920, 30 ips, 60 s, narré, sous‑titré, avec effets sonores) ainsi que caption.txt pour Instagram. Ne posez pas de questions sauf si l’idée n’est pas claire. Choisissez des valeurs par défaut sensées et dites lesquelles vous avez choisies.
Le style maison est un lieu réel en 3D low-poly construit en code (Three.js). Il comporte un compte à rebours en haut à gauche, des sous-titres en italique serif, une section « rayons X » avec contours blancs sur fond noir, un plan large (planète/espace/micro), une escalade des conséquences et une carte de fin avec un bouton d’abonnement. Pseudo : @the.whatif.studio.
0. Configuration unique (vérifier, installer uniquement ce qui manque)
Nécessite Node 18+, Python 3.10+ et ffmpeg dans le PATH (winget install ffmpeg / brew install ffmpeg).
Racine du projet : ~/whatif/ (créer si absent). Les fichiers partagés du moteur se trouvent dans la racine, et chaque vidéo dans videos/<slug>/.
mkdir -p ~/whatif/models ~/whatif/videos && cd ~/whatif
npm init -y && npm i [email protected] playwright @fontsource/cormorant-garamond @fontsource/ibm-plex-mono
npx playwright install chromium
pip install kokoro-onnx soundfile scipy numpy
curl -L -o models/kokoro-v1.0.onnx https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx
curl -L -o models/voices-v1.0.bin https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/voices-v1.0.bin
Copiez ensuite les fichiers du moteur depuis le dossier engine/ de cette compétence vers la racine s’ils n’existent pas (voir section 9). Sous Windows, utilisez python au lieu de python3.
1. La physique d’abord (le plus important)
Les commentateurs vérifieront la science. Avant d’écrire quoi que ce soit :
- Déterminez ce qui se passe RÉELLEMENT. Rédigez le raisonnement et tous les nombres dans
videos/<slug>/physics.md, et calculez les nombres avec un petit script Python. - Cherchez le twist contre‑intuitif (ex. gravité coupée : rien ne semble se passer au début, car la roche, l’eau et l’air comprimés jaillissent vers l’extérieur et cette poussée ressemble à la gravité). Le twist est l’accroche.
- Vérifiez les affirmations clés par une recherche web quand elle est disponible. Si quelque chose est incertain, adoucissez le propos (« pendant des minutes », « des kilomètres ») et n’inventez jamais de chiffres précis.
2. Script (videos/<slug>/script.json)
Suivez ce modèle de battement 60 s (décalez les temps si l’histoire le nécessite) :
| Temps | Battement | Visuel | HUD |
|---|---|---|---|
| 0–8 | Monde normal, accroche | travelling lent à travers le lieu ; titre 0.2–3.9 | compte à rebours <ÉVÉNEMENT DANS> de 8.00 S → 0, sous‑titre = lieu |
| 8.0 | L’événement se produit | ondulation + impulsion chromatique | — |
| 8–28 | Fenêtre de l’événement, montrée au ralenti (ex. 5 s réelles à 4×) | d’abord vue normale, puis rayons X | <FIN DE L’ÉVÉNEMENT DANS> 5.00 S, sous‑titre MONTRE 4× PLUS LENT · <statut en direct> |
| 16–24 | Mécanisme caché | mode contours + particules lumineuses | identique |
| 24–28 | Plan large | scène séparée (planète/espace/cellules), flash blanc entrée & sortie | identique |
| 28 | Retour | flash + boom | <CHOSE EST> / DE RETOUR |
| 28–52 | Escalade des conséquences | secousses, fissures, vagues, débris, etc. | statistique clé (ex. 176 KM/H) |
| ~46 | Chute | — | « Et oui. <conséquence>. » |
| 51.2–52 | Fondu au noir | ||
| 52–60 | Carte de fin | ligne de fait + SUIVEZ POUR PLUS DE WHAT IFS, appui sur bouton ~57.3 | — |
Narration : 14–16 lignes, ≤3 mots par seconde, ton documentaire calme. La ligne 1 à 0.3 s est la question du titre. La carte de fin comporte deux lignes : un fait en une phrase (~52.7) et « Suivez pour plus de what ifs. » (~56.6). Les sous‑titres sont des versions raccourcies des lignes de narration (≤2 lignes, <br> entre).
{
"handle": "@the.whatif.studio",
"voice": "am_michael",
"title": "Et si la gravité disparaissait<br>pendant 5 secondes ?",
"titleEnd": 3.9,
"endTitle": "Et si la gravité disparaissait pendant 5 secondes ?",
"endFact": "Vous ne ressentez jamais la gravité. Vous ressentez le sol qui pousse en retour.",
"duration": 60, "endStart": 52, "press": 57.3,
"narration": [[0.3, "Et si la gravité disparaissait… pendant cinq secondes ?"], [4.1, "En ce moment même, la gravité tire sur chaque atome de ce parc."]],
"captions": [[4.1, 7.9, "En ce moment même, la gravité tire<br>sur chaque atome de ce parc."]]
}
3. La voix d’abord, puis corriger le timing
Exécutez python3 gen.py <slug>. Cela écrit videos/<slug>/audio/lNN.wav et durs.json et affiche la durée de chaque ligne. Si une ligne chevauche la suivante ou un changement de battement, raccourcissez le texte ou déplacez‑le, puis relancez. Ensuite, réglez chaque sous‑titre sur [début, début + durée + 0.35, texte]. Voix : am_michael (masculin par défaut), af_heart (meilleure féminine), bm_george (britannique masculin).
4. Construire la scène (videos/<slug>/scene.js)
Écrivez une nouvelle scène pour chaque vidéo. Elle doit exporter build(h), update(t, h) et hud(t) (modèle dans la section 9). Règles :
- Déterministe : utilisez uniquement
h.rnd()/h.R(a,b)(ensemencé) au moment de la construction. Tout ce qui est dansupdateest une fonction pure det. N’utilisez jamaisMath.random,Dateouperformance.now. - Ralenti via le temps monde :
w = t<8 ? t : t<28 ? 8+(t-8)/4 : 13+(t-28). Animez les personnages, l’eau et les nuages avecw. - Apparence : primitives low-poly avec
flatShading. Modélisez un lieu réel de manière approximative (jetée, parc, rue, plage). Boîtes pour les bâtiments (texture de fenêtre canvas), personnages boîte+sphère de couleurs variées, arbres instanciés, lampadaires noirs avec globes blancs. Ajoutez un shader de ciel en dégradé, des nuages sprite,THREE.Fogpour la profondeur, et unDirectionalLightsolaire avec ombres (camera d’ombre ±45) +HemisphereLight. - Caméra : FOV vertical ~58, hauteur des yeux 1.7–2.2 m, travelling lent et inclinaisons douces. Dans les conséquences, ajoutez des secousses avec des sinusoïdes sommées.
- Phase rayons X : renvoyez
outline: 0→1(fondu sur ~0.6 s). Pendant celle‑ci, remplacez les cartes des bâtiments parnullet cachez les nuages (évite les bords bruités). Renvoyez éventuellementoverScene: une scènePointsadditive (depthTest false) pour les traînées/particules. - Plan large : construisez une seconde scène + caméra et renvoyez‑les comme
scene/camerapour 24–28. - FX renvoyés par
update:flash(0–1 blanc),chroma,ripple+rp(rayon de l’anneau),fade(0→1 à 51.2–52). - Performances : gardez les appels de dessin sous ~400 (instancing), et évitez beaucoup de grands sprites transparents près de la caméra, car cette surcharge est très lente.
- Gardez le texte hors des 20 % du bas et du bord droit (interface Instagram). Les sous‑titres se trouvent à y≈1240.
5. Prévisualiser, puis corriger
Exécutez node render.js preview <slug> 2,6,10,18,22,26,30,40,47,55. Cela écrit des JPEG dans videos/<slug>/prev/. Ouvrez‑les et vérifiez : le lieu est‑il lisible, les sous‑titres sont‑ils lisibles, le mode contours est‑il net, le plan large est‑il bien cadré, les conséquences sont‑elles dramatiques ? Corrigez les problèmes et prévisualisez à nouveau. Ne rendez la vidéo complète que lorsque les images fixes semblent bonnes.
6. Rendre les couches
La scène (plateau) et le texte (superposition) sont rendus séparément, afin que les corrections de texte ne nécessitent pas un nouveau rendu 3D.
# plateau : diviser entre plusieurs processus (un par 2 cœurs CPU), chacun sur son propre PORT ; seulement 0..endStart (le reste est noir)
LAYER=plate PORT=8781 node render.js full <slug> plate1.mp4 0 26
LAYER=plate PORT=8782 node render.js full <slug> plate2.mp4 26 52
LAYER=overlay PORT=8783 node render.js full <slug> overlay.mov 0 60
Exécutez ces commandes en arrière‑plan et surveillez les journaux. Si WebGL signale SwiftShader (lent, CPU), essayez HEADFUL=1 pour utiliser le vrai GPU.
7. Son (videos/<slug>/mix.py)
Copiez le modèle de mix depuis la section 9 et modifiez le bloc EVENTS pour correspondre aux battements : ambiance, tic‑tac du compte à rebours, une montée avant l’événement, boom sur l’événement et le retour, un shimmer pendant les rayons X, un whoosh vers le plan large, un grondement/fissures ou autres sons de conséquences, le pad de fin et le pop du bouton. Il place la narration automatiquement et réduit les effets sous la voix. Exécutez‑le, puis normalisez :
python3 videos/<slug>/mix.py <slug>
ffmpeg -y -i videos/<slug>/mix.wav -af loudnorm=I=-14:TP=-1.5:LRA=11 -ar 48000 videos/<slug>/mix_norm.wav
8. Composer et livrer
cd videos/<slug>
ffmpeg -y -i plate1.mp4 -i plate2.mp4 -f lavfi -t 8 -i "color=black:s=1080x1920:r=30" -i overlay.mov -i mix_norm.wav \
-filter_complex "[0:v][1:v][2:v]concat=n=3:v=1:a=0,format=yuv420p,setsar=1[b];[b][3:v]overlay=format=auto,format=yuv420p[v]" \
-map "[v]" -map 4:a -c:v libx264 -preset veryfast -crf 23 -c:a aac -b:a 192k -movflags +faststart -shortest final.mp4
(La durée du clip noir = durée − endStart.) Extrayez 8–10 images de final.mp4 et examinez‑les avant de livrer. Écrivez caption.txt : une ligne d’accroche, 2–3 phrases de la physique réelle, « Suivez @the.whatif.studio pour plus de what ifs », et 12–15 hashtags (#whatif #physics #science #3danimation …). Dites à l’utilisateur qu’il peut ajouter une musique douce dans CapCut à 15–20 % du volume.
9. Fichiers du moteur
Le moteur réutilisable se trouve dans le dossier engine/ de cette compétence. Copiez les fichiers – ne les retapez pas. Un moteur partagé est réutilisé par chaque vidéo ; deux fichiers sont copiés par vidéo puis modifiés.
Moteur partagé (copier une fois dans ~/whatif/) :
engine/index.html→~/whatif/index.htmlengine/main.js→~/whatif/main.jsengine/render.js→~/whatif/render.jsengine/gen.py→~/whatif/gen.py
Par vidéo (copier pour chaque nouvelle vidéo, puis modifier) :
engine/scene.template.js→videos/<slug>/scene.js— réécrivez la scène pour chaque vidéo (voir section 4). Doit exporterbuild(h),update(t, h),hud(t).engine/mix.py→videos/<slug>/mix.py— modifiez le bloc EVENTS pour correspondre aux battements (voir section 7).
# SKILL_DIR = dossier de cette compétence ; exécutez depuis la racine du projet (~/whatif)
cp "$SKILL_DIR"/engine/{index.html,main.js,render.js,gen.py} ~/whatif/
cp "$SKILL_DIR"/engine/scene.template.js videos/<slug>/scene.js
cp "$SKILL_DIR"/engine/mix.py videos/<slug>/mix.py
Liste de contrôle qualité avant livraison
- Physique vérifiée et nombres calculés ; le twist est clair dans les 15 premières secondes.
- Chaque ligne de narration tient dans son battement sans chevauchement ; les sous‑titres correspondent à la narration.
- Les prévisualisations étaient bonnes ; la vidéo finale a été vérifiée sur 8–10 images.
- Le pseudo affiche @the.whatif.studio ; la carte de fin fonctionne et l’appui sur le bouton a lieu juste après « Suivez pour plus de what ifs ».
- Le niveau sonore est d’environ −14 LUFS ; la voix est nettement au‑dessus des effets.