Creador de Reels 'Qué pasaría si…'
El usuario proporciona UNA línea (ej. "¿Qué pasaría si la Luna desapareciera durante 5 segundos?"). Tú haces todo lo demás y entregas final.mp4 (1080×1920, 30 fps, 60 s, narrado, subtitulado, con efectos de sonido) más caption.txt para Instagram. No hagas preguntas a menos que la idea no esté clara. Elige valores predeterminados sensatos y di cuáles elegiste.
El estilo característico es una ubicación real del mundo en 3D low-poly construida en código (Three.js). Tiene un HUD de cuenta regresiva en la esquina superior izquierda, subtítulos en serif itálica, una sección de "rayos X" con contorno blanco sobre fondo negro, una toma de gran angular (planeta/espacio/micro), una escalada de consecuencias y una tarjeta final con un botón de seguir. Handle: @the.whatif.studio.
0. Configuración única (verificar, instalar solo lo que falte)
Requiere Node 18+, Python 3.10+ y ffmpeg en PATH (winget install ffmpeg / brew install ffmpeg).
Raíz del proyecto: ~/whatif/ (crear si no existe). Los archivos compartidos del motor viven en la raíz, y cada video vive en 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
Luego copia los archivos del motor de la carpeta engine/ de esta habilidad a la raíz si no existen (ver sección 9). En Windows usa python en lugar de python3.
1. Física primero (lo más importante)
Los comentaristas verificarán la ciencia. Antes de escribir nada:
- Averigua qué sucede REALMENTE. Escribe el razonamiento y cada número en
videos/<slug>/physics.md, y calcula los números con un rápido script de Python. - Busca el giro contra intuitivo (ej. gravedad desactivada: al principio no parece pasar nada, porque la roca comprimida, el agua y el aire saltan hacia afuera y ese empuje se siente como gravedad). El giro es el gancho.
- Verifica las afirmaciones clave con búsqueda en la web cuando esté disponible. Si algo es incierto, suaviza la redacción ("durante minutos", "kilómetros") y nunca inventes cifras precisas.
2. Guion (videos/<slug>/script.json)
Sigue esta plantilla de tiempos de 60 s (desplaza los tiempos si la historia lo necesita):
| Tiempo | Beat | Visual | HUD |
|---|---|---|---|
| 0–8 | Mundo normal, gancho | dolly lento por la ubicación; título 0.2–3.9 | <EVENTO> EN cuenta atrás 8.00 S→0, sub = ubicación |
| 8.0 | Ocurre el evento | onda expansiva + pulso de croma | — |
| 8–28 | Ventana del evento, mostrada en cámara lenta (ej. 5 s reales a 4x) | primera vista normal, luego rayos X | <EVENTO TERMINA EN> 5.00 S, sub MOSTRADO 4X MÁS LENTO · <estadística en vivo> |
| 16–24 | Mecanismo oculto | modo contorno + partículas brillantes | mismo |
| 24–28 | Gran imagen | escena separada (planeta/espacio/células), destello blanco de entrada y salida | mismo |
| 28 | Regreso | destello + explosión | <COSA> ESTÁ / DE VUELTA |
| 28–52 | Consecuencias escalan | sacudida, grietas, olas, escombros, etc. | estadística clave (ej. 176 KM/H) |
| ~46 | Remate | — | "Y sí. ." |
| 51.2–52 | Fundido a negro | ||
| 52–60 | Tarjeta final | línea de hecho + SIGUE PARA MÁS QUÉ PASARÍA SI, pulsación de botón ~57.3 | — |
Narración: 14–16 líneas, ≤3 palabras por segundo, tono documental tranquilo. La línea 1 a los 0.3 s es la pregunta del título. La tarjeta final tiene dos líneas: un hecho de una oración (~52.7) y "Sigue para más qué pasaría si." (~56.6). Los subtítulos son versiones abreviadas de las líneas de narración (≤2 líneas, <br> entre ellas).
{
"handle": "@the.whatif.studio",
"voice": "am_michael",
"title": "¿Qué pasaría si la gravedad desapareciera<br>durante 5 segundos?",
"titleEnd": 3.9,
"endTitle": "¿Qué pasaría si la gravedad desapareciera durante 5 segundos?",
"endFact": "Nunca sientes la gravedad. Sientes el suelo empujando hacia arriba.",
"duration": 60, "endStart": 52, "press": 57.3,
"narration": [[0.3, "¿Qué pasaría si la gravedad desapareciera... durante cinco segundos?"], [4.1, "Ahora mismo, la gravedad está tirando de cada átomo de este parque."]],
"captions": [[4.1, 7.9, "Ahora mismo, la gravedad está tirando<br>de cada átomo de este parque."]]
}
3. Voz primero, luego ajustar tiempos
Ejecuta python3 gen.py <slug>. Escribe videos/<slug>/audio/lNN.wav y durs.json e imprime la duración de cada línea. Si una línea se superpone con la siguiente o con un cambio de beat, acorta el texto o muévelo, luego vuelve a ejecutar. Después establece cada subtítulo como [inicio, inicio + duración + 0.35, texto]. Voces: am_michael (masculino por defecto), af_heart (mejor femenina), bm_george (masculino británico).
4. Construir la escena (videos/<slug>/scene.js)
Escribe una nueva escena para cada video. Debe exportar build(h), update(t, h) y hud(t) (plantilla en la sección 9). Reglas:
- Determinista: usa solo
h.rnd()/h.R(a,b)(con semilla) en tiempo de construcción. Todo enupdatees una función pura det. Nunca usesMath.random,Dateniperformance.now. - Cámara lenta mediante tiempo del mundo:
w = t<8 ? t : t<28 ? 8+(t-8)/4 : 13+(t-28). Anima personas, agua y nubes conw. - Aspecto: primitivas low-poly con
flatShading. Modela un lugar real de forma aproximada (embarcadero, parque, calle, playa). Cajas para edificios (textura de ventana con canvas), personas de caja+esfera en colores variados, árboles instanciados, farolas negras con globos blancos. Añade un sombreador de cielo degradado, nubes de sprites,THREE.Fogpara profundidad, y un solDirectionalLightcon sombras (cámara de sombra ±45) +HemisphereLight. - Cámara: FOV vertical ~58, altura de ojo 1.7–2.2 m, dolly lento e inclinaciones suaves. En las consecuencias, añade vibración a partir de senos sumados.
- Fase de rayos X: devuelve
outline: 0→1(fundido en ~0.6 s). Mientras está activo, cambia los mapas de los edificios anully oculta las nubes (detiene bordes ruidosos). Opcionalmente devuelveoverScene: una escenaPointsaditiva (depthTest false) para estelas/partículas. - Toma de gran angular: construye una segunda escena + cámara y devuélvelos como
scene/camerapara 24–28. - FX devueltos desde
update:flash(0–1 blanco),chroma,ripple+rp(radio del anillo),fade(0→1 en 51.2–52). - Rendimiento: mantén las llamadas de dibujo por debajo de ~400 (instanciado), y evita muchos sprites transparentes grandes cerca de la cámara, porque ese sobredibujado es muy lento.
- Mantén el texto fuera del 20% inferior y del borde derecho (interfaz de Instagram). Los subtítulos se sitúan en y≈1240.
5. Previsualizar, luego corregir
Ejecuta node render.js preview <slug> 2,6,10,18,22,26,30,40,47,55. Escribe JPEGs en videos/<slug>/prev/. Ábrelos y verifica: ¿se reconoce el lugar? ¿los subtítulos son legibles? ¿el modo contorno está limpio? ¿la toma de gran angular está bien encuadrada? ¿las consecuencias se sienten dramáticas? Corrige los problemas y previsualiza de nuevo. Solo renderiza el video completo cuando las imágenes fijas se vean bien.
6. Renderizar las capas
La escena (plato) y el texto (superposición) se renderizan por separado, así que las correcciones de texto no necesitan un rerenderizado 3D.
# plato: dividido en procesos (uno por cada 2 núcleos de CPU), cada uno en su propio PUERTO; solo 0..endStart (el resto es negro)
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
Ejecuta estos en segundo plano y revisa los registros. Si WebGL reporta SwiftShader (lento, CPU), prueba HEADFUL=1 para usar la GPU real.
7. Sonido (videos/<slug>/mix.py)
Copia la plantilla de mezcla de la sección 9 y edita el bloque EVENTS para que coincida con los beats: ambiente, tics de cuenta atrás, un crescendo antes del evento, boom en el evento y el regreso, un shimmer en rayos X, un whoosh al entrar en la gran imagen, un retumbo/grietas u otros sonidos de consecuencias, el pad final y el pop del botón. Coloca la narración automáticamente y reduce los efectos bajo la voz. Ejecútalo, luego normaliza:
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. Componer y entregar
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 duración del clip negro = duración − endStart). Extrae 8–10 fotogramas de final.mp4 y revísalos antes de entregar. Escribe caption.txt: una línea gancho, 2–3 oraciones de la física real, "Sigue a @the.whatif.studio para más qué pasaría si", y 12–15 hashtags (#quepasariasí #física #ciencia #animacion3d …). Indica al usuario que puede añadir música suave en CapCut al 15–20% de volumen.
9. Archivos del motor
El motor reutilizable reside en la carpeta engine/ de esta habilidad. Copia los archivos de ella, no los reescribas. Un motor compartido se reutiliza para cada video; dos archivos se copian por video y luego se editan.
Motor compartido (copiar una vez en ~/whatif/):
engine/index.html→~/whatif/index.htmlengine/main.js→~/whatif/main.jsengine/render.js→~/whatif/render.jsengine/gen.py→~/whatif/gen.py
Por video (copiar para cada nuevo video, luego editar):
engine/scene.template.js→videos/<slug>/scene.js— reescribe la escena para cada video (ver sección 4). Debe exportarbuild(h),update(t, h),hud(t).engine/mix.py→videos/<slug>/mix.py— edita el bloque EVENTS para que coincida con los beats (ver sección 7).
# SKILL_DIR = carpeta de esta habilidad; ejecutar desde la raíz del proyecto (~/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
Lista de verificación de calidad antes de entregar
- Física verificada y números calculados; el giro queda claro en los primeros 15 s.
- Cada línea de narración encaja en su beat sin superposiciones; los subtítulos coinciden con la narración.
- Las previsualizaciones se veían bien; el video final se revisó en 8–10 fotogramas.
- El handle muestra @the.whatif.studio; la tarjeta final funciona y la pulsación del botón ocurre justo después de "Sigue para más qué pasaría si".
- La sonoridad es de aproximadamente −14 LUFS; la voz se escucha claramente por encima de los efectos.