Como Criar um Estúdio de Animação 2.5D com Opus 5.5

Um prompt, um arquivo HTML e um exportador de 25 linhas: construa um estúdio de movimento 2.5D no navegador usando o Opus 5.5 com o Claude Code, renderize o resultado em MP4 e teste a chamada de API da shot list do Opus 5.5 com o Apidog CLI.

Ahmed Waheed

Ahmed Waheed

12 novembro 2026

Como Criar um Estúdio de Animação 2.5D com Opus 5.5

Apidog para empresas

Implantação local

SSO & RBAC

Conforme SOC 2

Explorar Apidog Enterprise

Você pode construir um estúdio de motion 2.5D com o Opus 5.5 em uma única sessão do Claude Code: um único arquivo HTML que empilha camadas planas em diferentes profundidades, move uma câmera com keyframes por elas usando easing, e um script Playwright de 25 linhas que captura cada frame e o envia para o ffmpeg. Nossa build renderizou um MP4 de 720p com 6 segundos (180 frames) em cerca de 20 segundos em um laptop.

Este guia mostra os prompts, o código que o agente escreveu, os bugs que ele encontrou e como verificar as chamadas da API do Opus 5.5 por trás de um recurso de “descrever uma cena” com o Apidog CLI.

O que é um estúdio de motion 2.5D?

Um estúdio de motion 2.5D é uma ferramenta de animação que posiciona camadas 2D planas (céu, colinas, uma cidade, um cartão de título, folhagem em primeiro plano) em diferentes profundidades em um espaço 3D e, em seguida, move uma câmera virtual através delas. As camadas mais próximas da câmera deslizam mais rápido do que as distantes, o que produz parallax e uma sensação de profundidade sem nenhum modelo 3D.

Três partes fazem dele um estúdio, e não uma animação avulsa:

  1. Um grafo de cena: camadas com profundidade z, tamanho, posição e conteúdo HTML.
  2. Uma linha do tempo: keyframes para a câmera (dolly, truck, orbit) e para cada camada (opacidade, escala, posição), cada um com uma curva de easing.
  3. Um renderizador determinístico: uma função renderAt(t) que desenha o frame exato para qualquer tempo t, de modo que a exportação nunca dependa da velocidade com que a máquina o reproduz.

Esse terceiro ponto é o que a maioria dos tutoriais ignora, e é ele que decide se o seu MP4 trava ou não.

Configure o Claude Code no Opus 5.5

O Opus 5.5 é o modelo ideal para começar esse tipo de trabalho. A visão geral de modelos da Anthropic o descreve como “para trabalhos de codificação agêntica e de conhecimento de longa duração”, com uma janela de contexto de 1 milhão de tokens, saída máxima de 128K e US$ 4 / US$ 20 por milhão de tokens de entrada / saída.

Fixe o modelo para que uma mudança de alias não o troque no meio do projeto:

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

O Opus 5.5 usa medium como nível de esforço padrão, de acordo com a documentação de effort. Aumente para high na primeira build, quando o agente precisa acertar a matemática da projeção. Volte para medium para pequenos ajustes em keyframes e cores. Se quiser conhecer o modelo primeiro, leia o que é o Claude Opus 5.5 e como o prompt caching muda seu custo.

O prompt que constrói o estúdio

Um prompt específico vale mais do que cinco vagos. Aqui está a nossa especificação de build, escrita como um ú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.

As duas últimas linhas são as mais importantes: elas tornam a exportação parte do design, não um complemento.

O código que o agente escreveu

O estúdio tem cerca de 150 linhas. Três partes merecem destaque.

Keyframes e easing

Cada track é uma lista ordenada de keyframes. A sample() encontra os dois keys ao redor de t, aplica o easing do key de saída e interpola todos os campos numéricos:

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];
}

O truque da profundidade

A câmera nunca se move. O mundo se move na direção oposta. Cada camada recebe então um translate em z mais uma escala de compensação:

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})`;

Com a perspective do CSS definida como 1200px, uma camada em z = -900 é renderizada a 1200 / 2100, ou 57% do seu tamanho. Multiplicar sua escala e seus offsets x/y por 1 + 900/1200 = 1,75 cancela esse efeito. Cada camada aparece no tamanho e na posição que você definiu quando a câmera está parada, e ainda se move em sua própria velocidade quando a câmera se move. Essa é toda a ilusão.

O estúdio de motion 2.5D no navegador: um cartão de título diante de uma lua, colinas e um skyline de cidade, com uma linha do tempo mostrando keyframes da câmera em azul, keyframes das camadas em amarelo e um playhead vermelho em 2,10s

O bug que vale a pena conhecer

A primeira versão escalava cada camada, mas não seu offset, então as colinas subiram até cobrir dois terços do céu. A correção: multiplicar x e y por comp também. Nós o detectamos a partir de um frame renderizado, não lendo o código, então peça ao seu agente que renderize stills no início, no meio e no fim antes de confiar em qualquer movimento de câmera.

Exporte a linha do tempo para MP4

A reprodução em tempo real usa requestAnimationFrame, que descarta frames quando a máquina está ocupada. A exportação não pode fazer isso. Por isso, o exportador controla o tempo pelo índice do frame e espera cada frame ser pintado antes de capturar uma captura de tela do 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) é resolvido após dois animation frames, de modo que cada captura de tela vê os novos transforms. O image2pipe (veja a documentação de formatos do ffmpeg) lê PNGs do stdin, e o yuv420p mantém o arquivo reproduzível nos navegadores.

Nossa execução: 180 frames, 1280x720, 30 fps, 6,0 segundos, um MP4 de 420 KB, em 20 segundos de tempo real. Execute npx playwright install chromium uma vez se o Playwright ainda não tiver um navegador.

Três frames do MP4 exportado em 0,3s, 2,5s e 5,9s: a câmera se aproxima do cartão de título enquanto o skyline da cidade e a colina em primeiro plano se deslocam em velocidades diferentes, depois faz um orbit para que o cartão se incline

Os prédios da cidade se deslocam menos do que a colina escura em primeiro plano, que sai completamente do quadro. Isso é parallax.

Adicione um recurso de “descrever uma cena” com a API do Opus 5.5

Em seguida, permita que um redator digite a descrição de uma cena e receba keyframes de volta. O estúdio chama a Messages API diretamente:

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." }]
  }'

Dois detalhes da documentação de effort importam aqui. output_config.effort é onde o nível de esforço vai em uma requisição à Messages API. E o Opus 5.5 sempre usa adaptive thinking (uma requisição com thinking: {"type": "disabled"} retorna um 400), então os tokens de thinking contam para o max_tokens. Defina-o baixo demais e o JSON será cortado no meio do array com stop_reason: "max_tokens". Uma lista de keyframes de cena é uma tarefa pequena e bem especificada, então o esforço low é uma escolha inicial sensata; faça sua própria comparação antes de se decidir.

Faça o Claude Code testar a chamada de API com o Apidog CLI

Uma resposta truncada ou prolixa quebra a sample() no momento da renderização, então essa chamada precisa de um teste de contrato. A mesma sessão do Claude Code pode escrevê-lo e executá-lo com o Apidog CLI.

Instale e faça login uma vez:

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

Depois dê um único prompt ao agente:

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.

O agente lê os schemas de payload em vez de adivinhá-los, valida seus arquivos e, então, cria e executa tudo:

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

Passe a chave em tempo de execução com --env-var "api_key=$ANTHROPIC_API_KEY" para que ela nunca fique armazenada no projeto. Execute o caso de teste novamente quando mudar o system prompt ou o nível de esforço, já que ambos alteram o que é retornado. O mesmo apidog run com -r junit se integra ao CI; veja o guia de CI/CD do Apidog CLI e o Apidog CLI no Claude Code. O plano gratuito do Apidog cobre até 4 usuários.

Para onde levar o estúdio a seguir

FAQ

O que significa 2.5D em motion graphics? Significa arte 2D plana posicionada em diferentes profundidades e filmada por uma câmera em movimento. Você obtém parallax e pistas de profundidade sem modelos 3D, iluminação ou um motor 3D.

Por que usar o Opus 5.5 em vez de um modelo menor para essa build? A primeira build mistura matemática de projeção, um motor de keyframes e um pipeline de captura em uma única passagem. A Anthropic posiciona o Opus 5.5 para codificação agêntica de longa duração, e nossa sessão obteve um estúdio funcional a partir de um prompt mais uma rodada de correções. Para pequenas edições depois, um nível de esforço menor é suficiente.

Por que não gravar a tela em vez de capturar frames? A gravação de tela segue o tempo real, então qualquer frame lento se torna um frame descartado ou duplicado. Buscar i / fps e capturar cada frame torna a saída idêntica em qualquer máquina.

Posso usar o recurso de “descrever uma cena” sem uma chave de API? Não. O recurso chama a Messages API, que precisa da sua própria chave de API da Anthropic. O restante do estúdio e a exportação para MP4 rodam localmente sem chave.

Qual nível de esforço a chamada da lista de cenas deve usar? Comece com low, já que a tarefa é curta e o schema de saída é fixo. Aumente apenas se o seu teste no Apidog mostrar keyframes malformados ou fora do esperado.

Pratique o design de API no Apidog

Descubra uma forma mais fácil de construir e usar APIs