Cara Membangun Studio Motion 2.5D dengan Opus 5.5

Satu prompt, satu file HTML, satu exporter berukuran 25 baris: bangun studio motion 2.5D berbasis browser dengan Opus 5.5 yang menggerakkan Claude Code, render hasilnya ke MP4, dan uji panggilan API shot-list Opus 5.5 dengan Apidog CLI.

Ahmed Waheed

Ahmed Waheed

12 November 2026

Cara Membangun Studio Motion 2.5D dengan Opus 5.5

Apidog untuk Perusahaan

Penerapan On-Premises

SSO & RBAC

Sesuai SOC 2

Jelajahi Apidog Enterprise

Anda bisa membangun studio motion 2.5D dengan Opus 5.5 dalam satu sesi Claude Code: satu file HTML yang menumpuk lapisan datar pada kedalaman berbeda, menggerakkan kamera ber-keyframe melewatinya dengan easing, dan skrip Playwright berisi 25 baris yang menangkap setiap frame lalu menyalurkannya ke ffmpeg. Build kami merender MP4 720p berdurasi 6 detik (180 frame) dalam sekitar 20 detik di laptop.

Panduan ini menunjukkan prompt yang kami gunakan, kode yang ditulis agen, bug yang ditemuinya, dan cara memeriksa panggilan API Opus 5.5 di balik fitur "describe a shot" dengan Apidog CLI.

Apa itu studio motion 2.5D?

Studio motion 2.5D adalah alat animasi yang menempatkan lapisan 2D datar (langit, bukit, kota, kartu judul, dedaunan latar depan) pada kedalaman berbeda dalam ruang 3D, lalu menggerakkan kamera virtual melewatinya. Lapisan yang lebih dekat ke kamera bergeser lebih cepat daripada yang jauh, sehingga menghasilkan efek parallax dan kesan kedalaman tanpa model 3D apa pun.

Tiga bagian menjadikannya sebuah studio, bukan sekadar animasi sesaat:

  1. Scene graph: lapisan dengan kedalaman z, ukuran, posisi, dan konten HTML.
  2. Timeline: keyframe untuk kamera (dolly, truck, orbit) dan untuk setiap lapisan (opacity, scale, posisi), masing-masing dengan kurva easing.
  3. Renderer deterministik: fungsi renderAt(t) yang menggambar frame yang tepat untuk waktu t mana pun, sehingga ekspor tidak pernah bergantung pada seberapa cepat mesin memutarannya.

Poin ketiga itulah yang paling sering dilewatkan tutorial, dan poin itu menentukan apakah MP4 Anda patah-patah atau tidak.

Menyiapkan Claude Code dengan Opus 5.5

Opus 5.5 adalah model yang tepat untuk memulai pekerjaan semacam ini. Ringkasan model-model Anthropic menggambarkannya sebagai model "untuk pekerjaan coding agentic dan pengetahuan yang berjalan lama", dengan jendela konteks 1 juta token, output maksimal 128K, dan harga $4 / $20 per juta token input / output.

Kunci modelnya agar perubahan alias tidak menggantinya di tengah proyek:

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

Opus 5.5 secara default menggunakan effort medium, menurut dokumentasi effort. Naikkan ke high untuk build pertama, saat agen harus mendapatkan matematika proyeksinya dengan benar. Turunkan kembali ke medium untuk penyesuaian kecil pada keyframe dan warna. Jika Anda ingin memahami model ini lebih dulu, baca apa itu Claude Opus 5.5 dan bagaimana prompt caching mengubah biayanya.

Prompt yang membangun studio

Satu prompt yang spesifik mengalahkan lima prompt yang samar. Berikut spesifikasi build kami, ditulis sebagai satu 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.

Dua baris terakhir paling penting: keduanya menjadikan ekspor bagian dari desain, bukan tambahan belakangan.

Kode yang ditulis agen

Studionya berisi sekitar 150 baris. Tiga bagian yang penting.

Keyframe dan easing

Setiap track adalah daftar keyframe yang terurut. sample() mencari dua keyframe yang mengapit t, menerapkan easing dari keyframe keluar, dan menginterpolasi setiap field numerik:

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

Trik kedalaman

Kamera tidak pernah bergerak. Dunialah yang bergerak sebaliknya. Setiap lapisan kemudian mendapat translasi pada sumbu z plus skala kompensasi:

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

Dengan CSS perspective yang diatur ke 1200px, lapisan di z = -900 dirender pada skala 1200 / 2100, atau 57% dari ukurannya. Mengalikan skala dan offset x/y-nya dengan 1 + 900/1200 = 1,75 meniadakan efek itu. Setiap lapisan muncul pada ukuran dan posisi yang Anda tentukan saat kamera diam, dan tetap bergerak dengan kecepatannya sendiri saat kamera bergerak. Itulah seluruh ilusinya.

Studio motion 2.5D di browser: sebuah kartu judul di depan bulan, bukit, dan siluet kota, dengan timeline yang menampilkan keyframe kamera berwarna biru, keyframe lapisan berwarna kuning, dan playhead merah di 2,10 detik

Bug yang perlu Anda ketahui

Versi pertama mengalikan skala setiap lapisan tetapi bukan offsetnya, sehingga bukit-bukit naik menutupi dua pertiga langit. Solusinya: kalikan x dan y dengan comp juga. Kami menemukannya dari satu frame hasil render, bukan dari membaca kode, jadi mintalah agen Anda merender tangkapan still di awal, tengah, dan akhir sebelum Anda memercayai gerakan kamera apa pun.

Mengekspor timeline ke MP4

Pemutaran real-time menggunakan requestAnimationFrame, yang membuang frame saat mesin sedang sibuk. Ekspor tidak boleh begitu. Karena itu, exporter menggerakkan waktu dari indeks frame dan menunggu setiap frame selesai digambar sebelum mengambil tangkapan layar 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) resolves setelah dua animation frame, sehingga setiap tangkapan layar melihat transformasi yang baru. image2pipe (lihat dokumentasi format ffmpeg) membaca PNG dari stdin, dan yuv420p menjaga agar file tetap bisa diputar di browser.

Hasil run kami: 180 frame, 1280x720, 30 fps, 6,0 detik, sebuah MP4 berukuran 420 KB, dalam 20 detik waktu nyata. Jalankan npx playwright install chromium sekali jika Playwright belum memiliki browser.

Tiga frame dari MP4 hasil ekspor pada 0,3 detik, 2,5 detik, dan 5,9 detik: kamera mendorong mendekat ke kartu judul sementara siluet kota dan bukit latar depan bergeser dengan kecepatan berbeda, lalu mengorbit sehingga kartu miring

Menara-menara kota bergeser lebih sedikit daripada bukit latar depan yang gelap, yang keluar dari frame sepenuhnya. Itulah parallax.

Menambahkan fitur "describe a shot" dengan API Opus 5.5

Selanjutnya, biarkan seorang penulis mengetik deskripsi shot dan mendapatkan keyframe sebagai hasilnya. Studio memanggil Messages API secara langsung:

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

Dua detail dari dokumentasi effort penting di sini. output_config.effort adalah tempat level effort ditempatkan dalam request Messages API. Dan Opus 5.5 selalu menggunakan adaptive thinking (request dengan thinking: {"type": "disabled"} mengembalikan 400), sehingga token thinking ikut dihitung dalam max_tokens. Jika terlalu kecil, JSON terpotong di tengah array dengan stop_reason: "max_tokens". Daftar shot adalah tugas yang kecil dan spesifikasinya jelas, jadi effort low adalah pilihan awal yang masuk akal; lakukan perbandingan sendiri sebelum menetapkannya.

Meminta Claude Code menguji panggilan API dengan Apidog CLI

Balasan yang terpotong atau bertele-tele akan merusak sample() saat render, sehingga panggilan ini membutuhkan contract test. Sesi Claude Code yang sama bisa menulis dan menjalankannya dengan Apidog CLI.

Instal dan login sekali:

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

Kemudian beri agen satu 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.

Agen membaca schema payload alih-alih menebaknya, memvalidasi filenya, lalu membuat dan menjalankan semuanya:

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

Serahkan key saat runtime dengan --env-var "api_key=$ANTHROPIC_API_KEY" agar key tidak pernah tersimpan di proyek. Jalankan ulang test case ketika Anda mengubah system prompt atau level effort, karena keduanya mengubah hasil yang dikembalikan. apidog run yang sama dengan -r junit bisa langsung dipakai di CI; lihat panduan CI/CD Apidog CLI dan Apidog CLI di Claude Code. Paket Free Apidog mencakup hingga 4 pengguna.

Langkah selanjutnya untuk studio ini

FAQ

Apa arti 2.5D dalam motion graphics? Artinya karya seni 2D datar ditempatkan pada kedalaman berbeda dan direkam oleh kamera yang bergerak. Anda mendapatkan parallax dan isyarat kedalaman tanpa model 3D, pencahayaan, atau engine 3D.

Mengapa menggunakan Opus 5.5 alih-alih model yang lebih kecil untuk build ini? Build pertama mencampur matematika proyeksi, engine keyframe, dan pipeline tangkap dalam satu kali jalan. Anthropic memosisikan Opus 5.5 untuk coding agentic berdurasi panjang, dan sesi kami menghasilkan studio yang berfungsi dari satu prompt plus satu putaran perbaikan. Untuk editan kecil setelahnya, level effort yang lebih rendah sudah cukup.

Mengapa tidak merekam layar alih-alih menangkap frame? Rekaman layar mengikuti waktu nyata, sehingga frame yang lambat menjadi frame yang hilang atau berlipat. Dengan seek ke i / fps dan menangkap setiap frame, hasilnya identik di setiap mesin.

Bisakah saya menggunakan fitur "describe a shot" tanpa API key? Tidak. Fitur ini memanggil Messages API, yang membutuhkan API key Anthropic Anda sendiri. Bagian lain dari studio dan ekspor MP4 berjalan secara lokal tanpa key.

Level effort apa yang sebaiknya dipakai untuk panggilan daftar shot? Mulailah dengan low, karena tugasnya pendek dan schema outputnya tetap. Naikkan hanya jika pengujian Apidog Anda menunjukkan keyframe yang rusak format atau tidak sesuai deskripsi.

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.