code-video: Haz que un modelo de lenguaje grande escriba código y dibuje fotograma a fotograma videos divulgativos
La imagen no se genera con modelos de video ni se graba: el modelo escribe una página web (Canvas / SVG / Three.js / WebGL),
la página expone __render(t), un script captura la pantalla fotograma por fotograma y ffmpeg los codifica en mp4.
La ventaja es que es reproducible, modificable, con texto y números absolutamente precisos y sin costo de generación.
Todo el proceso consta de tres pasos: Elegir estilo → Redactar el prompt detallado → Primero verificar con fotogramas de prueba, luego renderizar el video completo.
0. Preparación (primer uso)
cd <directorio de la skill>
npm install # Instalar playwright-core
npx playwright-core install chromium-headless-shell # O configurar CHROME=/path/to/chrome
# Se necesita ffmpeg / ffprobe en PATH; se recomienda instalar una fuente CJK como Noto Sans CJK (fonts-noto-cjk / noto-fonts-cjk)
pip install edge-tts numpy scipy # Opcional: locución, subtítulos, síntesis de música
1. Elegir estilo: El estilo sigue al tema
Primero identifica a qué categoría pertenece el tema, luego lee el archivo de estilo correspondiente en references/styles/ (cada archivo incluye: temas adecuados,
prompt resumido, prompt completo, notas de producción, base factual y código de ejemplo en examples/<nombre>/).
| Tema | Probar primero | También se puede |
|---|---|---|
| Anécdotas, historias históricas | Sombras chinesas piying | Píxel pixel, Cómic comic |
| Divulgación infantil, crecimiento natural | Libro ilustrado picturebook | Motion graphics plano flatmg |
| Caracteres, artefactos, dinastías | Evolución de caracteres chinos hanzi | Tinta china ink |
| Rutas, embajadas, migraciones | Mapa antiguo oldmap | Flujo isométrico isometric |
| Estructuras mecánicas, despiece de productos | Despiece 3D explode3d | Pizarra blanca whiteboard |
| Procesos, líneas de producción | Flujo isométrico isometric | Motion graphics plano flatmg |
| Tamaño, profundidad, distancia | Escala scale | Infografía de datos infographic |
| Eras, órdenes de magnitud | Infografía de datos infographic | Escala scale |
| Teoremas, fórmulas | Visualización matemática math | Dibujo lineal lineart |
| Principio único, causa-efecto | Pizarra blanca whiteboard | Dibujo lineal lineart |
| Eslogan, intro/outro | Texto cinético kinetic | — |
Los 16 estilos completos se encuentran en references/styles/README.md. Cuando el usuario nombre un estilo específico, lee directamente ese archivo.
2. Redactar el prompt detallado: Una sola frase solo define el estilo
Una frase como "haz una animación de sombras chinesas de diez segundos" solo le dice al modelo el estilo, pero no sabe qué representar, qué números usar ni cuánto dura cada parte. Sigue la siguiente plantilla para especificar cuatro cosas (los prompts completos en los archivos de estilo siguen esta estructura):
Dibuja fotograma a fotograma con Canvas una animación divulgativa de 1920×1080, 30fps, unos 12 segundos, en estilo «...»: define la paleta de colores, la textura y la fuente.
El tema es "...": divide en varias tomas, qué muestra cada toma, qué texto aparece en pantalla, y termina con una frase que resuma la idea.
Los números a usar: ..., escribe la fuente en notes.txt; los números inciertos no los des con precisión de unidades.
Cada fotograma depende solo del tiempo t (sin temporizadores, usa semilla fija para números aleatorios).
Primero captura 4–6 fotogramas para verificar que los subtítulos y etiquetas sean lo suficientemente grandes, no se superpongan ni salgan del encuadre; luego renderiza el video completo.
Además, añade las reglas físicas/de hecho del tema que el modelo podría dibujar incorrectamente. Ejemplo: en la historia de Cao Chong pesando el elefante, el calado del barco debe calcularse según la carga, de lo contrario la marca no coincidirá con la línea de flotación; si no se escribe esta regla, el modelo lo dibujará mal.
3. Escribir la página: Contrato de página obligatorio
Cada video tiene un directorio <work>/<nombre>/, que contiene al menos index.html. Se recomienda también crear prompt.txt (el prompt usado)
y notes.txt (fuente de números y hechos). Puedes comenzar desde templates/canvas/index.html.
- La página tiene un tamaño fijo de 1920×1080, con
overflow:hidden. - Debe incluir esta línea (render.sh la lee con una expresión regular):
const FPS = 30, DUR = 12; window.__info = { fps: FPS, duration: DUR, frames: Math.round(FPS * DUR) };window.__render = t => { ...; return { seg: '<nombre de la toma>', tau: t.toFixed(2) }; }Cada fotograma depende solo de t: no uses CSS animation/transition, setTimeout, requestAnimationFrame,Date.now(),Math.random(); para valores aleatorios usa una semilla fija (por ejemplo, mulberry32); partículas, vibraciones, física deben poder calcularse directamente con t, sin acumular estado entre fotogramas.- Después de cargar fuentes y recursos, establece
window.__ready = true(las páginas WebGL lo establecen después de renderizar el primer fotograma). - No accede a internet (el script de captura bloqueará todas las solicitudes externas). Usa fuentes instaladas en el sistema.
- Debe ser legible en dispositivos móviles: etiquetas de texto ≥ 36px, títulos ≥ 64px, opcionalmente texto pequeño en el pie de página inferior izquierdo.
- Páginas Three.js:
scripts/fetch_three.sh <nombre>descarga en<nombre>/vendor/, luego<script type="importmap">{ "imports": { "three": "./vendor/three.module.js", "three/addons/": "./vendor/jsm/" } }</script>; configura el renderer conpreserveDrawingBuffer: true, y en__render(t)llama sincrónicamente arenderer.render()(o composer).
Detalles y errores comunes en references/page-contract.md.
4. Primero captura fotogramas de prueba para que el modelo los vea, luego renderiza el video completo
scripts/render.sh <work>/<nombre> 30,120,210,300 # Captura solo estos fotogramas -> <work>/_preview/<nombre>/
Usa un visor de imágenes para revisarlos uno por uno. Busca problemas según esta lista y corrige antes de la siguiente ronda (al menos una iteración):
- Texto: ¿Es lo suficientemente grande? ¿Se superpone, sale del encuadre o está oculto? ¿Los caracteres chinos son fuentes reales (sin cuadrados)?
- Hechos: ¿Los números, fechas, nombres de lugares, fórmulas en la pantalla coinciden con notes.txt? Las imágenes esquemáticas deben etiquetarse como "esquema".
- Composición: ¿El sujeto principal es lo suficientemente grande (el protagonista en plano general ocupa al menos 1/4 de la altura)? ¿El encuadre está vacío? ¿La paleta de colores es coherente con el tema?
- Movimiento: ¿Las acciones clave realmente ocurren (compara dos fotogramas consecutivos)? ¿Las transiciones son abruptas?
- WebGL: ¿Hay artefactos negros/manchas, parpadeos?
Si no hay problemas, renderiza el video completo:
scripts/render.sh <work>/<nombre> # -> <work>/<nombre>.mp4
N=8 scripts/render.sh <work>/<nombre> # Número de procesos de captura en paralelo (por defecto min(6, núcleos/2))
GPU_ANGLE=vulkan scripts/render.sh ... # Para WebGL con GPU (más rápido, pero puede producir manchas negras; primero verifica con fotogramas de prueba)
El codificador se selecciona automáticamente: si está disponible, usa h264_nvenc; de lo contrario, libx264.
La captura consume principalmente CPU; el cuello de botella suele ser "el modelo escribe la página, revisa las capturas y corrige el código", no el renderizado en sí.
5. Opcional: Locución, subtítulos, música, imagen de vista previa
# Locución + subtítulos (usa edge-tts gratuito; sintetiza toda la locución de una vez para que la voz sea consistente)
python3 scripts/tts.py script.txt -o out/narration --voice zh-CN-YunyangNeural --rate -5%
# Música: Sinteíza tu propia música (sin problemas de derechos) o usa bibliotecas libres de derechos (ver references/narration.md)
python3 scripts/chiptune.py out/bgm.wav 30 # Música chip 8-bit
python3 scripts/beat.py out/beat.wav --bpm 120 --beats 20 # Ritmo sincopado, beats alineados con fotogramas
# Composición: La música se atenúa automáticamente para no cubrir la voz; el volumen se normaliza a -16 LUFS; --burn quema los subtítulos en el video
scripts/mux.sh out/<nombre>.mp4 out/<nombre>.final.mp4 --voice out/narration.mp3 --music out/bgm.wav --srt out/narration.srt --burn
# GIF de vista previa / fotograma de portada
scripts/gif.sh out/<nombre>.mp4 2.5 4 # Desde 2.5 segundos durante 4 segundos
scripts/gif.sh --poster out/<nombre>.mp4 6.0 # Captura un fotograma jpg
Si vas a quemar subtítulos, deja vacío el quinto inferior de la página; no dibujes tu propia barra de subtítulos (o usa SUB_MARGIN=60 para elevar los subtítulos);
el volumen objetivo es -16 LUFS, y puede ser ligeramente menor cuando la voz tiene picos altos (límite de pico verdadero -1.5 dBTP).
Para opciones de voz, integración de TTS propio, y sincronización de beats, consulta references/narration.md.
6. Crear múltiples videos a la vez (comparación de estilos, serie de videos)
Cada video tiene su propio directorio y prompt, independientes entre sí. Pueden asignarse a varios subagentes para que escriban las páginas y se autoverifiquen en paralelo, mientras que el agente principal solo se encarga del renderizado final, la composición y la revisión. En las instrucciones para cada subagente, especifica: el contrato de página, la convención de directorios, la lista de autoverificación, que los hechos deben escribirse en notes.txt, y que al finalizar debe informar la duración y la autoevaluación.
Antes de empezar, aclara
- Los números factuales deben ser reales y verificables; al tratar temas de noticias o productos nuevos, solo dibuja información pública, y marca en la esquina "esquema".
- No reutilices los números de los temas de ejemplo como datos genéricos; verifícalos de nuevo al cambiar de tema.
- La música generada por modelos (por ejemplo, los pesos de MusicGen) suele tener licencias no comerciales; para publicaciones comerciales, usa música sintetizada por ti mismo o con licencia explícita.