Skip to main content

HappyOyster Web SDK 接入指南

本文面向前端 / 全棧開發者,說明如何在生產環境中穩定接入 HappyOyster Web SDK 。

具體 API 需參考 HappyOyster Web SDK API Reference。

最小接入示例

如果你已經從伺服器端拿到了百鍊臨時 api-key token 和 Travel ticket,前端接入 SDK 的最小鏈路大致如下:
import { HappyOysterEngine, isSdkError } from "@happy-oyster/js-sdk";

const engine = new HappyOysterEngine({
  APIHost: "open-platform.example.com",
  model: "happyoyster-1.0-adventure", // 必填;此处以 Adventure 模型为例
  logLevel: "warn",
});

engine.updateToken(token);

const videoElement = document.querySelector("video") as HTMLVideoElement;
const travel = engine.createTravel({
  ticket,
  videoElement,
  maxExperienceTimeSec: 90, // 可选,仅 Adventure 生效:60 / 90 / 120
});

const offStatus = travel.on("statusChanged", (status) => {
  // 用 status 驱动 loading、按钮禁用、播放器状态等 UI。
});

const offError = travel.onError((error) => {
  // 这里通常做日志、toast;如果是 token 过期,重新向服务端申请 token 后 updateToken。
  if (isSdkError(error)) console.error(error.code, error.message);
});

try {
  await travel.start();
  // running 后再通过 travel.can(action) 开放操控或 Directing 输入。
} finally {
  offStatus();
  offError();
  await travel.end();
}
這段程式碼只覆蓋 SDK 側。建立世界、等待世界 ready、申請 ticket、申請百鍊臨時 api-key token 都應該在業務伺服器端或經由業務伺服器端完成。

端到端鏈路 Overview

一次完整的體驗主要涉及以下參與方。

參與方

參與方

職責

業務前端

UI、<video>、會話編排、呼叫 SDK

業務伺服器端

保管主 API Key、代調開放平台世界類 API、下發百鍊平台臨時憑證

HappyOyster OpenApi

提供 HappyOyster 世界模型所需 API 的對外介面。

HappyOyster SDK

業務前端所呼叫的 SDK,主要負責用戶端側管理 Travel 會話,視訊流接入等。

端到端參與方示意圖

故事鏈路

階段

執行方

動作

說明

① 建立世界

業務伺服器端 → HappyOyster OpenApi

POST /openapi/v1/worlds

返回 encryptedWorldId、status、firstFrame

② 等待就緒

業務伺服器端 → HappyOyster OpenApi

GET /openapi/v1/worlds/build-status

輪詢至 status === ready(建立時已 ready 可跳過)

③ 體驗憑證

業務伺服器端 → HappyOyster OpenApi

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

返回 ticket(一次性,供 enter-travel)

④ 申請臨時 api-key token

業務伺服器端 → HappyOyster OpenApi

POST /api/v1/tokens?expire_in_seconds=1800

返回臨時 api-key token,過期時間建議不要過短,否則可能無法完成整套體驗或頻繁更新 token

⑤ 下發臨時 api-key token 以及體驗憑證

業務前端 → 業務伺服器端 → 業務前端

申請臨時 api-key 和 體驗憑證

前端拿到 token 和 ticket 後,進入 SDK 啓動流程

⑥ 進入體驗

業務前端 → HappyOyster SDK

見下文「SDK 啓動子鏈路」

new HappyOysterEngine/updateToken → createTravel → start()

SDK 遊玩子鏈路(階段 ⑥ 展開)

啓動一個 Travel

Travel 啓動流程
呼叫順序要點

步驟

API

說明

1

new HappyOysterEngine()

同一 APIHost + model 建議復用實例

2

updateToken()

在 start() 前完成

3

createTravel()

必須傳入 videoElement

4

travel.on(...)

建議在 start() 前註冊

5

await travel.start()

成功後進入 running

在 Adventure 模式下進行遊玩

Adventure 即時操控流程

在 Directing / 角色演繹模式下進行遊玩

Directing / 角色演繹 指令流程
Adventure、Directing 和角色演繹可以先按下表理解:

模式

主要能力

常見場景

注意點

Adventure(1)

sendCommand()

鍵盤、搖桿、按鈕等即時操控

只在 running 後發送;maxExperienceTimeSec 僅對該模式生效

Directing(2)

sendInstruct()、pause()、resume()、rewind()

用自然語言推進劇情、控制播放節奏

暫停、恢復和回退由會話能力決定;先用 travel.can(action) 判斷

角色演繹(3)

sendInstruct()、pause()、resume()

演出型體驗與畫幅設定

暫停、恢復由會話能力決定;不支援 rewind(),且 scriptlist 不支援 sendInstruct()

業務伺服器端相關實踐(概要)

伺服器端這邊只抓住幾件事就好:
  • 主 API Key 僅駐留業務伺服器端,瀏覽器只拿短效 token(Demo:POST /server-api/temp-api-key)
  • 體驗憑證由伺服器端代申請,按世界 / 用戶鑒權後再下發 ticket;不要在前端硬編碼或長期快取
  • 世界未 ready 不要簽發憑證,否則 enter-travel 可能失敗或體驗不完整
  • 業務伺服器端與 SDK 指向同一開放平台環境:業務伺服器端可使用完整 OpenAPI 地址;SDK 的 APIHost 只傳裸 host,例如 open-platform.example.com

SDK 核心概念

在端到端鏈路中,SDK 只承擔「進入 Travel → 播放 → 操控 → 結束」段。兩個核心對象:

對象

作用

HappyOysterEngine

設定 APIHost 和 model、百鍊臨時 api-key token(updateToken)、建立 Travel

Travel

一次會話:start 連 RTC,sendCommand / sendInstruct / 生命週期方法

會話狀態(statusChanged):
idle ──start()──► prepare ──video 可播放──► running ⇄ paused ──end()──► idle
三條約束(後文展開):
  • 每個 Engine 同時只允許一個 active Travel
  • videoElement 必須在 createTravel 時傳入
  • 百鍊臨時 api-key token 與 travel ticket 用途不同(見「故事鏈路」階段 ④⑤ 與「雙憑證模型」)

初始化與 Token 管理

Engine 實例化

必須
  • 設定 APIHost(開放平台裸 host,不含 https://、協議頭或路徑,例如 open-platform.example.com)
  • 同一 APIHost + model 復用一個 HappyOysterEngine;切換 host 或模型前,先結束當前 Travel,再使用目標設定的 Engine
推薦
  • 開發環境 logLevel: 'debug',生產環境 'warn' 或 'none'
  • Engine 在會話編排層建立,不用每次 start 都 new
常用設定可以先按這張表理解:

設定項

必填

建議

APIHost

是

只傳裸 host,例如 open-platform.example.com;不要帶 https:// 或路徑

model

是

必填,無預設值;與業務伺服器端建立世界、簽發 ticket 使用的模型保持一致。Engine 建立後固定,不會根據 mode 或 ticket 自動推斷

token

否

可以構造時傳,也可以後續用 updateToken(token) 設定;token 過期後也用 updateToken 刷新

logLevel

否

開發環境用 debug,生產環境用 warn 或 none

streamReadyTimeout

否

網路或渲染鏈路較慢時可調大;超時後建議給用戶重試入口

避免
  • 在 render / 熱路徑中重復 new HappyOysterEngine()
  • 傳入完整 URL(例如帶 https://)或省略 APIHost 後再呼叫 SDK 後端介面

雙憑證模型

對應故事鏈路階段 ③④⑤:

憑證

來源

設定方式

用途

百鍊臨時 api-key token

業務伺服器端下發短效 Key

sdk.updateToken(token)

SDK 與開放平台請求認證

Travel ticket

業務伺服器端代申請體驗憑證

createTravel({ ticket })

Travel 的單次遊玩憑證

必須
  • 在 travel.start() 之前完成兩者準備
  • SDK 不持久化、不自動刷新 token
推薦
  • token 過期或心跳 onError 後,經業務伺服器端重新申請並 updateToken
避免
  • 混用兩種 token
  • 把主 API Key 放到業務前端

Travel 生命週期

建立與啓動

必須
  • createTravel({ ticket, videoElement }) — ticket 為單次 Travel 憑證,videoElement 在此時傳入
  • 先註冊 statusChanged / onError,再 await travel.start(),保證錯誤和狀態感知
推薦
  • prepare 階段展示 connecting UI,防止重復點擊;監聽 travelInfoReady 盡早讀取會話資訊,firstFrameGenerated 可用於展示首影格佔位圖
避免
  • DOM 元素尚未就緒時 create Travel

運行中

  • statusChanged 驅動 UI:prepare = 等待畫面,running = 可交互
  • pause / resume / rewind 的使用場景與前置條件(由會話能力決定;rewind 需在 paused 且流已中斷)

結束與重建

必須
  • 結束會話:await travel.end()
  • 建立新 Travel 前確保上一次已 end
  • 頁面卸載 / 路由離開時在 cleanup 中 travel.end()
推薦
  • 失敗後走「end → 清理監聽 → 從故事鏈路 ③ 或 ⑤ 重試」
  • 重試時重新申請體驗憑證(若一次性)
避免
  • 不 end 就 createTravel 第二次(同步 throw)
  • 頁面離開未 cleanup,導致 RTC 資源洩漏

視訊元素與瀏覽器策略

必須
  • <video> 設定 playsInline(iOS 必需)
  • 瞭解瀏覽器自動播放策略對 autoPlay / muted 的影響
推薦
  • prepare 階段用首影格圖 + 遮罩,running 後隱藏
  • 按需設定 streamReadyTimeout(預設 15000ms),超時給出重試入口
  • 播放器容器預留固定寬高比
避免
  • video 未掛載到 DOM 時傳入元素引用
  • 忽略 paused / 斷流,UI 仍顯示可交互

事件訂閱與錯誤處理

事件訂閱

必須
  • 事件掛在 Travel 上,不是 HappyOysterEngine 上
  • 儲存 travel.on(...) / travel.onError(...) 返回的 unsubscribe 函數
推薦
  • 集中註冊、集中清理;切換 Travel 前先取消舊監聽

事件

用途

statusChanged

狀態展示、畫面就緒判斷(running)、按鈕 enable/disable

travelInfoReady

RTC 連接前取得 encryptedTravelId、模式、首影格、體驗時長與 角色演繹畫幅;也可用 travel.getInfo() 讀取

firstFrameGenerated

有非空首影格時,在 travelInfoReady 後觸發;可用於在 prepare 階段展示佔位圖

error(via onError)

日誌、toast、觸發 token 刷新

錯誤分層

  • 啓動失敗:travel.start() reject(enter-travel / RTC / 超時)
  • 運行時錯誤:travel.onError(RTC、心跳鑒權失敗等)
  • 業務伺服器端 / 開放平台錯誤在故事鏈路 ①–④ 階段由業務層處理,不進 SDK
避免
  • 只 catch start() 不監聽 onError
  • 重復註冊監聽但不 unsubscribe

指令發送:Command 與 Instruct

sendCommand(即時操控)

sendCommand() 用於 Adventure(模式 1)下的即時操控,經 RTC DataChannel 發送,僅在會話處於 running 狀態時可用。 SDK 最多約每 42ms(約 24FPS)發送一次指令:距上次發送已超過一個週期時立即發送;同一週期內呼叫多次時,只發送最後一次呼叫的完整指令。translation、rotation、interaction 是三個獨立的控制維度,未傳字段按 None 發送,SDK 不會跨呼叫合併字段,也不會週期性重復上一條指令或自動發送 None。 單次動作 跳躍、攻擊等單次觸發動作呼叫一次即可:
await travel.sendCommand({ interaction: "Jump" });
持續動作 移動、持續轉動視角等動作,按住期間應持續呼叫。前端應用無需自行按 42ms 節流,SDK 會將高頻呼叫合併為約 24FPS 的發送頻率;松開時應顯式發送一次 None 復位:
// 按住期间持续调用
void travel.sendCommand({ translation: "Front" });

// 松开时停止移动
void travel.sendCommand({ translation: "None" });
避免
  • prepare 階段大量發送
  • 用 sendCommand 發送自然語言即時導演內容

sendInstruct(即時導演指令)

必須
  • Directing(模式 2)或 角色演繹(模式 3,非 scriptlist)會話;await travel.sendInstruct({ content })
推薦
  • 發送前檢查 content 非空,防止重復提交
  • 根據返回的 accepted 等字段反饋用戶

常見問題與排障

現象

常見原因

建議處理

初始化就報參數錯誤

APIHost 傳了完整 URL,例如帶 https:// 或路徑

只傳裸 host,例如 open-platform.example.com

travel.start() 失敗,提示 ticket 無效或已使用

ticket 是一次性憑證,可能過期、重復使用,或世界還沒 ready

重新從伺服器端申請 ticket;確保世界狀態為 ready 後再進入

運行一段時間後 onError 收到鑒權錯誤

百鍊臨時 api-key token 過期

前端向業務伺服器端重新申請 token,然後呼叫 engine.updateToken(newToken)

畫面一直 loading 或 start() 超時

遠端推流未就緒、網路慢、streamReadyTimeout 太短

給用戶重試入口;必要時調大 streamReadyTimeout,並檢查伺服器端/RTC 日誌

第二次 createTravel() 報已有會話

上一次 Travel 沒有 end()

頁面切換、重試、退出時都呼叫 await travel.end() 並清理監聽

按鍵或指令沒有反應

當前狀態不是 running,或 Adventure / Directing / 角色演繹模式用錯 API

用 statusChanged 控制按鈕可用性;呼叫前用 travel.can(action) 判斷

排查問題時建議同時記錄三類資訊:SDK ErrorCode、當前 TravelStatus、業務伺服器端請求日誌。這樣基本可以判斷問題是在憑證、狀態、網路,還是渲染鏈路上。
HappyOyster Web SDK 接入指南 - Alibaba Cloud Model Studio