All Products
Search
Document Center

Alibaba Cloud Model Studio:Panduan Integrasi HappyOyster Web SDK

Last Updated:Oct 16, 2026

Dokumen ini ditujukan bagi pengembang frontend dan full-stack serta menjelaskan cara mengintegrasikan HappyOyster Web SDK secara andal di lingkungan produksi untuk mode Adventure, Directing, dan Acting.

Dokumen ini ditujukan bagi pengembang frontend dan full-stack. Dokumen ini menjelaskan cara mengintegrasikan SDK secara andal di lingkungan produksi. Untuk masing-masing API, lihat Referensi API.

0. Contoh Integrasi Minimal

Jika backend Anda sudah mengembalikan token API key sementara Model Studio dan ticket Travel, alur SDK frontend adalah sebagai berikut:

import { HappyOysterEngine, isSdkError } from "@happy-oyster/js-sdk";

const engine = new HappyOysterEngine({
  APIHost: "open-platform.example.com",
  model: "happyoyster-1.0-adventure", // Required; Adventure model shown as an example
  logLevel: "warn",
});

engine.updateToken(token);

const videoElement = document.querySelector("video") as HTMLVideoElement;
const travel = engine.createTravel({
  ticket,
  videoElement,
  maxExperienceTimeSec: 90, // Optional, Adventure only: 60 / 90 / 120
});

const offStatus = travel.on("statusChanged", (status) => {
  // Use status to drive loading states, disabled buttons, and player UI.
});

const offError = travel.onError((error) => {
  // Usually log, show a toast, and refresh the token if it has expired.
  if (isSdkError(error)) console.error(error.code, error.message);
});

try {
  await travel.start();
  // Enable controls or Directing input with travel.can(action) after the session is running.
} finally {
  offStatus();
  offError();
  await travel.end();
}

Cuplikan ini hanya mencakup sisi SDK. Pembuatan dunia, menunggu hingga siap, meminta ticket, dan meminta token API key sementara Model Studio harus dilakukan di atau melalui backend aplikasi Anda.

1. Gambaran Umum Alur Menyeluruh

Pengalaman lengkap terutama melibatkan komponen berikut.

1.1 Komponen

Komponen

Tanggung jawab

Frontend aplikasi

UI, <video>, orkestrasi sesi, dan panggilan SDK

Backend aplikasi

Menyimpan API Key utama, memanggil API dunia Open Platform atas nama klien, dan menerbitkan kredensial sementara Model Studio

HappyOyster OpenAPI

Menyediakan API yang diperlukan oleh model dunia HappyOyster.

HappyOyster SDK

SDK yang digunakan oleh frontend aplikasi. SDK ini terutama mengelola sesi Travel dan akses stream video pada klien.

happy-oyster-overview.png

1.2 Alur Pengalaman

Tahap

Pelaksana

Tindakan

Deskripsi

① Buat dunia

Backend aplikasi → HappyOyster OpenAPI

POST /openapi/v1/worlds

Mengembalikan encryptedWorldId, status, dan firstFrame

② Tunggu hingga siap

Backend aplikasi → HappyOyster OpenAPI

GET /openapi/v1/worlds/build-status

Lakukan polling hingga status === ready (lewati langkah ini jika dunia sudah siap saat dibuat)

③ Dapatkan kredensial Travel

Backend aplikasi → HappyOyster OpenAPI

POST /openapi/v1/worlds/get-travel-credential

Mengembalikan ticket sekali pakai untuk enter-travel

④ Minta token API key sementara

Backend aplikasi → HappyOyster OpenAPI

POST /api/v1/tokens?expire_in_seconds=1800

Mengembalikan token API key sementara. Jangan tetapkan masa berlaku terlalu singkat karena token dapat kedaluwarsa sebelum pengalaman selesai dan perlu sering diperbarui.

⑤ Kirim token API key sementara dan kredensial Travel

Frontend aplikasi → backend aplikasi → frontend aplikasi

Minta API key sementara dan kredensial Travel

Setelah frontend menerima token dan ticket, frontend memulai alur SDK

⑥ Masuk ke pengalaman

Frontend aplikasi → HappyOyster SDK

Lihat “Subalur startup SDK” di bawah

new HappyOysterEngine/updateToken → createTravel → start()

1.3 Subalur Interaksi SDK (Rincian Tahap ⑥)

1.3.1 Memulai Travel

travel-start-flow.png

Persyaratan utama urutan panggilan

Langkah

API

Deskripsi

1

new HappyOysterEngine()

Gunakan kembali Engine untuk APIHost + model yang sama

2

updateToken()

Selesaikan sebelum start()

3

createTravel()

videoElement wajib diisi

4

travel.on(...)

Daftarkan listener sebelum start()

5

await travel.start()

Memasuki running setelah berhasil dimulai

1.3.2 Bermain dalam Mode Adventure

adventure-command-flow.png

1.3.3 Bermain dalam Mode Directing / Acting

adventure-control-flow.png

Tabel ini merangkum perbedaan Adventure, Directing, dan Acting:

Mode

API utama

Penggunaan umum

Hal yang perlu diperhatikan

Adventure (1)

sendCommand()

Kontrol real-time dengan keyboard, joystick, dan tombol

Kirim hanya setelah running; maxExperienceTimeSec hanya berlaku untuk mode ini

Directing (2)

sendInstruct(), pause(), resume(), rewind()

Pengarahan dengan bahasa alami dan kontrol pemutaran

Jeda, lanjutkan, dan putar balik bergantung pada kemampuan sesi; periksa travel.can(action) terlebih dahulu

Acting (3)

sendInstruct(), pause(), resume()

Pengalaman berorientasi akting dan konfigurasi rasio aspek

Jeda dan lanjutkan bergantung pada kemampuan sesi; rewind() tidak tersedia dan scriptlist tidak dapat menggunakan sendInstruct()

1.4 Praktik Backend Aplikasi (Ringkasan)

Di sisi backend, patuhi aturan berikut:

  • Simpan API Key utama hanya di backend aplikasi. Browser hanya boleh menerima token berumur pendek (demo: POST /server-api/temp-api-key).
  • Minta kredensial Travel melalui backend. Otorisasi dunia dan pengguna sebelum menerbitkan ticket; jangan hard-code atau menyimpannya dalam cache jangka panjang di frontend.
  • Jangan terbitkan kredensial sebelum dunia berstatus ready. Jika tidak, enter-travel dapat gagal atau pengalaman menjadi tidak lengkap.
  • Arahkan backend aplikasi dan SDK ke lingkungan Open Platform yang sama. Backend dapat menggunakan URL OpenAPI lengkap; APIHost SDK harus hanya berupa nama host, seperti open-platform.example.com.

2. Konsep Inti SDK

Dalam alur pada §1, SDK hanya bertanggung jawab atas “masuk Travel → putar → kontrol → akhiri”. Ada dua objek inti:

Objek

Tujuan

HappyOysterEngine

Mengonfigurasi APIHost dan model, mengelola token API key sementara Model Studio (updateToken), dan membuat sesi Travel

Travel

Mewakili satu sesi: start terhubung ke RTC; sendCommand, sendInstruct, dan metode siklus hidup mengontrol sesi

Status sesi (statusChanged):

idle ──start()──► prepare ──video playable──► running ⇄ paused ──end()──► idle

Tiga batasan (dijelaskan kemudian):

  • Setiap Engine hanya boleh memiliki satu Travel aktif pada satu waktu.
  • videoElement harus diberikan ke createTravel.
  • Token API key sementara Model Studio dan tiket Travel memiliki tujuan berbeda (lihat tahap ④–⑤ pada §1.2 dan §3.2).

3. Inisialisasi dan Pengelolaan Token

3.1 Instansiasi Engine

Wajib
  • Konfigurasikan APIHost sebagai nama host Open Platform saja, tanpa https://, skema, atau path, seperti open-platform.example.com.
  • Gunakan kembali HappyOysterEngine untuk APIHost + model yang sama. Sebelum mengganti host atau model, akhiri Travel aktif dan gunakan Engine yang dikonfigurasi untuk target baru.
Disarankan
  • Gunakan logLevel: 'debug' dalam pengembangan dan 'warn' atau 'none' dalam produksi.
  • Buat Engine pada lapisan orkestrasi sesi, bukan membuat yang baru setiap kali memulai.

Tabel berikut merangkum kolom konfigurasi umum:

Kolom

Wajib

Panduan

APIHost

Ya

Berikan nama host saja, seperti open-platform.example.com; jangan sertakan https:// atau path

model

Ya

Wajib, tanpa nilai default; samakan dengan model backend yang digunakan untuk membuat dunia dan menerbitkan tiketnya. Nilai ini tetap untuk Engine dan tidak disimpulkan dari mode atau tiket

token

Tidak

Anda dapat memberikannya melalui konstruktor atau mengaturnya nanti dengan updateToken(token); perbarui token kedaluwarsa dengan updateToken juga

logLevel

Tidak

Gunakan debug dalam pengembangan dan warn atau none dalam produksi

streamReadyTimeout

Tidak

Naikkan nilainya jika jaringan atau persiapan rendering lambat; sediakan cara mencoba ulang setelah timeout

Hindari
  • Memanggil new HappyOysterEngine() berulang kali saat rendering atau pada jalur yang sering dieksekusi.
  • Memberikan URL lengkap, misalnya yang menyertakan https://, atau memanggil API backend SDK tanpa mengisi APIHost.

3.2 Model Dua Kredensial

Sesuai dengan tahap ③–⑤ pada §1.2:

Kredensial

Sumber

Cara mengatur

Tujuan

Token API key sementara Model Studio

Kunci berumur pendek yang diterbitkan backend aplikasi

sdk.updateToken(token)

Mengautentikasi permintaan SDK ke Open Platform

Tiket Travel

Kredensial Travel yang diminta oleh backend aplikasi

createTravel({ ticket })

Kredensial sekali pakai untuk sesi Travel

Wajib
  • Siapkan kedua kredensial sebelum travel.start().
  • SDK tidak menyimpan secara persisten atau memperbarui secara otomatis token.
Disarankan
  • Jika token kedaluwarsa atau error heartbeat diterima melalui onError, minta token baru melalui backend aplikasi lalu panggil updateToken.
Hindari
  • Mencampuradukkan kedua kredensial.
  • Mengekspos API Key utama ke frontend aplikasi.

4. Siklus Hidup Travel

4.1 Membuat dan Memulai

Wajib
  • Panggil createTravel({ ticket, videoElement }); ticket adalah kredensial Travel sekali pakai, dan videoElement diberikan pada tahap ini.
  • Daftarkan statusChanged dan onError sebelum await travel.start() agar error dan perubahan status selalu terpantau.
Disarankan
  • Tampilkan UI sedang menghubungkan selama prepare untuk mencegah klik berulang. Gunakan travelInfoReady untuk membaca metadata sesi lebih awal, dan gunakan firstFrameGenerated sebagai placeholder frame pertama jika tersedia.
Hindari
  • Membuat Travel sebelum elemen DOM siap.

4.2 Saat Berjalan

  • Perbarui UI berdasarkan statusChanged: prepare berarti menunggu video, sedangkan running berarti interaksi tersedia.
  • Perhatikan penggunaan dan prasyarat pause, resume, dan rewind (bergantung pada kemampuan sesi; rewind juga memerlukan sesi berstatus paused dan stream sudah berhenti).

4.3 Mengakhiri dan Membuat Ulang

Wajib
  • Akhiri sesi dengan await travel.end().
  • Pastikan Travel sebelumnya sudah berakhir sebelum membuat yang baru.
  • Panggil travel.end() saat pembersihan ketika halaman ditutup atau rute berubah.
Disarankan
  • Setelah kegagalan, lakukan “akhiri → hapus listener → coba ulang dari tahap ③ atau ⑤ pada §1.2”.
  • Minta kredensial Travel baru saat mencoba ulang jika kredensial bersifat sekali pakai.
Hindari
  • Memanggil createTravel kedua kali tanpa mengakhiri Travel pertama; tindakan ini melempar pengecualian secara sinkron.
  • Meninggalkan halaman tanpa pembersihan, yang menyebabkan kebocoran resource RTC.

5. Elemen Video dan Kebijakan Browser

Wajib
  • Atur playsInline pada <video> (wajib di iOS).
  • Pahami pengaruh kebijakan autoplay browser terhadap autoPlay dan muted.
Disarankan
  • Selama prepare, tampilkan gambar frame pertama sebagai overlay; sembunyikan setelah sesi memasuki running.
  • Konfigurasikan streamReadyTimeout sesuai kebutuhan (default: 15.000 ms), dan sediakan tindakan coba ulang setelah timeout.
  • Tetapkan rasio aspek tetap untuk kontainer pemutar.
Hindari
  • Memberikan referensi elemen video sebelum elemen tersebut terpasang di DOM.
  • Membiarkan UI tetap interaktif saat sesi berstatus paused atau stream terputus.

6. Langganan Event dan Penanganan Error

6.1 Langganan Event

Wajib
  • Event milik Travel, bukan HappyOysterEngine.
  • Simpan fungsi berhenti berlangganan yang dikembalikan oleh travel.on(...) dan travel.onError(...).
Disarankan
  • Daftarkan dan bersihkan listener di satu tempat. Hapus listener lama sebelum beralih sesi Travel.

Event

Tujuan

statusChanged

Menampilkan status, mendeteksi kesiapan video (running), dan mengaktifkan atau menonaktifkan tombol

travelInfoReady

Membaca encryptedTravelId, mode, frame pertama, durasi pengalaman, dan rasio aspek Acting sebelum RTC terhubung; travel.getInfo() mengembalikan data yang sama

firstFrameGenerated

Jika frame pertama yang tidak kosong tersedia, event ini mengikuti travelInfoReady; gunakan sebagai placeholder selama prepare

error (melalui onError)

Pencatatan log, notifikasi toast, dan pemicu pembaruan token

6.2 Lapisan Error

  • Kegagalan startup: travel.start() ditolak (enter-travel / RTC / timeout).
  • Error runtime: dilaporkan melalui travel.onError (error RTC, kegagalan autentikasi heartbeat, dan sebagainya).
  • Error backend aplikasi dan Open Platform pada tahap ①–④ di §1.2 ditangani oleh lapisan aplikasi dan tidak masuk ke SDK.
Hindari
  • Hanya menangkap error start() tanpa mendengarkan onError.
  • Mendaftarkan listener berulang kali tanpa berhenti berlangganan.

7. Mengirim Instruksi: Command dan Instruct

7.1 sendCommand (Kontrol Real-Time)

sendCommand() menyediakan kontrol real-time dalam mode Adventure (1). Metode ini mengirim perintah melalui RTC DataChannel dan hanya tersedia saat sesi berstatus running.

SDK mengirim maksimal satu perintah kira-kira setiap 42 ms (sekitar 24 FPS). Jika satu siklus telah berlalu sejak pengiriman sebelumnya, perintah baru langsung dikirim. Jika sendCommand() dipanggil beberapa kali dalam siklus yang sama, hanya perintah lengkap dari panggilan terakhir yang dikirim. translation, rotation, dan interaction adalah dimensi kontrol independen. Kolom yang dihilangkan dikirim sebagai None; SDK tidak menggabungkan kolom antar-panggilan, mengulangi perintah sebelumnya secara berkala, atau mengirim None secara otomatis.

Tindakan satu kali

Panggil sendCommand() sekali untuk tindakan satu kali seperti melompat atau menyerang:

await travel.sendCommand({ interaction: "Jump" });
Tindakan berkelanjutan

Terus panggil sendCommand() selama kontrol gerakan atau rotasi pandangan berkelanjutan tetap ditekan. Aplikasi frontend tidak perlu membatasi panggilan menjadi setiap 42 ms; SDK menggabungkan panggilan berfrekuensi tinggi menjadi laju output sekitar 24 FPS. Saat dilepas, kirim None secara eksplisit untuk mereset kontrol:

// Keep calling while the control is pressed
void travel.sendCommand({ translation: "Front" });

// Stop moving on release
void travel.sendCommand({ translation: "None" });
Hindari
  • Mengirim banyak perintah selama prepare.
  • Menggunakan sendCommand untuk instruksi Directing dengan bahasa alami.

7.2 sendInstruct (Instruksi Directing)

Wajib
  • Gunakan sesi Directing (2) atau sesi Acting (3) yang bukan scriptlist; panggil await travel.sendInstruct({ content }).
Disarankan
  • Pastikan content tidak kosong sebelum mengirim dan cegah pengiriman duplikat.
  • Berikan umpan balik kepada pengguna berdasarkan kolom yang dikembalikan seperti accepted.

8. Pemecahan Masalah

Gejala

Penyebab umum

Tindakan

Inisialisasi SDK gagal dengan error argumen

APIHost diberikan sebagai URL lengkap, misalnya dengan https:// atau path

Berikan nama host saja, seperti open-platform.example.com

travel.start() gagal karena tiket tidak valid atau sudah digunakan

ticket bersifat sekali pakai; mungkin sudah kedaluwarsa, digunakan ulang, atau diterbitkan sebelum dunia siap

Minta ticket baru dari backend; pastikan dunia siap sebelum masuk

onError melaporkan error autentikasi setelah sesi berjalan

token API key sementara Model Studio kedaluwarsa

Minta token baru dari backend, lalu panggil engine.updateToken(newToken)

Pemutar terus memuat atau start() mengalami timeout

Stream jarak jauh belum siap, jaringan lambat, atau streamReadyTimeout terlalu singkat

Sediakan tindakan coba ulang; naikkan streamReadyTimeout bila perlu; periksa log backend dan RTC

Panggilan createTravel() kedua gagal karena Travel aktif sudah ada

Travel sebelumnya belum diakhiri

Panggil await travel.end() dan bersihkan listener saat keluar, mencoba ulang, atau berganti sesi

Kontrol atau instruksi tidak bereaksi

Sesi tidak berstatus running, atau API yang digunakan tidak sesuai untuk mode Adventure, Directing, atau Acting saat ini

Atur ketersediaan tombol berdasarkan statusChanged; panggil travel.can(action) sebelum tindakan yang bergantung pada mode

Saat debugging, catat tiga hal bersama-sama: ErrorCode SDK, TravelStatus saat ini, dan log permintaan backend. Biasanya informasi ini menunjukkan apakah masalah terkait kredensial, status, jaringan, atau rendering.