Motion por código con agente|INEMA.CLUB-PRO

Clase 2 · 15 min

HyperFrames desde cero: HTML con data-* se vuelve MP4

HyperFrames es un motor abierto de HeyGen que renderiza HTML en video. Tres atributos dicen el tamaño y la duración, una timeline GSAP en pausa dice el movimiento, y el check lo revisa todo antes del render. En esta clase creas el proyecto, escribes la primera composición y sales con un MP4 verificado.

Empezar la clase
Laptop abierta sobre una mesa oscura mostrando un fotograma de video oscuro, con un monitor de referencia al lado.

En esta clase vas a

  1. 1Qué crea el init y por qué la versión queda fija en el package.json
  2. 2La raíz con data-composition-id, data-width, data-height y data-duration
  3. 3La timeline GSAP en pausa registrada en window.__timelines
  4. 4check, render y el verificador del kit

Objetivo: crear un proyecto HyperFrames, escribir la composición con data-* y renderizar un MP4 que pase el verificador.

01El camino de un proyecto

Haz clic en cada etapa.

Haz clic en cada bloque del diagrama para ver qué hace.

Cuando la raíz tiene data-duration, es ella la que manda: una timeline más corta sostiene el último fotograma.

02Crear el proyecto

El init sin preguntas (--non-interactive) y la telemetría desactivada antes de todo.

Terminal · crear el proyecto y ver lo que vino
export HYPERFRAMES_NO_TELEMETRY=1 NO_COLOR=1
E=${TMPDIR:-/tmp}/ensaio-motion/a2; rm -rf "$E"; mkdir -p "$E"; cd "$E"
npx -y hyperframes@0.8.176 init minha-abertura --non-interactive > init.log 2>&1; echo "saída: $?"
ls minha-abertura
grep '"render"' minha-abertura/package.json
npx -y hyperframes@0.8.176 telemetry status | head -2
Ejemplo del repositorio
saída: 0
AGENTS.md
CLAUDE.md
hyperframes.json
index.html
meta.json
package.json
    "render": "npx --yes hyperframes@0.8.176 render",

  Status:     disabled

El script render del package.json ya llama a la versión exacta. La telemetría aparece desactivada porque el bloque exportó HYPERFRAMES_NO_TELEMETRY=1.

03La primera composición

Título, filete y subtítulo entrando en orden. Cópialo sobre el index.html del init.

Archivo · kit/exemplos/a2-ola/index.html
<!doctype html>
<html lang="pt-BR">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=1920, height=1080" />
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      html, body { width: 1920px; height: 1080px; overflow: hidden; background: #0c0c10; }
      #root { width: 100%; height: 100%; position: relative; font-family: ui-sans-serif, system-ui, sans-serif; }
      #cena { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; padding-left: 200px; }
      #titulo { color: #f4f4f5; font-size: 120px; font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; }
      #linha { width: 640px; height: 6px; margin: 36px 0; background: #e9b949; transform-origin: left center; }
      #sub { color: #a1a1aa; font-size: 48px; line-height: 1.2; }
    </style>
  </head>
  <body>
    <div id="root" data-composition-id="main" data-start="0" data-duration="5" data-width="1920" data-height="1080">
      <section id="cena">
        <h1 id="titulo">El video es código</h1>
        <div id="linha"></div>
        <p id="sub">Una página HTML, un reloj, un MP4.</p>
      </section>
    </div>
    <script>
      const tl = gsap.timeline({ paused: true });
      tl.fromTo("#titulo", { y: 60, opacity: 0 }, { y: 0, opacity: 1, duration: 0.8, ease: "power3.out" }, 0.3);
      tl.fromTo("#linha", { scaleX: 0 }, { scaleX: 1, duration: 0.7, ease: "power2.inOut" }, 0.9);
      tl.fromTo("#sub", { y: 30, opacity: 0 }, { y: 0, opacity: 1, duration: 0.6, ease: "power2.out" }, 1.4);
      window.__timelines["main"] = tl;
    </script>
  </body>
</html>
Terminal · check, render y verificar
K=~/projetos/formacao-cinema-ia-motion-v72/kit
export HYPERFRAMES_NO_TELEMETRY=1 NO_COLOR=1
cd ${TMPDIR:-/tmp}/ensaio-motion/a2/minha-abertura
cp "$K/exemplos/a2-ola/index.html" index.html
npx -y hyperframes@0.8.176 check 2>&1 | grep -E "◇|✗|⚠"
npx -y hyperframes@0.8.176 render --quality draft --workers 2 --quiet --output renders/abertura.mp4 > render.log 2>&1
echo "render: $?"
python3 "$K/conferir.py" renders/abertura.mp4 5 1920x1080; echo "saída: $?"
Ejemplo del repositorio
  ◇ 0 errors, 0 warnings
  ◇ 0 errors, 0 warnings
  ◇ 0 issues across 9 sample(s)
  ◇ 0 errors, 0 warnings
  ◇ 7/7 text checks pass WCAG AA
  ◇ disabled
◇  Check passed
render: 0
OK: 5,0 s · 1920×1080 · 30 fps · sem áudio
saída: 0

Las cinco primeras líneas ◇ son las partes del check (lint, ejecución, layout, movimiento, contraste); la sexta, disabled, es la captura de fotogramas, que viene desactivada (--snapshots la activa). El verificador lee el MP4 con ffprobe y lo compara con lo que pediste: 5 s, 1920×1080.

04Para que el agente trabaje con las reglas correctas

HyperFrames publica skills para agentes (investigación, §5). El init ya deja un AGENTS.md y un CLAUDE.md en la carpeta del proyecto.

Opcional · instalar las skills oficiales en tu agente
npx skills add heygen-com/hyperframes

05Práctica

Del init al MP4 verificado, y un cambio tuyo.

E1 · Crear el proyecto

5 min

Ejecuta el bloque "criar o projeto e ver o que veio".

Listo cuando: La salida muestra saída: 0, la lista con index.html y package.json, la línea hyperframes@0.8.176 render y Status: disabled.

E2 · Primer MP4

10 min

Ejecuta el bloque "check, render e conferir".

Listo cuando: ◇ Check passed, render: 0 y OK: 5,0 s · 1920×1080 · 30 fps · sem áudio con saída: 0.

E3 · Ocho segundos

10 min

En el index.html de tu proyecto, cambia data-duration de la raíz a 8, cambia el título por uno tuyo, ejecuta check y render de nuevo.

Listo cuando: python3 ~/projetos/formacao-cinema-ia-motion-v72/kit/conferir.py renders/abertura.mp4 8 1920x1080; echo "saída: $?" → OK: 8,0 s · 1920×1080 · 30 fps · sem áudio y saída: 0.

06Prueba de la clase

La explicación aparece después de tu respuesta.

Pregunta 1 de 4

¿Qué define la duración del MP4 en HyperFrames?

07En tres frases

Raízdata-composition-id, tamaño y duración; clips con data-start.
Una timelineGSAP en pausa en window.__timelines con la misma clave de la raíz.
Compuertacheck antes del render, verificador después; versión fija y telemetría desactivada.

Para ir más allá

Clase anteriorPróxima clase