Todos los productos
Search
Centro de documentos

Alibaba Cloud Model Studio:Guía de integración del Web SDK de HappyOyster

Última actualización: Oct 12, 2026

Este documento está dirigido a desarrolladores frontend y full-stack, y explica cómo integrar el Web SDK de HappyOyster de manera confiable en producción en sus modos adventure, directing y acting.

Este documento está dirigido a desarrolladores frontend y full-stack. Explica cómo integrar el SDK de manera confiable en producción. Para consultar APIs individuales, consulte la Referencia de API.

0. Ejemplo mínimo de integración

Si su backend ya ha devuelto una API key temporal de Model Studio token y un ticket de Travel, el flujo del SDK en el frontend es el siguiente:

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

Este fragmento cubre únicamente el lado del SDK. La creación del mundo, la espera hasta que esté listo, la solicitud del ticket y la solicitud de la API key temporal de Model Studio token deben realizarse en, o a través de, su backend de aplicación.

1. Descripción general del flujo de extremo a extremo

Una experiencia completa involucra principalmente a los siguientes participantes.

1.1 Participantes

Participante

Responsabilidad

Frontend de la aplicación

UI, <video>, orquestación de sesiones y llamadas al SDK

Backend de la aplicación

Almacena la API Key principal, invoca las API del mundo de Open Platform en nombre del cliente y emite credenciales temporales de Model Studio

OpenAPI de HappyOyster

Expone las API requeridas por el modelo de mundo HappyOyster.

SDK de HappyOyster

El SDK utilizado por el frontend de la aplicación. Gestiona principalmente las sesiones de Travel y el acceso a la transmisión de video en el cliente.

happy-oyster-overview.png

1.2 Flujo de experiencia

Etapa

Actor

Acción

Descripción

① Crear un mundo

Backend de la aplicación → OpenAPI de HappyOyster

POST /openapi/v1/worlds

Devuelve encryptedWorldId, status y firstFrame

② Esperar hasta que esté listo

Backend de la aplicación → OpenAPI de HappyOyster

GET /openapi/v1/worlds/build-status

Sondee hasta status === ready (omita este paso si el mundo ya está listo al crearse)

③ Obtener una credencial de Travel

Backend de la aplicación → OpenAPI de HappyOyster

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

Devuelve un ticket de un solo uso para entrar al Travel

④ Solicitar un token de clave de API temporal

Backend de la aplicación → OpenAPI de HappyOyster

POST /api/v1/tokens?expire_in_seconds=1800

Devuelve una API key temporal token. No configure una caducidad demasiado breve, ya que el token podría vencer antes de que finalice la experiencia y requerir actualizaciones frecuentes.

⑤ Entregar el token de clave de API temporal y la credencial de Travel

Frontend de la aplicación → Backend de la aplicación → Frontend de la aplicación

Solicitar una clave de API temporal y una credencial de Travel

Después de que el frontend recibe token y ticket, inicia el flujo del SDK

⑥ Ingresar a la experiencia

Frontend de la aplicación → SDK de HappyOyster

Consulte "Subflujo de inicio del SDK" a continuación

new HappyOysterEngine/updateToken → createTravel → start()

1.3 Subflujo de interacción del SDK (Etapa ⑥ ampliada)

1.3.1 Iniciar un Travel

travel-start-flow.png

Requisitos clave del orden de llamadas

Paso

API

Descripción

1

new HappyOysterEngine()

Reutilizar un Engine para el mismo APIHost + model

2

updateToken()

Complete esto antes de start()

3

createTravel()

videoElement es obligatorio

4

travel.on(...)

Registre los listeners antes de start()

5

await travel.start()

Entra en running después de un inicio exitoso

1.3.2 Reproducir en modo Aventura

adventure-command-flow.png

1.3.3 Reproducir en modo Dirección / Actuación

adventure-control-flow.png

Utilice esta tabla como modelo mental rápido para Aventura, Dirección y Actuación:

Modo

APIs principales

Uso típico

Precauciones

Aventura (1)

sendCommand()

Control en tiempo real mediante teclado, joystick y botones

Enviar solo después de running; maxExperienceTimeSec aplica únicamente a este modo

Dirección (2)

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

Dirección en lenguaje natural y control de reproducción

Pausar, reanudar y rebobinar dependen de la capacidad de la sesión; verifique primero travel.can(action)

Actuación (3)

sendInstruct(), pause(), resume()

Experiencias orientadas al rendimiento y configuración de la relación de aspecto

La pausa y la reanudación dependen de la capacidad de la sesión; rewind() no está disponible y scriptlist no puede usar sendInstruct()

1.4 Prácticas del backend de la aplicación (Resumen)

En el lado del backend, mantenga las siguientes reglas simples y estrictas:

  • Mantenga la API Key principal exclusivamente en el backend de la aplicación. El navegador debe recibir únicamente un token de corta duración (Demo: POST /server-api/temp-api-key).
  • Solicite las credenciales de Travel a través del backend. Autorice el mundo y al usuario antes de emitir ticket; no lo codifique de forma rígida ni lo almacene en caché a largo plazo en el frontend.
  • No emita una credencial hasta que el mundo esté ready. De lo contrario, la entrada a Travel puede fallar o proporcionar una experiencia incompleta.
  • Dirija el backend de la aplicación y el SDK al mismo entorno de Open Platform. El backend puede utilizar una URL completa de OpenAPI; el APIHost del SDK debe ser únicamente el host base, como open-platform.example.com.

2. Conceptos básicos del SDK

En el flujo descrito en §1, el SDK es responsable únicamente de "entrar a Travel → reproducir → controlar → finalizar". Existen dos objetos principales:

Object

Propósito

HappyOysterEngine

Configura APIHost y model, gestiona el token de API key temporal de Model Studio (updateToken) y crea sesiones de Travel

Travel

Representa una sesión: start se conecta a RTC; sendCommand, sendInstruct y los métodos de ciclo de vida controlan la sesión

Estados de la sesión (statusChanged):

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

Tres restricciones (explicadas más adelante):

  • Cada Engine puede tener solo un Travel activo a la vez.
  • Se debe proporcionar videoElement a createTravel.
  • El token de clave de API temporal de Model Studio y el ticket de Travel tienen propósitos diferentes (consulte las etapas ④–⑤ en §1.2 y §3.2).

3. Inicialización y gestión de tokens

3.1 Instanciación del Engine

Obligatorio
  • Configure APIHost como el host base de Open Platform, sin https://, esquema ni ruta, por ejemplo open-platform.example.com.
  • Reutilice un HappyOysterEngine para el mismo APIHost + model. Antes de cambiar el host o el modelo, finalice el Travel activo y utilice un Engine configurado para el nuevo destino.
Recomendado
  • Use logLevel: 'debug' en desarrollo y 'warn' o 'none' en producción.
  • Cree el Engine en la capa de orquestación de sesiones en lugar de construir uno nuevo para cada inicio.

Utilice esta tabla de referencia rápida para los campos de configuración comunes:

Campo

Obligatorio

Orientación

APIHost

Sí

Proporcione solo el host base, como open-platform.example.com; no incluya https:// ni una ruta

model

Sí

Obligatorio, sin valor predeterminado; manténgalo alineado con el modelo del backend utilizado para crear el mundo y emitir su ticket. Es fijo para el Engine y no se infiere de mode ni del ticket

token

No

Puede pasarlo en el constructor o configurarlo posteriormente con updateToken(token); también puede actualizar los tokens caducados con updateToken

logLevel

No

Use debug en desarrollo y warn o none en producción

streamReadyTimeout

No

Auméntelo si la red o la configuración de renderizado son lentos; proporcione una ruta de reintento tras el tiempo de espera

Evitar
  • Llamar repetidamente a new HappyOysterEngine() durante el renderizado o en una ruta crítica.
  • Pasar una URL completa, como una con https://, o llamar a las API del backend del SDK tras omitir APIHost.

3.2 Modelo de credenciales duales

Correspondiente a las etapas ③–⑤ en §1.2:

Credencial

Origen

Cómo configurarlo

Propósito

Token de clave de API temporal de Model Studio

Clave de corta duración emitida por el backend de la aplicación

sdk.updateToken(token)

Autentica las solicitudes del SDK ante Open Platform

Ticket de Travel

Credencial de Travel solicitada por el backend de la aplicación

createTravel({ ticket })

Credencial única para una sesión de Travel

Obligatorio
  • Prepare ambas credenciales antes de travel.start().
  • El SDK no conserva ni actualiza automáticamente el token.
Recomendado
  • Si el token caduca o se recibe un error de latido a través de onError, solicite un nuevo token mediante el backend de la aplicación e invoque updateToken.
Evitar
  • Mezclar las dos credenciales.
  • Exponer la clave de API principal al frontend de la aplicación.

4. Ciclo de vida de Travel

4.1 Crear e iniciar

Obligatorio
  • Invoque createTravel({ ticket, videoElement }); ticket es la credencial de Travel de un solo uso, y videoElement se proporciona en este punto.
  • Registre statusChanged y onError antes de await travel.start() para que siempre se observen los errores y los cambios de estado.
Recomendado
  • Muestre una interfaz de conexión durante prepare para evitar clics duplicados. Utilice travelInfoReady para leer los metadatos de la sesión anticipadamente y use firstFrameGenerated como marcador de posición del primer fotograma cuando esté disponible.
Evitar
  • Crear un Travel antes de que el elemento DOM esté listo.

4.2 Durante la ejecución

  • Controle la UI desde statusChanged: prepare significa que se está esperando el video, mientras que running significa que la interacción está disponible.
  • Observe los casos de uso y las condiciones previas para pause, resume y rewind (dependen de la capacidad de la sesión; rewind también requiere que la sesión esté paused y que la transmisión se haya detenido).

4.3 Finalizar y recrear

Obligatorio
  • Finalice la sesión con await travel.end().
  • Asegúrese de que el Travel anterior haya finalizado antes de crear uno nuevo.
  • Llame a travel.end() durante la limpieza cuando la página se descargue o cambie la ruta.
Recomendado
  • Después de un fallo, utilice "finalizar → eliminar listeners → reintentar desde la etapa ③ o ⑤ en §1.2".
  • Solicite una nueva credencial de Travel al reintentar si la credencial es de un solo uso.
Evitar
  • Llamar a createTravel una segunda vez sin finalizar el primer Travel; esto lanza una excepción síncrona.
  • Abandonar la página sin realizar la limpieza, lo que provoca fugas de recursos RTC.

5. Elemento de video y políticas del navegador

Obligatorio
  • Establezca playsInline en <video> (obligatorio en iOS).
  • Comprenda cómo las políticas de reproducción automática del navegador afectan a autoPlay y muted.
Recomendado
  • Durante prepare, muestre la imagen del primer fotograma con una superposición; ocúltela después de que la sesión entre en running.
  • Configure streamReadyTimeout según sea necesario (valor predeterminado: 15,000 ms) y proporcione una acción de reintento tras un tiempo de espera.
  • Reserve una relación de aspecto fija para el contenedor del reproductor.
Evitar
  • Pasar una referencia de elemento de video antes de que el elemento se adjunte al DOM.
  • Dejar la UI interactiva mientras la sesión está paused o la transmisión está desconectada.

6. Suscripciones a eventos y manejo de errores

6.1 Suscripciones a eventos

Obligatorio
  • Los eventos pertenecen a Travel, no a HappyOysterEngine.
  • Guarde las funciones de cancelación de suscripción devueltas por travel.on(...) y travel.onError(...).
Recomendado
  • Registre y limpie los listeners en un solo lugar. Elimine los listeners antiguos antes de cambiar de sesión de Travel.

Evento

Propósito

statusChanged

Mostrar estado, detectar disponibilidad del video (running) y habilitar o deshabilitar botones

travelInfoReady

Lea encryptedTravelId, modo, primer fotograma, duración de la experiencia y relación de aspecto de Acting antes de que se conecte RTC; travel.getInfo() devuelve los mismos datos

firstFrameGenerated

Cuando existe un primer fotograma no vacío, este sigue a travelInfoReady; utilícelo como marcador de posición durante prepare

error (a través de onError)

Registro de logs, notificaciones emergentes y activación de la renovación del token

6.2 Capas de error

  • Fallos de inicio: travel.start() rechaza la promesa (entrada al Travel / RTC / tiempo de espera).
  • Errores en tiempo de ejecución: reportados a través de travel.onError (errores RTC, fallos de autenticación de latidos, etc.).
  • Los errores del backend de la aplicación y de Open Platform en las etapas ①–④ de §1.2 son gestionados por la capa de aplicación y no ingresan al SDK.
Evitar
  • Capturar solo start() sin escuchar onError.
  • Registrar listeners repetidamente sin cancelar la suscripción.

7. Envío de instrucciones: Command e Instruct

7.1 sendCommand (Control en tiempo real)

sendCommand() proporciona control en tiempo real en el modo Adventure (1). Envía comandos a través del DataChannel de RTC y solo está disponible mientras la sesión está running.

El SDK envía como máximo un comando aproximadamente cada 42 ms (alrededor de 24 FPS). Si ha transcurrido un ciclo desde el envío anterior, envía el nuevo comando inmediatamente. Si se invoca sendCommand() varias veces dentro del mismo ciclo, solo se envía el comando completo de la última llamada. translation, rotation y interaction son dimensiones de control independientes. Los campos omitidos se envían como None; el SDK no combina campos entre llamadas, no repite periódicamente el comando anterior ni envía automáticamente None.

Acciones únicas

Llame a sendCommand() una vez para acciones puntuales como saltar o atacar:

await travel.sendCommand({ interaction: "Jump" });
Acciones continuas

Continúe invocando sendCommand() mientras se mantenga presionado un control de movimiento o de rotación continua de la vista. La aplicación frontend no necesita limitar las llamadas a 42 ms; el SDK consolida las llamadas de alta frecuencia en una tasa de salida de aproximadamente 24 FPS. Al soltar, envíe explícitamente None para restablecer el control:

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

// Stop moving on release
void travel.sendCommand({ translation: "None" });
Evitar
  • Enviar muchos comandos durante prepare.
  • Usar sendCommand para instrucciones de dirección en lenguaje natural.

7.2 sendInstruct (Instrucciones de dirección)

Obligatorio
  • una sesión de Dirección (2) o una sesión de Actuación (3) que no sea scriptlist; llame a await travel.sendInstruct({ content }).
Recomendado
  • Verifique que content no esté vacío antes de enviar y evite envíos duplicados.
  • Proporcione retroalimentación al usuario basada en los campos devueltos, como accepted.

8. Solución de problemas

Síntoma

Causa común

Qué hacer

La inicialización del SDK falla con un error de argumento

APIHost se pasó como una URL completa, por ejemplo con https:// o una ruta

Pase solo el host base, como open-platform.example.com

travel.start() falla porque el ticket es inválido o ya fue utilizado

ticket es de un solo uso; puede haber caducado, haber sido reutilizado o emitido antes de que el mundo estuviera listo

Solicite un nuevo ticket al backend; asegúrese de que el mundo esté listo antes de entrar

onError reporta un error de autenticación después de que la sesión ha estado en ejecución

El token de clave de API temporal de Model Studio ha caducado

Solicite un nuevo token a su backend y luego llame a engine.updateToken(newToken)

El reproductor sigue cargando o start() agota el tiempo de espera

La transmisión remota no está lista, la red es lenta o streamReadyTimeout es demasiado corto

Proporcione una acción de reintento; aumente streamReadyTimeout si es necesario; revise los registros del backend y de RTC

Una segunda llamada a createTravel() falla porque ya existe un Travel activo

El Travel anterior no finalizó

Llame a await travel.end() y limpie los listeners al salir, reintentar o cambiar de sesión

Los controles o instrucciones no tienen efecto

La sesión no está running, o se utiliza la API incorrecta para el modo actual de Aventura, Dirección o Actuación

Determine la disponibilidad de los botones desde statusChanged; llame a travel.can(action) antes de realizar acciones sensibles al modo

Al depurar, registre tres elementos conjuntamente: el ErrorCode del SDK, el TravelStatus actual y los registros de solicitudes del backend. Esto generalmente indica si el problema está relacionado con credenciales, estado, red o renderizado.