HappyOysterEngine 負責設定 Open Platform host 與模型、更新百煉臨時 API Key token,並建立 Travel 會話。Travel 是 createTravel() 回傳的會話物件,呼叫 travel.start() 後才會進入並啟動會話。
核心名詞概念
名詞 | 含義 | 備註 |
|---|---|---|
token | 百煉臨時 api-key token:在瀏覽器、行動 App 等不可信環境中呼叫百煉模型服務時,透過安全的後端服務產生臨時 API Key,避免永久 API Key 洩露。SDK 以 HTTP Bearer 方式攜帶該 token 請求 Open Platform。 | |
ticket | HappyOyster 世界體驗憑證:第三方伺服器端透過 AK 驗證(閘道器 Header)呼叫此介面,換取一個短效期的體驗憑證( |
方法概覽
本 SDK 主要物件如下:
HappyOysterEngine
API | 描述 |
|---|---|
| 建立 Engine 執行個體。 |
| 更新後續 Open Platform API 請求使用的百煉臨時 api-key token。 |
| 建立一次 Travel 工作階段。 |
| 目前 SDK 版本號碼。 |
| 目前 SDK 套件名稱、版本和套件通道。 |
Travel
API | 描述 |
|---|---|
| 啟動目前 Travel 工作階段。 |
| 訂閱工作階段狀態變更。 |
| 訂閱首幀 URL 產生通知。 |
| 訂閱進入工作階段後即可取得的工作階段中繼資訊。 |
| 訂閱工作階段執行階段錯誤。 |
| 判斷目前是否可以呼叫指定動作。 |
| 取得已返回的會話中繼資料;尚未返回時為 |
| 傳送即時操控指令。 |
| 傳送即時導演或提示詞內容。 |
| 暫停目前工作階段。 |
| 恢復已暫停的工作階段。 |
| 將 Directing 會話回退到指定秒數。 |
| 結束目前工作階段並釋放相關資源。 |
其他匯出
匯出 | 描述 |
|---|---|
| SDK 對外公開的錯誤碼常數物件。 |
| 判斷未知錯誤是否為 SDK 標準錯誤。 |
Types |
|
範例
import { HappyOysterEngine, isSdkError } from '@happy-oyster/js-sdk'
const engine = new HappyOysterEngine({
APIHost: 'open-platform.example.com',
model: 'happyoyster-1.0-adventure', // 必填;此处以 Adventure 模型为例
token: 'bailian-temporary-api-key-token',
logLevel: 'warn',
streamReadyTimeout: 15_000,
})
const videoElement = document.getElementById('player') as HTMLVideoElement
const travel = engine.createTravel({
ticket: 'travel-ticket',
videoElement,
maxExperienceTimeSec: 90,
})
const unsubscribeStatus = travel.on('statusChanged', (status) => {
console.log('Travel status:', status)
})
const unsubscribeFirstFrame = travel.on('firstFrameGenerated', (firstFrame) => {
console.log('First frame URL:', firstFrame)
})
const unsubscribeInfo = travel.on('travelInfoReady', (info) => {
console.log('Travel info is ready before RTC playback:', info)
})
const unsubscribeError = travel.onError((error) => {
console.error('Travel error:', error)
})
try {
const { encryptedTravelId, mode, creationModel, firstFrame, maxExperienceTimeSec, aspectRatio } = await travel.start()
// Adventure(模式 1)
await travel.sendCommand({
translation: 'Front',
rotation: 'Mouse_Left',
interaction: 'Jump',
})
// Directing(模式 2)或角色演绎(模式 3;非 scriptlist)
await travel.sendInstruct({ content: '镜头转向城堡,主角开始奔跑' })
await travel.pause()
await travel.resume()
} catch (err) {
if (isSdkError(err)) {
console.error('SDK error:', err.code, err.message)
} else {
console.error('Unexpected error:', err)
}
} finally {
unsubscribeStatus()
unsubscribeFirstFrame()
unsubscribeInfo()
unsubscribeError()
await travel.end()
}
engine.updateToken('new-bailian-temporary-api-key-token')
HappyOysterEngine
HappyOysterEngine 是 Web SDK 的入口物件,用於設定 Open Platform host、維護後續請求使用的百煉臨時 api-key token,並建立 Travel 會話。
說明一個 Engine 執行個體同一時間只管理一個 active Travel(目前限制)。如果需要開始新的會話,請先結束目前的 Travel。
設定 token(建構時或透過 updateToken())後,SDK 內部會自動拉取功能開關(Feature Gate)。此能力用於遠端關閉 SDK 或強制升級舊版本;請求失敗時 SDK 會 fail-open,不阻塞正常體驗。
API | 描述 |
|---|---|
| 建立 Engine 執行個體,設定必填的 API host、模型及可選的 token 和日誌等級。 |
| 更新後續 Open Platform 請求使用的百煉臨時 api-key token。 |
| 建立一次尚未啟動的 Travel 工作階段。 |
new HappyOysterEngine
建立一個 HappyOysterEngine 執行個體。
簽章
new HappyOysterEngine(config: SDKConfig)
參數
SDKConfig
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
APIHost | string | 是 | Open Platform API host,必須是裸 host,例如 |
model | string | 是 | 要使用的 Open Platform 模型識別碼。必填,無預設值;在 Engine 建立時固定,其所有 Travel 共用此設定。 |
token | string | 否 | 建構時設定的百煉臨時 api-key token。也可之後透過 |
logLevel | LogLevel | 否 | SDK 日誌等級,預設為 |
streamReadyTimeout | number | 否 | 等待 |
model 應填寫模型識別碼,例如 Adventure 模型 happyoyster-1.0-adventure;實際值應與目標服務環境一致。SDK 不會根據體驗 mode 自動選擇模型,也不會解析 ticket 推斷模型。
一個 Engine 固定對應 APIHost + model,可複用於同一服務和模型的多次 Travel。切換任一設定前,請先結束目前的 Travel,再使用目標設定的 Engine;世界建立和 ticket 簽發也應指向同一服務目標。
傳回值
返回 HappyOysterEngine 執行個體。
錯誤
當 config 缺失,或 APIHost、model、token、logLevel、streamReadyTimeout 類型/取值不合法時,會同步擲出 SdkError,錯誤碼為 ErrorCode.INVALID_ARGUMENT(10010001)。APIHost 傳入完整 URL、空字串或帶路徑的字串都屬於非法輸入參數。
model 為必填項,必須是去除首尾空白後非空的字串;null、非字串和純空白字串均為非法值。省略或傳入 undefined 同樣會回報參數錯誤;SDK 不提供預設模型。
updateToken
更新後續 Open Platform API 請求使用的百煉臨時 api-key token。
簽章
updateToken(token: string): void
參數
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
token | string | 是 | 百煉臨時 api-key token。傳入空白字串會清空目前 token。 |
傳回值
無回傳值。
錯誤
當 token 不是字串時,會同步擲出 SdkError,錯誤碼為 ErrorCode.INVALID_ARGUMENT(10010001)。
createTravel
建立一次 Travel 會話執行個體,但不啟動會話。
簽章
createTravel(config: CreateTravelConfig): Travel
參數
CreateTravelConfig
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
ticket | string | 是 | 用於之後啟動 Travel 的 ticket。 |
videoElement | HTMLVideoElement | 是 | 用於渲染會話影片的 |
maxExperienceTimeSec | 60 | 90 | 120 | 否 | Adventure 最大體驗時間,單位為秒;Directing 和角色演繹會忽略該欄位,省略時由伺服器端使用預設值。 |
返回值
回傳已建立但尚未啟動的 Travel 會話物件。呼叫方需要再執行 await travel.start() 才會正式進入會話並等待影片可播放。
每個 HappyOysterEngine 執行個體同一時間只允許存在一個 active Travel。如需建立下一次 Travel,請先呼叫 await travel.end()。
錯誤
createTravel() 會在以下情況同步拋出 SdkError:
ErrorCode | 描述 |
|---|---|
|
|
| 目前已有進行中的 Travel,需先呼叫 |
啟動階段的錯誤由 travel.start() 暴露。
Travel
Travel 表示一次由 HappyOysterEngine.createTravel() 建立的會話。建立後會話尚未啟動,呼叫 travel.start() 後,SDK 會進入會話並等待影片可播放。
Travel 提供會話啟動、暫停、恢復、回退、結束、即時操控指令和提示詞發送能力,也提供狀態變化和執行階段錯誤訂閱。
方法
方法 | 描述 |
|---|---|
| 啟動目前 Travel 工作階段。 |
| 訂閱工作階段狀態變更。 |
| 訂閱首幀 URL 產生通知。 |
| 訂閱進入工作階段後即可取得的工作階段中繼資訊。 |
| 訂閱工作階段執行階段錯誤。 |
| 判斷目前是否可以呼叫指定動作。 |
| 取得已返回的會話中繼資料;尚未返回時為 |
| 傳送即時操控指令。 |
| 傳送即時導演或提示詞內容。 |
| 暫停目前工作階段。 |
| 恢復已暫停的工作階段。 |
| 將目前工作階段回退到指定秒數。 |
| 結束目前工作階段並釋放相關資源。 |
狀態
狀態 | 描述 |
|---|---|
| 工作階段尚未啟動。 |
| 工作階段正在啟動並等待視訊可播放。 |
| 工作階段正在執行中。 |
| 工作階段已暫停,可繼續恢復或回退。 |
| 工作階段已正常結束並釋放資源。 |
事件
透過 travel.on(event, handler) 訂閱事件。訂閱方法返回取消訂閱函式。
事件 | 回呼 | 描述 |
|---|---|---|
statusChanged | (status: TravelStatus) => void | 工作階段狀態變更。 |
firstFrameGenerated | (firstFrame: string) => void | 在 |
travelInfoReady | (info: TravelInfo) => void | enter-travel 返回後、RTC 連線前觸發。可透過 |
error | (error: unknown) => void | 工作階段執行階段錯誤。 |
Travel.can
判斷目前狀態和會話能力下是否可以呼叫指定動作。
簽章
can(action: TravelAction): boolean
參數
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
action | TravelAction | 是 | 要檢查的動作: |
傳回值
返回 boolean。true 表示目前可以呼叫該動作;false 表示目前狀態、模式或會話能力不滿足前置條件。
可用條件
action | 可用條件 |
|---|---|
| Travel 仍為 |
|
|
|
|
|
|
|
|
|
|
| Travel 未關閉。 |
錯誤
目前方法不會主動拋出業務錯誤;未知動作會返回 false。
Travel.start
啟動目前 Travel 工作階段。
簽章
start(): Promise<StartTravelResult>
參數
無參數。
返回值
返回 Promise<StartTravelResult>。Promise 在會話啟動完成、影片可播放後 resolve。
enter-travel 返回後,SDK 會在連線 RTC 前觸發 travelInfoReady。晚訂閱方可呼叫 travel.getInfo();尚未返回時為 null。若回應中包含非空 firstFrame,仍會緊隨該事件觸發 firstFrameGenerated。
StartTravelResult
欄位 | 類型 | 描述 |
|---|---|---|
encryptedTravelId | string | 目前 Travel 工作階段 ID。 |
mode | number | 會話模式: |
creationModel | string | 世界建立模型,常見值為 |
firstFrame | string | null | 首幀圖片 URL;伺服器端未返回時為 |
maxExperienceTimeSec | 60 | 90 | 120 | null | Adventure 最大體驗時間(秒);Directing、角色演繹或伺服器端未返回該欄位時為 |
aspectRatio | "9:16" | "16:9" | null | 角色演繹畫幅;其他模式或伺服器端未返回該欄位時為 |
錯誤
start() 會在以下情況 reject,並觸發 error 事件。可透過 isSdkError(err) 判斷,並讀取 err.code 與 err.message。
ErrorCode | 描述 |
|---|---|
| SDK 功能開關關閉( |
| 無法啟動:目前狀態不允許、Open Platform 未設定,或進入會話失敗 |
| 無法啟動:伺服器傳回的工作階段設定不完整 |
| 無法啟動:建立視訊串流連線失敗,或 SDK 功能開關請求失敗 |
| 無法啟動:等待影片串流就緒逾時(取 |
| 無法啟動:等待影片可播放逾時(受 |
| Open Platform 參數、資源或伺服器端錯誤 |
Travel.on("statusChanged")
訂閱工作階段狀態變更。
簽章
on("statusChanged", handler: (status: TravelStatus) => void): () => void
參數
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
handler | (status: TravelStatus) => void | 是 | 狀態變更時呼叫的回呼函式。 |
傳回值
回傳取消訂閱函式。TravelStatus 取值為 idle / prepare / running / paused / completed。
錯誤
目前方法不會主動擲回業務錯誤。
Travel.on("firstFrameGenerated")
訂閱首幀 URL 產生通知。
簽章
on("firstFrameGenerated", handler: (firstFrame: string) => void): () => void
參數
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
handler | (firstFrame: string) => void | 是 | 首幀 URL 可用時呼叫的回呼函式。 |
傳回值
返回取消訂閱函式。
行為
僅在 travel.start() 過程中觸發。SDK 呼叫 Open Platform enter-travel 並取得非空 firstFrame 後立即發出,通常發生在 statusChanged("prepare") 之後、start() resolve 和影片可播放之前。若回應未返回首幀 URL,則不會觸發。
錯誤
目前方法不會主動擲回業務錯誤。
Travel.onError
訂閱工作階段執行階段錯誤。
簽章
onError(handler: (error: unknown) => void): () => void
參數
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
handler | (error: unknown) => void | 是 | 發生執行階段錯誤時呼叫的回呼函式。 |
傳回值
返回取消訂閱函式。錯誤物件可透過 isSdkError 收窄為 SdkError。
錯誤
目前方法不會主動擲回業務錯誤。
Travel.sendCommand
傳送即時操控指令。
簽章
sendCommand(params: AdventureCommand): Promise<void>
參數
AdventureCommand
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
translation | string | 否 | 移動方向。未傳時按 |
rotation | string | 否 | 視角旋轉。未傳時按 |
interaction | string | 否 | 互動動作。未傳時按 |
控制指令參考
translation — 移動方向
描述角色的移動方向,支援 8 個方向及組合。
值 | 方向 |
|---|---|
| 前 |
| 後 |
| 左 |
| 右 |
| 左前 |
| 右前 |
| 左後 |
| 右後 |
| 靜止 |
rotation — 視角旋轉
模擬滑鼠方向的視角轉動,支援 8 個方向。
值 | 方向 |
|---|---|
| 上 |
| 下 |
| 左 |
| 右 |
| 左上 |
| 右上 |
| 左下 |
| 右下 |
| 無 |
interaction — 互動動作
值 | 動作 |
|---|---|
| 跳躍 |
| 攻擊 |
| 蹲下 |
| 衝刺 |
| 無 |
傳回值
返回 Promise<void>。指令提交完成後 resolve。
錯誤
sendCommand() 會在以下情況 reject:
ErrorCode | 描述 |
|---|---|
|
|
| 目前狀態/會話模式不允許發送指令,或視訊串流側指令發送失敗 |
Travel.sendInstruct
傳送即時導演或提示詞內容。
簽章
sendInstruct(params: InstructData): Promise<void>
參數
InstructData
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
content | string | 是 | 要傳送的提示詞內容。 |
傳回值
返回 Promise<void>。Open Platform 接收並處理完成後 resolve。
錯誤
sendInstruct() 會在以下情況 reject,並觸發 error 事件:
ErrorCode | 描述 |
|---|---|
| 工作階段尚未啟動 |
| 傳送即時導演指令失敗 |
| Open Platform 參數、資源或伺服器端錯誤 |
Travel.pause
暫停目前工作階段。
簽章
pause(): Promise<void>
參數
無參數。
傳回值
返回 Promise<void>。影片停止播放後 resolve。
錯誤
pause() 會在以下情況 reject:
ErrorCode | 描述 |
|---|---|
| 目前狀態、會話模式或會話能力不允許暫停,或暫停請求失敗 |
| 等待 backend 上報視訊串流狀態為 paused 逾時(15 秒) |
| Open Platform 參數、資源或伺服器端錯誤 |
Travel.resume
恢復已暫停的工作階段。
簽章
resume(): Promise<void>
參數
無參數。
傳回值
返回 Promise<void>。影片恢復可播放後 resolve。
錯誤
resume() 會在以下情況 reject:
ErrorCode | 描述 |
|---|---|
| 目前狀態、會話模式或會話能力不允許恢復,或恢復請求失敗 |
| 等待視訊恢復可播放逾時(15 秒) |
| Open Platform 參數、資源或伺服器端錯誤 |
Travel.rewind
將目前工作階段回退到指定秒數。
簽章
rewind(params: RewindTravelParams): Promise<RewindTravelResult>
參數
RewindTravelParams
欄位 | 類型 | 是否必填 | 描述 |
|---|---|---|---|
rewindToSec | number | 是 | 要倒轉回的秒數,僅支援 4 的整數倍(如 |
傳回值
返回 Promise<RewindTravelResult>。回退完成並恢復播放後 resolve。
RewindTravelResult
欄位 | 類型 | 描述 |
|---|---|---|
resumedAtSec | number | 伺服器實際恢復播放的秒數。 |
錯誤
rewind() 會在以下情況 reject,並觸發 error 事件:
ErrorCode | 描述 |
|---|---|
| 工作階段尚未啟動 |
| 無法回退:須先暫停且影片已停止播放,或回退請求/重連 RTC 失敗 |
| 回退後等待視訊恢復逾時(15 秒) |
| Open Platform 參數、資源或伺服器端錯誤 |
Travel.end
結束目前工作階段並釋放相關資源。
簽章
end(): Promise<void>
參數
無參數。
傳回值
返回 Promise<void>。清理流程結束後 resolve。
錯誤
清理過程中的錯誤不會向呼叫方拋出;end() 會盡量完成資源釋放。
錯誤處理
SDK 透過 Promise reject 或 error 事件公開執行階段錯誤。錯誤物件為 SdkError,可透過 isSdkError(err) 判斷,並讀取 err.code 與 err.message。
Open Platform 回傳的可識別錯誤會對應到 10000001–10000012 區間;err.message 為平台回傳的說明文字。各 Travel 方法特有的錯誤碼請參閱對應 API 的錯誤小節。
ErrorCode 一覽
錯誤碼分段約定:
100000xx:Open Platform 映射錯誤1001xxxx:Engine 用戶端錯誤1002xxxx:Travel 用戶端錯誤
code | name | 描述 |
|---|---|---|
|
| 請求參數無效(Open Platform 返回) |
|
| 資源不存在(Travel 不存在 / 不歸屬 / 跨 workspace / 產物未就緒) |
|
| 世界不存在、已刪除或不屬於目前開發者 |
|
| 系統錯誤 |
|
| ticket 無效或已過期 |
|
| ticket 已使用(一次性憑證) |
|
| 世界狀態非 ready,無法進入 |
|
| 推理資源分配失敗(席位不足、推流建立失敗、Session 初始化失敗等) |
|
| 目前介面僅允許主 API Key(臨時 API Key 不可用) |
|
| 輸入內容違規(內容安全審查攔截) |
|
| 輸入圖片版權 / IP 違規 |
|
| 請求與目前資源狀態衝突 |
|
| SDK 用戶端輸入參數驗證失敗(非 Open Platform 映射) |
|
| SDK 功能開關已關閉 |
|
| 已有進行中的 Travel |
|
| 播放中視訊串流中斷 |
|
| 啟動工作階段請求失敗 |
|
| 啟動時視訊串流設定遺失 |
|
| 視訊串流連線失敗 |
|
| 等待視訊串流就緒逾時 |
|
| 等待視訊可播放逾時 |
|
| 暫停請求失敗 |
|
| 等待視訊暫停逾時 |
|
| 恢復請求失敗 |
|
| 等待視訊恢復逾時 |
|
| 回退請求失敗 |
|
| 回退後等待視訊恢復逾時 |
|
| 傳送即時操控指令失敗 |
|
| 傳送即時導演指令失敗 |
|
| 結束工作階段請求失敗 |
其他匯出
Runtime exports
匯出 | 類型 | 描述 |
|---|---|---|
| class | SDK client,負責設定 Open Platform、更新 token 和建立 Travel。 |
| string | 目前 SDK 版本號碼。 |
| SDKMetadata | 目前 SDK 套件名稱、版本和套件通道。 |
| const | SDK 對外公開的錯誤碼常數物件。 |
| function | 判斷未知錯誤是否為 SDK 標準錯誤。 |
ErrorCode
SDK 對外公開的錯誤碼常數物件。呼叫方可以用它和 SdkError.code 進行穩定比較,避免在業務程式碼中散落數字字面量。
import { ErrorCode } from '@happy-oyster/js-sdk'
isSdkError
判斷未知錯誤是否為 SDK 標準錯誤。回傳 true 後,TypeScript 會將錯誤收窄為 SdkError,即可安全讀取 code 與 message。
isSdkError(error: unknown): error is SdkError
try {
await travel.start()
} catch (err) {
if (isSdkError(err) && err.code === ErrorCode.OPEN_PLATFORM_TICKET_INVALID) {
// Request a new Travel ticket, then create a new Travel.
}
}
公開類型
以下類型從套件入口匯出,可直接從 @happy-oyster/js-sdk 引入。它們僅在 TypeScript 編譯期存在,不會產生執行階段程式碼。
類型 | 描述 |
|---|---|
|
|
| SDK 日誌等級: |
| SDK 套件中繼資料: |
| SDK 套件通道: |
|
|
|
|
| 在 |
| 角色演繹畫幅: |
|
|
| SDK 本機會話狀態: |
|
|
|
|
|
|
|
|
|
|
| 包含 |
| 執行階段 |
|
|