Eine 2.5D-Motion-Studio lässt sich mit Opus 5.5 in einer einzigen Claude-Code-Sitzung bauen: eine einzelne HTML-Datei, die flache Ebenen in verschiedenen Tiefen stapelt, eine Keyframe-Kamera mit Easing durch sie hindurchbewegt – und ein 25-Zeilen-Playwright-Skript, das jeden Frame aufnimmt und an ffmpeg weiterreicht. Unser Build hat einen 6-sekündigen 720p-MP4 (180 Frames) auf einem Laptop in etwa 20 Sekunden gerendert.
Dieser Leitfaden zeigt die Prompts, den Code, den der Agent geschrieben hat, die Bugs, auf die er gestoßen ist, und wie man die Opus-5.5-API-Aufrufe hinter einer Funktion „Szene beschreiben“ mit der Apidog CLI prüft.
Was ist ein 2.5D-Motion-Studio?
Ein 2.5D-Motion-Studio ist ein Animationswerkzeug, das flache 2D-Ebenen (Himmel, Hügel, eine Stadt, ein Titel-Card, Vordergrund-Pflanzen) in verschiedenen Tiefen eines 3D-Raums platziert und dann eine virtuelle Kamera durch sie hindurchbewegt. Ebenen, die näher an der Kamera liegen, gleiten schneller als entfernte – das erzeugt Parallaxe und ein Tiefengefühl ganz ohne 3D-Modelle.
Drei Bestandteile machen daraus ein Studio statt einer einmaligen Animation:
- Ein Szenengraph: Ebenen mit
z-Tiefe, Größe, Position und HTML-Inhalt. - Eine Timeline: Keyframes für die Kamera (Dolly, Truck, Orbit) und für jede Ebene (Opacity, Skalierung, Position), jeweils mit einer Easing-Kurve.
- Ein deterministischer Renderer: eine Funktion
renderAt(t), die den exakten Frame für jede Zeittzeichnet, damit der Export nie davon abhängt, wie schnell die Maschine die Wiedergabe schafft.
Der dritte Punkt ist der, den die meisten Tutorials auslassen – und er entscheidet, ob Ihr MP4 ruckelt.
Claude Code mit Opus 5.5 einrichten
Opus 5.5 ist das Modell der Wahl für diese Art von Aufgabe. Anthropics Modelle-Übersicht beschreibt es als Modell „für langlebige agentische Coding- und Wissensarbeiten“, mit einem 1M-Token-Kontextfenster, 128K maximaler Ausgabe und 4 $/20 $ pro Million Input-/Output-Token.
Pinnt das Modell fest, damit eine Alias-Änderung es mitten im Projekt nicht austauscht:
claude --model claude-opus-5-5 --effort high
Opus 5.5 nutzt standardmäßig medium effort, wie die Effort-Dokumentation erklärt. Setzen Sie es für den ersten Build auf high, wenn der Agent die Projektionsmathematik richtig hinbekommen muss. Gehen Sie für kleine Anpassungen an Keyframes und Farben zurück auf medium. Wenn Sie zuerst Hintergrundinformationen zum Modell möchten, lesen Sie, was Claude Opus 5.5 ist und wie Prompt Caching seine Kosten verändert.
Der Prompt, der das Studio baut
Ein spezifischer Prompt schlägt fünf vage. Hier ist unsere Build-Spezifikation als einzelner 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.
Die letzten zwei Zeilen sind die wichtigsten: Sie machen den Export zum Teil des Designs, nicht zu einem Zusatz.
Der Code, den der Agent geschrieben hat
Das Studio umfasst rund 150 Zeilen. Drei Teile sind entscheidend.
Keyframes und Easing
Jede Spur ist eine sortierte Liste von Keyframes. sample() findet die beiden Keys um t, wendet das Easing des auslaufenden Keys an und interpoliert jedes numerische Feld:
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];
}
Der Tiefe-Trick
Die Kamera bewegt sich nie. Die Welt bewegt sich in die Gegenrichtung. Jede Ebene bekommt dadurch ein Translate in z plus eine kompensierende Skalierung:
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})`;
Bei einer auf 1200 px gesetzten CSS-perspective wird eine Ebene bei z = -900 mit 1200 / 2100, also 57 % ihrer Größe gerendert. Multipliziert man ihre Skalierung und ihren x/y-Versatz mit 1 + 900/1200 = 1,75, hebt sich das auf. Jede Ebene erscheint in der Größe und Position, die Sie festgelegt haben, solange die Kamera ruht – und bewegt sich trotzdem mit ihrer eigenen Geschwindigkeit, wenn die Kamera sich bewegt. Das ist die gesamte Illusion.

Der Bug, den man kennen sollte
Die erste Version skalierte jede Ebene, aber nicht ihren Versatz – dadurch stiegen die Hügel an und verdeckten zwei Drittel des Himmels. Die Lösung: Auch x und y mit comp multiplizieren. Wir haben das anhand eines einzigen gerenderten Frames entdeckt, nicht beim Lesen des Codes. Bitten Sie Ihren Agenten also, Standbilder am Anfang, in der Mitte und am Ende zu rendern, bevor Sie einer Kamerabewegung vertrauen.
Die Timeline als MP4 exportieren
Die Echtzeitwiedergabe nutzt requestAnimationFrame, das Frames fallen lässt, wenn die Maschine ausgelastet ist. Der Export darf das nicht. Deshalb steuert der Exporter die Zeit über den Frame-Index und wartet, bis jeder Frame gezeichnet ist, bevor er einen Playwright-Screenshot aufnimmt:
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) resolves after two animation frames, so each screenshot sees the new transforms. image2pipe (see the ffmpeg formats docs) reads PNGs from stdin, and yuv420p keeps the file playable in browsers.
Unser Lauf: 180 Frames, 1280x720, 30 fps, 6,0 Sekunden, ein 420-KB-MP4, in 20 Sekunden Echtzeit. Führen Sie einmalig npx playwright install chromium aus, falls Playwright noch keinen Browser hat.

Die Stadttürme verschieben sich weniger als der dunkle Hügel im Vordergrund, der den Frame vollständig verlässt. Das ist Parallaxe.
Eine Funktion „Szene beschreiben“ mit der Opus-5.5-API hinzufügen
Als Nächstes soll ein Autor eine Beschreibung einer Szene eingeben und Keyframes zurückbekommen. Das Studio ruft die Messages-API direkt auf:
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." }]
}'
Zwei Details aus der Effort-Dokumentation sind hier wichtig. output_config.effort ist die Stelle, an der der Effort-Level in einer Messages-API-Anfrage gesetzt wird. Und Opus 5.5 verwendet immer adaptives Thinking (eine Anfrage mit thinking: {"type": "disabled"} liefert einen 400), daher zählen Thinking-Token auf max_tokens. Setzt man den Wert zu niedrig, wird das JSON mitten im Array abgeschnitten, mit stop_reason: "max_tokens". Eine Shot-Liste ist eine kleine, klar spezifizierte Aufgabe, daher ist low ein sinnvoller Startwert; machen Sie vor einer Festlegung Ihren eigenen Vergleich.
Den API-Aufruf mit der Apidog CLI durch Claude Code testen lassen
Eine abgeschnittene oder geschwätzige Antwort bricht sample() zur Renderzeit – dieser Aufruf braucht also einen Contract-Test. Dieselbe Claude-Code-Sitzung kann ihn mit der Apidog CLI schreiben und ausführen.
Einmalig installieren und anmelden:
npm install -g apidog-cli@latest
apidog auth login --with-token <YOUR_TOKEN>
apidog skill install
Dann geben Sie dem Agenten einen 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.
Der Agent liest die Payload-Schemata, statt sie zu erraten, validiert seine Dateien und erstellt dann alles und führt es aus:
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
Übergibt den Schlüssel zur Laufzeit mit --env-var "api_key=$ANTHROPIC_API_KEY", damit er nie im Projekt landet. Führt den Testfall erneut aus, wenn Sie den System-Prompt oder den Effort-Level ändern, da beides die Antwort verändert. Derselbe apidog run mit -r junit lässt sich in CI einbinden; siehe die Apidog-CLI-CI/CD-Anleitung und Apidog CLI in Claude Code. Apidogs Free-Plan deckt bis zu 4 Nutzer ab.
Wie es mit dem Studio weitergehen kann
- Mehr Ebenen, dieselbe Mathematik. Fügen Sie Regen, einen zweiten Titel oder ein Logo hinzu; geben Sie jedem ein
z, und die Kompensation erledigt den Rest. - Renderer austauschen. Wenn Sie Szenen lieber als React-Komponenten schreiben möchten, behandelt Claude Code mit Remotion diesen Weg. Der hier verfolgte Single-File-Ansatz kommt ohne Build-Schritt aus. Die Claude-Code-Übersicht erklärt Sitzungen und Berechtigungen.
FAQ
Was bedeutet 2.5D im Motion Design? Es bedeutet, flache 2D-Grafiken in verschiedenen Tiefen zu platzieren und sie mit einer bewegten Kamera zu filmen. Man erhält Parallaxe und Tiefenhinweise ganz ohne 3D-Modelle, Beleuchtung oder eine 3D-Engine.
Warum Opus 5.5 statt eines kleineren Modells für diesen Build? Der erste Build vermischt Projektionsmathematik, eine Keyframe-Engine und eine Capture-Pipeline in einem Durchgang. Anthropic positioniert Opus 5.5 für langlebige agentische Coding-Aufgaben, und unsere Sitzung lieferte ein funktionierendes Studio aus einem Prompt plus einer Runde Fixes. Für kleine nachträgliche Änderungen genügt ein niedrigerer Effort-Level.
Warum nicht einfach den Bildschirm aufzeichnen, statt Frames zu erfassen? Eine Bildschirmaufzeichnung folgt der Echtzeit, sodass jeder langsame Frame zu einem ausgelassenen oder doppelten Frame wird. Wenn man zu i / fps seeked und jeden Frame erfasst, ist das Ergebnis auf jeder Maschine identisch.
Kann ich die Funktion „Szene beschreiben“ ohne API-Key nutzen? Nein. Die Funktion ruft die Messages-API auf, die Ihren eigenen Anthropic-API-Key benötigt. Der Rest des Studios und der MP4-Export laufen lokal ohne Key.
Welcher Effort-Level sollte für den Shot-List-Aufruf verwendet werden? Starten Sie mit low, da die Aufgabe kurz ist und das Ausgabe-Schema feststeht. Erhöhen Sie ihn nur, wenn Ihr Apidog-Test fehlerhafte oder nicht dem Brief entsprechende Keyframes zeigt.
