Cómo crear un estudio de movimiento 2.5D con Opus 5.5

Un prompt, un archivo HTML y un exportador de 25 líneas: crea un estudio de animación 2.5D en el navegador usando Opus 5.5 con Claude Code, renderízalo a MP4 y prueba la llamada a la API de shot-list de Opus 5.5 con Apidog CLI.

Ahmed Waheed

Ahmed Waheed

12 November 2026

Cómo crear un estudio de movimiento 2.5D con Opus 5.5

Apidog para empresas

Despliegue local

SSO & RBAC

Conforme con SOC 2

Explorar Apidog Enterprise

Puedes construir un estudio de movimiento 2.5D con Opus 5.5 en una sola sesión de Claude Code: un único archivo HTML que apila capas planas a distintas profundidades, mueve una cámara con keyframes a través de ellas con suavizado, y un script de Playwright de 25 líneas que captura cada fotograma y lo envía a ffmpeg. Nuestra construcción renderizó un MP4 de 6 segundos a 720p (180 fotogramas) en unos 20 segundos en un portátil.

Esta guía muestra los prompts, el código que escribió el agente, los errores que encontró y cómo verificar las llamadas a la API de Opus 5.5 detrás de una función de “describir un plano” con Apidog CLI.

¿Qué es un estudio de movimiento 2.5D?

Un estudio de movimiento 2.5D es una herramienta de animación que coloca capas 2D planas (cielo, colinas, una ciudad, una tarjeta de título, follaje en primer plano) a distintas profundidades en un espacio 3D, y luego mueve una cámara virtual a través de ellas. Las capas más cercanas a la cámara se desplazan más rápido que las lejanas, lo que produce paralaje y una sensación de profundidad sin necesidad de modelos 3D.

Tres partes hacen que sea un estudio y no una animación puntual:

  1. Un grafo de escena: capas con una profundidad z, tamaño, posición y contenido HTML.
  2. Una línea de tiempo: keyframes para la cámara (dolly, travelling, órbita) y para cada capa (opacidad, escala, posición), cada uno con una curva de suavizado.
  3. Un renderizador determinista: una función renderAt(t) que dibuja el fotograma exacto para cualquier instante t, de modo que la exportación nunca dependa de la velocidad con la que la máquina lo reproduce.

Ese tercer punto es el que la mayoría de los tutoriales omiten, y decide si tu MP4 va a tirones.

Configura Claude Code con Opus 5.5

Opus 5.5 es el modelo con el que empezar para este tipo de trabajo. La descripción de modelos de Anthropic lo presenta como “para trabajo de código agéntico y de conocimiento de larga duración”, con una ventana de contexto de 1 millón de tokens, 128K de salida máxima y 4 / 20 dólares por millón de tokens de entrada / salida.

Fija el modelo para que un cambio de alias no lo sustituya a mitad del proyecto:

claude --model claude-opus-5-5 --effort high

Opus 5.5 usa por defecto el esfuerzo medium, según la documentación de effort. Súbelo a high para la primera construcción, cuando el agente tiene que acertar con las matemáticas de proyección. Vuelve a medium para pequeños ajustes de keyframes y colores. Si quieres conocer primero el modelo, lee qué es Claude Opus 5.5 y cómo la caché de prompts cambia su coste.

El prompt que construye el estudio

Un prompt específico vale más que cinco vagos. Esta es nuestra especificación de construcción, escrita como un único prompt:

Build a 2.5D motion studio as one file, studio.html, with no dependencies.
- Scene: 6 layers (sky, moon, hills, city skyline, a title card "Ship it.",
  foreground foliage), each at its own z depth, using CSS perspective and
  preserve-3d.
- Camera: keyframes for x, y, z (dolly) and yaw (orbit around the card).
- Per-layer tracks: opacity, scale, y. Easings: linear, easeInOutCubic,
  easeInOutSine, easeOutBack.
- A timeline bar with keyframe markers, a playhead, click to scrub,
  space to play or pause.
- renderAt(t) must be pure in t. Expose window.__seek(t) that resolves after
  the frame paints, and a ?capture mode that hides the UI.
Then write export.mjs: Playwright opens ?capture, seeks every frame at 30 fps,
screenshots it and pipes PNGs to ffmpeg as H.264.

Las dos últimas líneas son las más importantes: hacen que la exportación forme parte del diseño, no que sea un añadido.

El código que escribió el agente

El estudio tiene unas 150 líneas. Tres fragmentos son los que importan.

Keyframes y suavizado

Cada pista es una lista ordenada de keyframes. sample() encuentra los dos keyframes entre los que se encuentra t, aplica el suavizado del keyframe saliente e interpola cada campo numérico:

function sample(keys, t) {
  if (t <= keys[0].t) return keys[0];
  for (let i = 0; i < keys.length - 1; i++) {
    const a = keys[i], b = keys[i + 1];
    if (t <= b.t) {
      const p = (easings[a.ease] || easings.linear)((t - a.t) / (b.t - a.t));
      const out = {};
      for (const k in b) if (typeof b[k] === 'number' && k !== 't') out[k] = a[k] + (b[k] - a[k]) * p;
      return out;
    }
  }
  return keys[keys.length - 1];
}

El truco de la profundidad

La cámara nunca se mueve. El mundo se mueve en sentido contrario. Cada capa recibe entonces una traslación en z más una escala de compensación:

const PERSPECTIVE = 1200; // must match #viewport perspective
world.style.transform =
  `translate3d(${-cam.x}px, ${-cam.y}px, ${cam.z}px) rotateY(${-cam.yaw}deg)`;
const comp = 1 - L.z / PERSPECTIVE;
el.style.transform = `translate(-50%,-50%) ` +
  `translate3d(${x * comp}px, ${y * comp}px, ${L.z}px) scale(${comp * s})`;

Con la perspective de CSS fijada en 1200px, una capa en z = -900 se renderiza a 1200 / 2100, es decir, al 57 % de su tamaño. Multiplicar su escala y su desplazamiento x/y por 1 + 900/1200 = 1.75 cancela ese efecto. Cada capa aparece con el tamaño y la posición que definiste cuando la cámara está en reposo, y aun así se mueve a su propia velocidad cuando la cámara se mueve. Esa es toda la ilusión.

El estudio de movimiento 2.5D en el navegador: una tarjeta de título frente a una luna, colinas y un perfil urbano, con una línea de tiempo que muestra los keyframes de la cámara en azul, los keyframes de las capas en amarillo y un cursor rojo en 2.10s

El error que conviene conocer

La primera versión escalaba cada capa pero no su desplazamiento, así que las colinas subieron hasta cubrir dos tercios del cielo. La solución: multiplicar también x e y por comp. Lo detectamos a partir de un solo fotograma renderizado, no leyendo el código, así que pide a tu agente que renderice fotogramas fijos al inicio, en el medio y al final antes de fiarte de cualquier movimiento de cámara.

Exporta la línea de tiempo a MP4

La reproducción en tiempo real usa requestAnimationFrame, que pierde fotogramas cuando la máquina está ocupada. La exportación no puede permitírselo. Por eso el exportador controla el tiempo a partir del índice del fotograma y espera a que cada fotograma se pinte antes de tomar una captura con Playwright:

import { chromium } from 'playwright';
import { spawn } from 'node:child_process';
import { pathToFileURL } from 'node:url';

const out = process.argv[2] || 'out.mp4';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
await page.goto(pathToFileURL('studio.html').href + '?capture');

const { duration, fps } = await page.evaluate(() => window.__scene);
const ffmpeg = spawn('ffmpeg', ['-y', '-f', 'image2pipe', '-framerate', String(fps),
  '-i', '-', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-crf', '18', out],
  { stdio: ['pipe', 'ignore', 'inherit'] });

const frames = Math.round(duration * fps);
for (let i = 0; i < frames; i++) {
  await page.evaluate(t => window.__seek(t), i / fps);
  ffmpeg.stdin.write(await page.screenshot({ type: 'png' }));
}
ffmpeg.stdin.end();
await new Promise(r => ffmpeg.on('close', r));
await browser.close();

window.__seek(t) se resuelve tras dos fotogramas de animación, de modo que cada captura ve las nuevas transformaciones. image2pipe (ver la documentación de formatos de ffmpeg) lee los PNG desde stdin, y yuv420p mantiene el archivo reproducible en los navegadores.

Nuestra ejecución: 180 fotogramas, 1280x720, 30 fps, 6.0 segundos, un MP4 de 420 KB, en 20 segundos de tiempo real. Ejecuta npx playwright install chromium una vez si Playwright aún no tiene un navegador.

Tres fotogramas del MP4 exportado a 0.3s, 2.5s y 5.9s: la cámara se acerca a la tarjeta de título mientras el perfil urbano y la colina en primer plano se desplazan a distintas velocidades, y luego orbita de modo que la tarjeta se inclina

Las torres de la ciudad se desplazan menos que la colina oscura del primer plano, que sale por completo del encuadre. Eso es el paralaje.

Añade una función de “describir un plano” con la API de Opus 5.5

A continuación, permite que un redactor escriba la descripción de un plano y reciba keyframes a cambio. El estudio llama directamente a la API de Messages:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2026-10-21" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 4096,
    "output_config": { "effort": "low" },
    "system": "Return only JSON: {\"camera\": [{\"t\",\"x\",\"y\",\"z\",\"yaw\",\"ease\"}], \"tracks\": {}}. Times in seconds, 0 to 6.",
    "messages": [{ "role": "user", "content": "Slow push-in, slight orbit right, title fades up in the first second." }]
  }'

Dos detalles de la documentación de effort importan aquí. output_config.effort es donde va el nivel de esfuerzo en una petición a la API de Messages. Y Opus 5.5 siempre usa pensamiento adaptativo (una petición con thinking: {"type": "disabled"} devuelve un 400), por lo que los tokens de pensamiento cuentan dentro de max_tokens. Si lo pones demasiado bajo, el JSON se corta a mitad del array con stop_reason: "max_tokens". Una lista de planos es una tarea pequeña y bien especificada, así que el esfuerzo low es una configuración inicial razonable; haz tu propia comparación antes de decidirte.

Permite que Claude Code pruebe la llamada a la API con Apidog CLI

Una respuesta truncada o prolija rompe sample() en el momento del renderizado, así que esta llamada necesita una prueba de contrato. La misma sesión de Claude Code puede escribir y ejecutarla con Apidog CLI.

Instala e inicia sesión una vez:

npm install -g apidog-cli@latest
apidog auth login --with-token <YOUR_TOKEN>
apidog skill install

Luego dale al agente un solo prompt:

In Apidog project <projectId>, create an endpoint for POST /v1/messages and a
test case that sends the "describe a shot" request above with model
claude-opus-5-5. Assert: status 200, body.model is "claude-opus-5-5",
stop_reason is not "max_tokens", and content[0].text parses as JSON with a
non-empty camera array whose t values rise from 0 to 6. Use an environment
with base URL https://api.anthropic.com and the key in a variable. Run it and
summarize failures.

El agente lee los esquemas de los payloads en lugar de adivinarlos, valida sus archivos y luego crea y ejecuta todo:

apidog cli-schema get endpoint-create
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog environment create anthropic --project <projectId> --base-url https://api.anthropic.com
apidog endpoint create --project <projectId> --file endpoint.json
apidog test-case create --project <projectId> --file case.json
apidog run --test-case <caseId> --project <projectId> -e <envId> -r cli,json

Pasa la clave en tiempo de ejecución con --env-var "api_key=$ANTHROPIC_API_KEY" para que nunca quede almacenada en el proyecto. Ejecuta el caso de nuevo cuando cambies el prompt de sistema o el nivel de esfuerzo, ya que ambos cambian lo que devuelve. El mismo apidog run con -r junit se integra en CI; consulta la guía de CI/CD de Apidog CLI y Apidog CLI en Claude Code. El plan gratuito de Apidog cubre hasta 4 usuarios.

Cómo seguir evolucionando el estudio

FAQ

¿Qué significa 2.5D en motion graphics? Significa arte 2D plano colocado a distintas profundidades y filmado por una cámara en movimiento. Obtienes paralaje y señales de profundidad sin modelos 3D, iluminación ni un motor 3D.

¿Por qué usar Opus 5.5 en lugar de un modelo más pequeño para esta construcción? La primera construcción combina matemáticas de proyección, un motor de keyframes y un pipeline de captura en una sola pasada. Anthropic posiciona Opus 5.5 para codificación agéntica de larga duración, y nuestra sesión obtuvo un estudio funcional a partir de un prompt más una ronda de correcciones. Para pequeñas ediciones posteriores, basta un nivel de esfuerzo menor.

¿Por qué no grabar la pantalla en lugar de capturar fotogramas? La grabación de pantalla sigue el tiempo real, así que cualquier fotograma lento se convierte en un fotograma perdido o duplicado. Buscar el instante i / fps y capturar cada fotograma hace que la salida sea idéntica en todas las máquinas.

¿Puedo usar la función de “describir un plano” sin una clave de API? No. La función llama a la API de Messages, que necesita tu propia clave de API de Anthropic. El resto del estudio y la exportación a MP4 se ejecutan localmente sin ninguna clave.

¿Qué nivel de esfuerzo debería usar la llamada de la lista de planos? Empieza con low, ya que la tarea es corta y el esquema de salida está fijado. Súbelo solo si tus pruebas en Apidog muestran keyframes mal formados o fuera de lo pedido.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs