Communitygithub.com

jblxo/programmatic-video-skill

Crea y renderiza videos animados MP4 deterministas a 60fps y 1080p, incluyendo gráficos en movimiento, resúmenes, demostraciones de productos y videos "Wrapped" basados en datos, usando Canvas HTML5, SVG, Playwright, síntesis de audio procedural y FFmpeg.

¿Qué es programmatic-video-skill?

Este skill permite a agentes de IA (como Claude Code, Cursor, Codex) diseñar, revisar visualmente y renderizar videos MP4 animados de alta calidad (60fps, 1080p) sin necesidad de herramientas complejas como Remotion. El flujo de trabajo se basa en tres principios clave: (1) la escena es una función pura del índice de fotograma mediante `window.__setFrame`, (2) se realiza una revisión visual multimodal con una hoja de contactos antes del renderizado completo, y (3) el audio se sintetiza proceduralmente y se mezcla con señales de efectos WAV. El agente comienza con un storyboard y un presupuesto de escenas, escribe un archivo HTML autónomo con Canvas o SVG, captura fotogramas clave para generar una hoja de contactos, la revisa con herramientas multimodales, sintetiza la banda sonora y finalmente renderiza el video completo usando una tubería de Playwright a FFmpeg. El skill incluye scripts de referencia para renderizado, creación de hojas de contactos y síntesis de audio, así como guías detalladas para patrones visuales, bucles de control de calidad y composición musical.

Compatible con✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI✓OpenCode
npx skills add https://github.com/jblxo/programmatic-video-skill/tree/HEAD/skills/programmatic-video

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Habilidad de Generación de Video Programático

Un flujo de trabajo determinista y sin código repetitivo para que agentes de IA diseñen, revisen visualmente, evalúen y rendericen videos animados MP4 a 60fps y 1080p directamente desde un único archivo HTML5 Canvas/SVG, un script de audio procedural en Python y una tubería headless Playwright → FFmpeg.

Rutas. ${CLAUDE_SKILL_DIR} es el directorio que contiene este SKILL.md. En Claude Code se expande automáticamente; en Cursor, Codex, OpenCode u otros agentes, reemplaza ${CLAUDE_SKILL_DIR} con la ruta resuelta a skills/programmatic-video/.


¿Por qué Avance de Fotogramas Determinista?

Nunca uses grabación de pantalla en tiempo real (MediaRecorder, captura por reloj de pared de requestAnimationFrame o transiciones CSS en tiempo real) para producir videos con un agente de IA:

  1. La captura por reloj de pared pierde fotogramas cuando la carga de la CPU aumenta, causando desviación y tartamudeo de audio/video.
  2. Las animaciones CSS se ejecutan en tiempo real, imposibilitando buscar en t = 14.20s para una revisión visual instantánea.
  3. El renderizado ciego desperdicia minutos: renderizar 5,000 fotogramas antes de verificar si un título se desborda de su tarjeta garantiza trabajo perdido.

En su lugar, cada video construido con esta habilidad sigue tres reglas:

  • Regla 1 — Función Pura del Índice de Fotograma: Toda la escena se maneja mediante window.__setFrame(frameIndex, timeSeconds, fps) donde t = frameIndex / fps. Cada posición, opacidad, contador y partícula es una función matemática determinista de t (usando un PRNG con semilla como mulberry32, nunca Math.random()).
  • Regla 2 — Revisión Multimodal con Hoja de Contactos Antes del Renderizado Completo: Antes de codificar el MP4 completo a 60fps, captura 8–12 marcas de tiempo clave (render.mjs --timestamps ...), combínalas en una sola contact-sheet.png (contact-sheet.py) e inspecciona esa imagen usando tu herramienta multimodal de Lectura/Visión para corregir texto recortado, superposiciones o bajo contraste.
  • Regla 3 — Audio Preciso por Muestra + Tubería FFmpeg sin Hinchazón de Disco: Genera una banda sonora WAV estéreo multisegmento + señales de efectos SFX con marcas de tiempo (synth-audio.py), luego transmite búferes PNG desde Playwright directamente a ffmpeg -f image2pipe (render.mjs).

Flujo de Trabajo Integral del Agente (6 Pasos)

Paso 1: Storyboard y Presupuesto de Escenas

Diseña una tabla de línea de tiempo concreta antes de escribir código. Agrupa el video en escenas de 4 a 8 segundos con marcas de transición explícitas (T_cut) que tanto scene.html como synth-audio.py compartan:

EscenaTiempo (t)Fotogramas (60fps)Enfoque VisualAudio / Señal SFX
01 — Gancho / Alerta0.0s – 7.0s0 – 420Arranque de terminal CRT, logs de máquina de escribir, clic en botón CTA a 2.7sPulso grave + señal de clic/desbloqueo de UI a 2.7s, ascenso hasta 3.4s
02 — Métricas Estrella7.0s – 15.0s420 – 900Cuadrícula synthwave en perspectiva 3D + 3 tarjetas de contador con física de resorteBajo synthwave completo 124 BPM + arpegiador estéreo cae a 7.0s
03 — Telemetría Profunda15.0s – 23.0s900 – 1380Barras de progreso en pantalla dividida + medidor semicircular animadoBarrido de filtro + impulso de platillo, impacto grave a 15.0s
04 — Llamada de Lista y Final23.0s – 30.0s1380 – 1800Cuadrícula Bento de tarjetas de colaboradores + cartel de "¡TRABAJO TERMINADO!" y confetiAcorde final + señal de voz/SFX a 25.2s, desvanecimiento maestro 28.5–30.0s

Paso 2: Crear scene.html con window.__setFrame(f, t, fps)

Escribe un archivo HTML autónomo de 1920x1080 usando <canvas> de HTML5 (y/o <svg> en línea + superposiciones DOM) que exponga:

window.__setFrame = function(frameIndex, timeSeconds, fps = 60) {
  if (window.__rafId) {
    cancelAnimationFrame(window.__rafId);
    window.__rafId = null;
  }
  const t = typeof timeSeconds === 'number' ? timeSeconds : frameIndex / fps;
  renderSceneAtTime(frameIndex, t);
};
  • Incluye siempre un PRNG con semilla (mulberry32(seed)) para estrellas, partículas, confeti o ruido, de modo que el fotograma f sea bit-idéntico entre ejecuciones.
  • Espera a document.fonts.ready (manejado automáticamente por render.mjs).
  • Consulta references/visual-patterns.md para recetas copiables (cuadrícula 3D en perspectiva, contadores con resorte, terminal CRT, medidores, tarjetas bento, física de confeti).

Paso 3: Ejecutar Capturas Rápidas de Marcas de Tiempo y Generar contact-sheet.png

Nunca ejecutes primero un renderizado completo a 60fps. Muestrea 1–2 marcas de tiempo por escena (además de puntos medios de transición) y genera una sola hoja de contactos:

# 1. Capturar 9 fotogramas clave en ~3 segundos
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --timestamps 1.8,3.0,5.2,8.5,12.5,16.5,20.5,24.5,28.0 \
  --out-dir ./qa-frames

# 2. Combinarlos en una imagen de cuadrícula etiquetada
python3 "${CLAUDE_SKILL_DIR}/scripts/contact-sheet.py" \
  --dir ./qa-frames \
  --cols 3 \
  --thumb-width 560 \
  --title "HOJA DE CONTACTO DE QA VISUAL" \
  --out ./contact-sheet.png

Paso 4: Bucle de Autorevisión Multimodal (¡Obligatorio!)

Usa tu herramienta de Lectura/Visión de imágenes en ./contact-sheet.png (y en cualquier ./qa-frames/t-*.png individual que parezca densa). Revisa cada mosaico contra la lista de verificación en references/visual-qa-loop.md:

  • ¿Algún texto se desborda o choca con bordes de tarjetas, insignias o barras de progreso?
  • ¿Todos los números, etiquetas y encabezados HUD tienen alto contraste y son legibles a 1080p?
  • ¿Cada transición de escena aterriza limpiamente sin un fotograma vacío/negro no deseado?

Si detectas algún problema en contact-sheet.png, corrige scene.html y vuelve a ejecutar el Paso 3 antes de continuar.

Paso 5: Sintetizar Banda Sonora Procedural y Mezclar Señales SFX WAV

Genera una banda sonora WAV estéreo de 44.1 kHz cuyos ascensos de transición y señales SFX coincidan con las marcas de tiempo exactas en scene.html:

python3 "${CLAUDE_SKILL_DIR}/scripts/synth-audio.py" \
  --duration 30.0 \
  --bpm 124 \
  --style synthwave \
  --transitions 3.4,7.0,15.0,23.0,25.2 \
  --cue "25.2:./sfx/jobs-done.wav:+1.5" \
  --out ./soundtrack.wav

Para composiciones multisegmento personalizadas o la integración de paquetes de sonido temáticos (como jblxo/claude-code-sound-packs), lee references/audio-synthesis.md.

Paso 6: Renderizar el MP4 Final a 60fps H.264 mediante Tubería FFmpeg

Una vez que la revisión visual y la síntesis de audio hayan sido exitosas, ejecuta render.mjs en modo de tubería completa:

node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --duration 30 \
  --fps 60 \
  --audio ./soundtrack.wav \
  --crf 18 \
  --out ./final-video.mp4

Verifica el contenedor de salida con ffprobe:

ffprobe -v error -show_entries format=duration,size:stream=codec_name,width,height,r_frame_rate -of default=noprint_wrappers=1 ./final-video.mp4

Guías de Referencia (Cargadas Bajo Demanda)

TemaArchivo de Referencia
Primitivas visuales Canvas/SVG, funciones de easing, PRNG con semilla, cuadrícula synthwave 3D, medidores, tarjetas bentoreferences/visual-patterns.md
Bucle de QA visual con hoja de contactos multimodal, defectos de diseño comunes, estrategia de selección de marcas de tiemporeferences/visual-qa-loop.md
Síntesis de audio procedural Python/NumPy, progresiones de acordes, ascensos, ducking, mezcla de señales SFX WAVreferences/audio-synthesis.md

Skills relacionados