Opus 5.5 ile tek bir Claude Code oturumunda 2.5D bir motion studio kurabilirsiniz: düz katmanları farklı derinliklerde üst üste yığan tek bir HTML dosyası, anahtar kareli bir kamerayı yumuşatma (easing) ile bu katmanların içinden geçiren bir sahne ve her kareyi yakalayıp ffmpeg'e aktaran 25 satırlık bir Playwright betiği. Bizim kurulumumuz, bir dizüstü bilgisayarda 6 saniyelik 720p MP4 (180 kare) yaklaşık 20 saniyede oluşturdu.
Bu rehber; kullanılan komutları, ajanın yazdığı kodu, karşılaştığı hataları ve “bir çekim tanımla” özelliğinin arkasındaki Opus 5.5 API çağrılarını Apidog CLI ile nasıl doğrulayacağınızı gösteriyor.
2.5D motion studio nedir?
Bir 2.5D motion studio; düz 2D katmanları (gökyüzü, tepeler, bir şehir, bir başlık kartı, ön plandaki yapraklar) 3D bir alanda farklı derinliklere yerleştirip sanal bir kamerayı bunların içinden hareket ettiren bir animasyon aracıdır. Kameraya yakın katmanlar, uzaktakilerden daha hızlı kayar; bu da hiçbir 3D model kullanmadan paralaks ve derinlik hissi yaratır.
Onu tek seferlik bir animasyon olmaktan çıkarıp bir stüdyo yapan üç bileşen vardır:
- Bir sahne grafiği:
zderinliği, boyut, konum ve HTML içeriğine sahip katmanlar. - Bir zaman çizelgesi: kamera için (dolly, truck, orbit) ve her katman için (opaklık, ölçek, konum) anahtar kareler; her biri bir yumuşatma eğrisiyle.
- Belirlenebilir (deterministik) bir render motoru: herhangi bir
tzamanı için tam kareyi çizen birrenderAt(t)fonksiyonu; böylece dışa aktarım, makinenin oynatma hızına bağlı kalmaz.
Çoğu eğitimcinin atladığı nokta üçüncüsüdür ve MP4 dosyanızın takılıp takılmayacağını o belirler.
Opus 5.5 ile Claude Code'u kurun
Bu tür bir iş için başlangıç modeli Opus 5.5'tir. Anthropic'in modeller genel bakışı, onu “uzun süreli ajentik kodlama ve bilgi işi için” olarak tanımlar; 1 milyon token bağlam penceresi, 128K maksimum çıktı ve milyon giriş/çıkış tokenı başına 4 $ / 20 $ fiyatlandırma ile.
Modeli sabitleyin ki bir takma ad değişikliği projenin ortasında onun değişmesine yol açmasın:
claude --model claude-opus-5-5 --effort high
effort dokümanlarına göre Opus 5.5 varsayılan olarak medium effort kullanır. İlk kurulumda, ajanın projeksiyon matematiğini doğru yapması gerektiğinde bunu high seviyesine yükseltin. Anahtar kareler ve renklerde küçük düzeltmeler için tekrar medium'a düşürün. Modele önce arka plan bilgisi edinmek isterseniz Claude Opus 5.5 nedir yazısını ve prompt caching'in maliyetini nasıl değiştirdiğini okuyun.
Stüdyoyu kuran komut (prompt)
Tek bir net komut, beş belirsiz komuttan daha iyidir. İşte tek bir komut olarak yazılmış kurulum spesifikasyonumuz:
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.
Son iki satır en önemlisidir: dışa aktarımı tasarımın bir parçası haline getirirler, sonradan eklenen bir özellik değil.
Ajanın yazdığı kod
Stüdyo yaklaşık 150 satırdan oluşuyor. Üç parçası önemli.
Anahtar kareler ve yumuşatma
Her iz (track), sıralı bir anahtar kare listesidir. sample(), t'yi çevreleyen iki anahtarı bulur, çıkış yapan anahtarın yumuşatma eğrisini uygular ve her sayısal alanı interpolasyonla hesaplar:
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];
}
Derinlik numarası
Kamera hiç hareket etmez. Dünya ters yönde hareket eder. Böylece her katman z ekseninde bir translate ve buna eşlik eden bir ölçek dengelemesi alır:
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})`;
CSS perspective değeri 1200px olarak ayarlandığında, z = -900 konumundaki bir katman 1200 / 2100, yani kendi boyutunun %57'si kadar render edilir. Ölçeğini ve x/y kaymasını 1 + 900/1200 = 1.75 ile çarpmak bunu dengeler. Böylece kamera dururken her katman, sizin tasarladığınız boyut ve konumda görünür; kamera hareket ettiğinde de kendi hızında hareket etmeye devam eder. Tüm yanılsama bu kadar.

Bilinmesinde fayda olan hata
İlk sürüm her katmanı ölçeklendirdi ama kaymasını ölçeklemediği için tepeler yükselip gökyüzünün üçte ikisini kapladı. Çözüm: x ve y değerlerini de comp ile çarpmak. Bunu koddan okuyarak değil, tek bir render edilmiş kareden yakaladık; bu yüzden herhangi bir kamera hareketine güvenmeden önce ajanınızdan başlangıç, orta ve son noktalarda kare görüntüleri üretmesini isteyin.
Zaman çizelgesini MP4'e aktarın
Gerçek zamanlı oynatma, makine meşgulken kare düşüren requestAnimationFrame kullanır. Dışa aktarım bunu affetmez. Bu yüzden dışa aktarıcı zamanı kare indeksinden türetir ve bir Playwright ekran görüntüsü almadan önce her karenin çizilmesini bekler:
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), iki animasyon karesinden sonra resolve olur; böylece her ekran görüntüsü yeni transformları görür. image2pipe (ffmpeg format dokümanlarına bakın) PNG'leri stdin'den okur ve yuv420p, dosyanın tarayıcılarda oynatılabilir kalmasını sağlar.
Bizim çalıştırmamız: 180 kare, 1280x720, 30 fps, 6.0 saniye, 420 KB'lık bir MP4, 20 saniyelik gerçek süre. Playwright'ın henüz bir tarayıcısı yoksa bir kez npx playwright install chromium çalıştırın.

Şehirdeki kuleler, çerçeveden tamamen çıkan koyu ön plan tepesinden daha az kayar. Paralaks tam olarak budur.
Opus 5.5 API ile “çekim tanımlama” özelliği ekleyin
Sırada, bir yazarın çekim açıklaması yazıp anahtar kareleri geri alması var. Stüdyo, Messages API'yi doğrudan çağırır:
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." }]
}'
Effort dokümanlarındaki iki ayrıntı burada önemli. output_config.effort, effort seviyesinin Messages API isteğinde bulunduğu yerdir. Ve Opus 5.5 her zaman adaptive thinking kullanır (thinking: {"type": "disabled"} içeren bir istek 400 döner), bu yüzden düşünme tokenları max_tokens kapsamına girer. Değeri çok düşük ayarlarsanız JSON, dizinin ortasında stop_reason: "max_tokens" ile kesilir. Bir çekim listesi küçük ve net tanımlı bir görevdir, bu yüzden low effort mantıklı bir başlangıç ayarıdır; karar vermeden önce kendi karşılaştırmanızı yapın.
Claude Code'un API çağrısını Apidog CLI ile test etmesine izin verin
Kesilmiş veya gereksiz yere konuşkan bir yanıt, render sırasında sample()'ı bozar; bu yüzden bu çağrının bir sözleşme testine ihtiyacı var. Aynı Claude Code oturumu, Apidog CLI ile bu testi hem yazabilir hem çalıştırabilir.
Bir kez kurun ve giriş yapın:
npm install -g apidog-cli@latest
apidog auth login --with-token <YOUR_TOKEN>
apidog skill install
Sonra ajana tek bir komut verin:
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.
Ajan, payload şemalarını tahmin etmek yerine okur, dosyalarını doğrular, sonra her şeyi oluşturur ve çalıştırır:
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
Anahtarı çalışma anında --env-var "api_key=$ANTHROPIC_API_KEY" ile verin ki hiçbir zaman projenin içinde durmasın. Sistem komutunu (system prompt) veya effort seviyesini değiştirdiğinizde testi yeniden çalıştırın; çünkü ikisi de dönen yanıtı etkiler. -r junit ile aynı apidog run komutu CI'a doğrudan entegre olur; Apidog CLI CI/CD rehberine ve Claude Code'da Apidog CLI yazısına göz atın. Apidog'un Ücretsiz planı 4 kullanıcıya kadar yeter.
Stüdyoyu bir sonraki adımda nereye götürmelisiniz
- Daha fazla katman, aynı matematik. Yağmur, ikinci bir başlık ya da bir logo ekleyin; her birine bir
zverin, dengeleme gerisini halleder. - Render motorunu değiştirin. Sahneleme bileşenlerini React bileşenleri olarak yazmak isterseniz Remotion ile Claude Code o yolu anlatıyor. Buradaki tek dosya yaklaşımında ise bir derleme adımı yok. Claude Code genel bakışı oturumları ve izinleri açıklar.
SSS
Motion grafiklerde 2.5D ne anlama gelir? Farklı derinliklere yerleştirilmiş düz 2D grafiklerin hareketli bir kamera ile çekilmesi anlamına gelir. 3D model, ışıklandırma veya 3D motor olmadan paralaks ve derinlik ipuçları elde edersiniz.
Bu kurulum için daha küçük bir model yerine neden Opus 5.5 kullanmalıyım? İlk kurulum, projeksiyon matematiğini, bir anahtar kare motorunu ve bir yakalama hattını tek geçişte birleştirir. Anthropic, Opus 5.5'i uzun süreli ajentik kodlama için konumlandırıyor ve bizim oturumumuz tek komut artı bir tur düzeltmeyle çalışan bir stüdyo üretti. Sonrasındaki küçük düzenlemeler için daha düşük bir effort seviyesi yeterlidir.
Kare yakalamak yerine neden ekranı kaydetmiyorum? Ekran kaydı gerçek zamanı takip eder; bu yüzden yavaş bir kare, düşmüş veya ikilenmiş bir kareye dönüşür. i / fps konumuna gidip her kareyi yakalamak, çıktının her makinede aynı olmasını sağlar.
“Çekim tanımlama” özelliğini bir API anahtarı olmadan kullanabilir miyim? Hayır. Bu özellik Messages API'yi çağırır ve kendi Anthropic API anahtarınızı gerektirir. Stüdyonun geri kalanı ve MP4 dışa aktarımı, anahtar olmadan yerel olarak çalışır.
Çekim listesi çağrısı hangi effort seviyesini kullanmalı? low ile başlayın; çünkü görev kısadır ve çıktı şeması sabittir. Yalnızca Apidog testiniz bozuk ya da brief'e aykırı anahtar kareler gösterirse yükseltin.
