Vous pouvez construire un studio d'animation 2.5D avec Opus 5.5 en une seule session Claude Code : un fichier HTML unique qui empile des calques plats à différentes profondeurs, déplace une caméra animée par images clés à travers eux avec des courbes d'easing, et un script Playwright de 25 lignes qui capture chaque image et l'envoie à ffmpeg. Notre build a rendu un MP4 720p de 6 secondes (180 images) en environ 20 secondes sur un ordinateur portable.
Ce guide présente les prompts, le code écrit par l'agent, les bugs rencontrés, et comment vérifier les appels à l'API Opus 5.5 derrière une fonctionnalité « décrire un plan » avec Apidog CLI.
Qu'est-ce qu'un studio d'animation 2.5D ?
Un studio d'animation 2.5D est un outil d'animation qui place des calques 2D plats (ciel, collines, ville, carte de titre, feuillage au premier plan) à différentes profondeurs dans un espace 3D, puis déplace une caméra virtuelle à travers eux. Les calques proches de la caméra glissent plus vite que ceux au loin, ce qui produit du parallaxe et une sensation de profondeur sans aucun modèle 3D.
Trois éléments transforment cela en véritable studio plutôt qu'en animation ponctuelle :
- Un graphe de scène : des calques avec une profondeur
z, une taille, une position et un contenu HTML. - Une timeline : des images clés pour la caméra (dolly, travelling latéral, orbite) et pour chaque calque (opacité, échelle, position), chacune avec une courbe d'easing.
- Un moteur de rendu déterministe : une fonction
renderAt(t)qui dessine l'image exacte pour n'importe quel instantt, afin que l'export ne dépende jamais de la vitesse de lecture de la machine.
C'est ce troisième point que la plupart des tutoriels négligent, et c'est lui qui détermine si votre MP4 saccade ou non.
Configurer Claude Code avec Opus 5.5
Opus 5.5 est le modèle idéal pour ce type de travail. La présentation des modèles d'Anthropic le décrit comme « pour le codage agentique et le travail sur les connaissances de longue durée », avec une fenêtre de contexte d'un million de tokens, une sortie maximale de 128K, et des tarifs de 4 $ / 20 $ par million de tokens d'entrée / sortie.
Épinglez le modèle pour qu'un changement d'alias ne le remplace pas en cours de projet :
claude --model claude-opus-5-5 --effort high
Opus 5.5 utilise par défaut l'effort medium, selon la documentation sur l'effort. Passez à high pour la première construction, lorsque l'agent doit getionner correctement les calculs de projection. Redescendez à medium pour les petits ajustements d'images clés et de couleurs. Si vous voulez d'abord découvrir le modèle, lisez qu'est-ce que Claude Opus 5.5 et comment le prompt caching modifie son coût.
Le prompt qui construit le studio
Un prompt précis vaut mieux que cinq vagues. Voici notre cahier des charges, rédigé en un seul 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.
Les deux dernières lignes sont les plus importantes : elles font de l'export une partie de la conception, pas un ajout après coup.
Le code écrit par l'agent
Le studio fait environ 150 lignes. Trois morceaux comptent.
Images clés et easing
Chaque piste est une liste triée d'images clés. sample() trouve les deux clés encadrant t, applique l'easing de la clé sortante et interpole chaque champ numérique :
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];
}
L'astuce de la profondeur
La caméra ne bouge jamais. C'est le monde qui se déplace en sens inverse. Chaque calque reçoit alors une translation en z plus une échelle de compensation :
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})`;
Avec la propriété CSS perspective réglée à 1200px, un calque à z = -900 est rendu à 1200 / 2100, soit 57 % de sa taille. En multipliant son échelle et ses décalages x/y par 1 + 900/1200 = 1,75, on annule cet effet. Chaque calque apparaît à la taille et à la position définies par l'auteur quand la caméra est au repos, et se déplace toujours à sa propre vitesse quand la caméra bouge. C'est toute l'illusion.

Le bug qu'il faut connaître
La première version mettait à l'échelle chaque calque mais pas son décalage, si bien que les collines montaient jusqu'à couvrir les deux tiers du ciel. La correction : multiplier aussi x et y par comp. Nous l'avons repéré grâce à une seule image rendue, pas en lisant le code : demandez donc à votre agent de rendre des captures aux moments initial, intermédiaire et final avant de faire confiance à un mouvement de caméra.
Exporter la timeline en MP4
La lecture en temps réel utilise requestAnimationFrame, qui perd des images quand la machine est occupée. L'export ne le peut pas. L'exportateur pilote donc le temps à partir de l'index d'image et attend que chaque image soit peinte avant de prendre une capture d'écran 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 résout après deux images d'animation, de sorte que chaque capture voit les nouvelles transformations. image2pipe (voir la documentation des formats ffmpeg) lit les PNG depuis stdin, et yuv420p garantit que le fichier reste lisible dans les navigateurs.
Notre exécution : 180 images, 1280x720, 30 fps, 6,0 secondes, un MP4 de 420 Ko, en 20 secondes de temps réel. Exécutez npx playwright install chromium une fois si Playwright n'a pas encore de navigateur.

Les tours de la ville se décalent moins que la colline sombre au premier plan, qui finit par sortir complètement du cadre. C'est cela, le parallaxe.
Ajouter une fonctionnalité « décrire un plan » avec l'API Opus 5.5
Ensuite, permettons à un rédacteur de saisir une description de plan et de recevoir des images clés en retour. Le studio appelle directement l'API 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." }]
}'
Deux détails de la documentation sur l'effort comptent ici. output_config.effort est l'endroit où se place le niveau d'effort dans une requête à l'API Messages. Et Opus 5.5 utilise toujours le raisonnement adaptatif (une requête avec thinking: {"type": "disabled"} renvoie une erreur 400), donc les tokens de raisonnement comptent dans max_tokens. Réglez-le trop bas et le JSON est coupé en plein milieu d'un tableau avec stop_reason: "max_tokens". Une liste de plans est une tâche courte et bien spécifiée, donc l'effort low est un réglage de départ raisonnable ; faites votre propre comparaison avant de le fixer.
Laisser Claude Code tester l'appel API avec Apidog CLI
Une réponse tronquée ou bavarde casse sample() au moment du rendu, donc cet appel a besoin d'un test de contrat. La même session Claude Code peut l'écrire et l'exécuter avec Apidog CLI.
Installez et connectez-vous une fois :
npm install -g apidog-cli@latest
apidog auth login --with-token <YOUR_TOKEN>
apidog skill install
Puis donnez à l'agent un seul 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.
L'agent lit les schémas de charge utile au lieu de les deviner, valide ses fichiers, puis crée et exécute tout :
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
Passez la clé au moment de l'exécution avec --env-var "api_key=$ANTHROPIC_API_KEY" pour qu'elle ne figure jamais dans le projet. Réexécutez le cas de test quand vous modifiez le prompt système ou le niveau d'effort, car les deux changent ce qui est renvoyé. Le même apidog run avec -r junit s'intègre dans un pipeline CI ; voir le guide CI/CD d'Apidog CLI et Apidog CLI dans Claude Code. Le plan gratuit d'Apidog couvre jusqu'à 4 utilisateurs.
Où faire évoluer le studio ensuite
- Plus de calques, mêmes calculs. Ajoutez de la pluie, un second titre ou un logo ; donnez à chacun un
zet la compensation s'occupe du reste. - Changez de moteur de rendu. Si vous préférez écrire vos scènes en composants React, Claude Code avec Remotion couvre cette voie. L'approche mono-fichier présentée ici ne nécessite aucune étape de build. La présentation de Claude Code explique les sessions et les permissions.
FAQ
Que signifie 2.5D en motion graphics ? Cela désigne des illustrations 2D plates placées à différentes profondeurs et filmées par une caméra en mouvement. Vous obtenez du parallaxe et des indices de profondeur sans modèles 3D, éclairage ni moteur 3D.
Pourquoi utiliser Opus 5.5 plutôt qu'un modèle plus petit pour ce build ? La première construction mélange calculs de projection, moteur d'images clés et pipeline de capture en une seule passe. Anthropic positionne Opus 5.5 pour le codage agentique de longue durée, et notre session a obtenu un studio fonctionnel à partir d'un seul prompt plus une série de corrections. Pour les petites modifications ensuite, un niveau d'effort plus bas suffit.
Pourquoi ne pas simplement enregistrer l'écran au lieu de capturer les images ? L'enregistrement d'écran suit le temps réel, donc toute image lente devient une image perdue ou dupliquée. Se positionner à i / fps et capturer chaque image rend le résultat identique sur toutes les machines.
Puis-je utiliser la fonctionnalité « décrire un plan » sans clé API ? Non. Cette fonctionnalité appelle l'API Messages, qui requiert votre propre clé API Anthropic. Le reste du studio et l'export MP4 fonctionnent localement sans clé.
Quel niveau d'effort l'appel de liste de plans devrait-il utiliser ? Commencez avec low, car la tâche est courte et le schéma de sortie est fixe. Augmentez-le seulement si votre test Apidog révèle des images clés mal formées ou hors sujet.
