Skip to main content

Event Handlers

OdysseyEventHandlers

Event handlers for the Odyssey client class.
interface OdysseyEventHandlers {
  onConnected?: (mediaStream: MediaStream) => void;
  onDisconnected?: () => void;
  onStreamStarted?: (streamId: string) => void;
  onStreamEnded?: () => void;
  onInteractAcknowledged?: (prompt: string) => void;
  onStreamError?: (reason: string, message: string) => void;
  onError?: (error: Error, fatal: boolean) => void;
  onStatusChange?: (status: ConnectionStatus, message?: string) => void;
  onBroadcastReady?: (info: BroadcastInfo) => void;
}
HandlerParametersDescription
onConnectedmediaStream: MediaStreamCalled when video stream is established
onDisconnected-Called when video stream is closed
onStreamStartedstreamId: stringCalled when interactive stream is ready (streamId can be used for recordings)
onStreamEnded-Called when interactive stream has ended
onInteractAcknowledgedprompt: stringCalled when interaction is processed
onStreamErrorreason: string, message: stringCalled on stream error (e.g., model crash)
onErrorerror: Error, fatal: booleanCalled on general error
onStatusChangestatus: ConnectionStatus, message?: stringCalled when connection status changes
onBroadcastReadyinfo: BroadcastInfoCalled when broadcast is ready (spectators can watch via WHEP or HLS).

UseOdysseyHandlers

Event handlers for the useOdyssey React hook. Same interface as OdysseyEventHandlers.
type UseOdysseyHandlers = OdysseyEventHandlers;

UseOdysseyOptions

Configuration for the useOdyssey React hook.
interface UseOdysseyOptions {
  /** API key for authentication (required) */
  apiKey: string;
  /** Event handlers (optional) */
  handlers?: UseOdysseyHandlers;
}
PropertyTypeRequiredDescription
apiKeystringYesYour Odyssey API key
handlersUseOdysseyHandlersNoEvent handlers

Configuration

ClientConfig

Configuration for the Odyssey client constructor.
interface ClientConfig {
  /** API key for authentication (required) */
  apiKey: string;
}
PropertyTypeDescription
apiKeystringAPI key for authentication

Status Types

ConnectionStatus

type ConnectionStatus =
  | 'authenticating'  // Authenticating with Odyssey API
  | 'connecting'      // Connecting to streaming server
  | 'reconnecting'    // Reconnecting after disconnect
  | 'connected'       // Connected and ready
  | 'disconnected'    // Disconnected (clean)
  | 'failed';         // Connection failed (fatal)

Recording Types

Recording types were added in v1.0.0

Recording

Recording data returned from getRecording().
interface Recording {
  stream_id: string;
  video_url: string | null;
  events_url: string | null;
  thumbnail_url: string | null;
  preview_url: string | null;
  frame_count: number | null;
  duration_seconds: number | null;
}
PropertyTypeDescription
stream_idstringThe stream ID (unique per startStream/endStream)
video_urlstring | nullPresigned URL for full recording video (MP4)
events_urlstring | nullPresigned URL for events log (JSONL)
thumbnail_urlstring | nullPresigned URL for thumbnail image (JPEG)
preview_urlstring | nullPresigned URL for preview video (MP4)
frame_countnumber | nullTotal frames in recording
duration_secondsnumber | nullRecording duration in seconds
URLs are valid for a limited time (typically 1 hour).

StreamRecordingSummary

Summary of a stream recording returned in listStreamRecordings().
interface StreamRecordingSummary {
  stream_id: string;
  width: number;
  height: number;
  started_at: string;
  ended_at: string | null;
  duration_seconds: number | null;
}
PropertyTypeDescription
stream_idstringUnique stream identifier (per startStream/endStream)
widthnumberStream resolution width
heightnumberStream resolution height
started_atstringISO timestamp when stream started
ended_atstring | nullISO timestamp when stream ended
duration_secondsnumber | nullStream duration in seconds

ListStreamRecordingsOptions

Options for listStreamRecordings().
interface ListStreamRecordingsOptions {
  limit?: number;
  offset?: number;
}
PropertyTypeDefaultDescription
limitnumber50Maximum recordings to return (max 100)
offsetnumber0Number of recordings to skip (pagination)

StreamRecordingsListResponse

Response from listStreamRecordings().
interface StreamRecordingsListResponse {
  recordings: StreamRecordingSummary[];
  total: number;
  limit: number;
  offset: number;
}
PropertyTypeDescription
recordingsStreamRecordingSummary[]Array of stream recording summaries
totalnumberTotal recordings available
limitnumberLimit used in request
offsetnumberOffset used in request

Simulate API Types

Simulate API types were added in v1.0.0

SimulationJobStatus

Status of a simulation job.
type SimulationJobStatus = 'pending' | 'dispatched' | 'processing' | 'completed' | 'failed' | 'cancelled';
StatusDescription
pendingJob is queued and waiting to start
dispatchedJob has been dispatched to a worker
processingJob is currently being processed
completedJob finished successfully
failedJob encountered an error
cancelledJob was cancelled by user

ScriptEntry

An entry in a simulation script.
interface ScriptEntry {
  timestamp_ms: number;           // When this action occurs (milliseconds from start)
  start?: {                       // Begin a new stream
    prompt: string;
    image?: File | Blob | string; // Optional image for image-to-video
  };
  interact?: {                    // Send an interaction
    prompt: string;
  };
  end?: Record<string, never>;    // End the stream (empty object)
}
PropertyTypeDescription
timestamp_msnumberWhen this action occurs (milliseconds from start)
start{ prompt: string; image?: File | Blob | string }Begin a new stream with initial prompt
interact{ prompt: string }Send an interaction prompt
end{}End the current stream (empty object)

SimulateOptions

Options for simulate().
interface SimulateOptions {
  /** Single script to run */
  script?: ScriptEntry[];
  /** Batch mode: multiple scripts */
  scripts?: ScriptEntry[][];
  /** URL to script JSON file */
  script_url?: string;
  /** Portrait (true) or landscape (false). Default: true */
  portrait?: boolean;
  /** Skip prompt expansion for this job. Requires the expansion bypass privilege. */
  bypassPromptExpansion?: boolean;
}
PropertyTypeDescription
scriptScriptEntry[]Single script to run (provide one of script, scripts, or script_url)
scriptsScriptEntry[][]Batch mode: multiple scripts to run in a single job
script_urlstringURL to a JSON file containing the script
portraitbooleanPortrait mode (default: true)
bypassPromptExpansionbooleanSkip prompt expansion (safety-only mode). Requires privilege.

SimulationStream

Output stream from a simulation job, including recording artifact URLs.
interface SimulationStream {
  stream_id: string;
  video_url: string | null;
  events_url: string | null;
  thumbnail_url: string | null;
  preview_url: string | null;
  frame_count: number | null;
  duration_seconds: number | null;
  script_index: number;
}
PropertyTypeDescription
stream_idstringUnique stream identifier
video_urlstring | nullPresigned URL for the video file (MP4)
events_urlstring | nullPresigned URL for the events log (JSONL)
thumbnail_urlstring | nullPresigned URL for the thumbnail image (JPEG)
preview_urlstring | nullPresigned URL for the preview video (MP4)
frame_countnumber | nullTotal number of frames in the video
duration_secondsnumber | nullDuration of the video in seconds
script_indexnumberIndex of the script in batch mode (0 for single script)

SimulationJob

Response from simulate().
interface SimulationJob {
  job_id: string;
  status: SimulationJobStatus;
  priority: string;
  created_at: string;
  estimated_wait_minutes: number | null;
}
PropertyTypeDescription
job_idstringUnique identifier for the job
statusSimulationJobStatusCurrent job status
prioritystringJob priority
created_atstringISO timestamp when job was created
estimated_wait_minutesnumber | nullEstimated wait time in minutes

SimulationJobDetail

Detailed information about a simulation job from getSimulateStatus().
interface SimulationJobDetail {
  job_id: string;
  status: SimulationJobStatus;
  priority: string;
  created_at: string;
  dispatched_at: string | null;
  started_at: string | null;
  completed_at: string | null;
  error_message: string | null;
  assigned_region: string | null;
  retry_count: number;
  streams: SimulationStream[];
}
PropertyTypeDescription
job_idstringUnique identifier for the job
statusSimulationJobStatusCurrent job status
prioritystringJob priority
created_atstringISO timestamp when job was created
dispatched_atstring | nullISO timestamp when job was dispatched to a worker
started_atstring | nullISO timestamp when processing started
completed_atstring | nullISO timestamp when job completed
error_messagestring | nullError message if job failed
assigned_regionstring | nullRegion where the job is being processed
retry_countnumberNumber of times the job has been retried
streamsSimulationStream[]Output streams from the simulation

SimulationJobInfo

Summary information for a simulation job in a list.
interface SimulationJobInfo {
  job_id: string;
  status: SimulationJobStatus;
  priority: string;
  created_at: string;
  completed_at: string | null;
  error_message: string | null;
}
PropertyTypeDescription
job_idstringUnique identifier for the job
statusSimulationJobStatusCurrent job status
prioritystringJob priority
created_atstringISO timestamp when job was created
completed_atstring | nullISO timestamp when job completed
error_messagestring | nullError message if job failed

ListSimulationsOptions

Options for listSimulations().
interface ListSimulationsOptions {
  status?: SimulationJobStatus;
  active?: boolean;
  limit?: number;
  offset?: number;
}
PropertyTypeDefaultDescription
statusSimulationJobStatusFilter by job status
activebooleanOnly show active jobs (pending/dispatched/processing)
limitnumber20Maximum jobs to return (max 100)
offsetnumber0Number of jobs to skip (pagination)

SimulationJobsList

Response from listSimulations().
interface SimulationJobsList {
  jobs: SimulationJobInfo[];
  total: number;
  limit: number;
  offset: number;
}
PropertyTypeDescription
jobsSimulationJobInfo[]Array of simulation job summaries
totalnumberTotal jobs available
limitnumberLimit used in request
offsetnumberOffset used in request

Broadcast Types

StartStreamOptions

Options for starting a live stream.
interface StartStreamOptions {
 prompt?: string;
 portrait?: boolean;
 image?: File | Blob;
 bypassPromptExpansion?: boolean;
 broadcast?: boolean;
}
PropertyTypeDescription
promptstringInitial prompt to generate the stream
portraitbooleanTrue for portrait (704x1280), false for landscape (1280x704). Default: true
imageFile | BlobOptional image for image-to-video generation
bypassPromptExpansionbooleanSkip prompt expansion (safety-only mode). Requires the expansion bypass privilege.
broadcastbooleanEnable broadcast for spectators (HLS/WebRTC). Default: false

BroadcastInfo

Represents broadcast playback details delivered via onBroadcastReady.
interface BroadcastInfo {
 webrtcUrl: string;
 spectatorToken: string;
 hlsUrl: string | null;
}
PropertyTypeDescription
webrtcUrlstringWebRTC (WHEP) endpoint URL for spectator playback
hlsUrlstring | nullHLS playlist URL for broad compatibility
spectatorTokenstringAuthentication token for spectator access

Example: Broadcast Streamer

import { Odyssey } from "@odysseyml/odyssey";

const client = new Odyssey({ apiKey });

await client.connect({
 onBroadcastReady: ({ webrtcUrl, spectatorToken }) => {
   console.log("Share these with spectators:", webrtcUrl, spectatorToken);
 },
});

await client.startStream({
 prompt: "A floating alien temple",
 broadcast: true,
});

Example: Broadcast Spectator

const spectator = await Odyssey.connectToStream(
 webrtcUrl,
 spectatorToken
);

videoElement.srcObject = spectator.stream;

spectator.onDisconnect(() => {
 console.log("Broadcast ended");
});

Error Handling

Fatal vs Non-Fatal Errors

The onError handler receives a fatal boolean parameter:
FatalDescriptionAction Required
trueConnection cannot continueReturn user to connect page
falseRecoverable errorMay retry or notify user

Common Error Messages

ErrorDescription
Odyssey: config object is required...Constructor called without a config object
Odyssey: apiKey is required and must be a string...API key is missing, undefined, or not a string
Odyssey: apiKey cannot be empty...API key is an empty string
Invalid API keyThe provided API key is invalid (401)
Invalid API key format...API key format is malformed (422)
API key access deniedThe API key is valid but access is denied (403, e.g., suspended account)
Maximum concurrent sessions (N) reachedConcurrent session quota exceeded (429)
No available sessionsNo streamers available, try again later
Streamer not availableAssigned streamer is not responding
Streamer disconnectedStreamer disconnected during session
Timed out waiting for a streamerQueue timeout expired while waiting for a streamer

TypeScript Exports

// Main entry point (@odysseyml/odyssey)
export { Odyssey } from './odyssey';
export type { OdysseyEventHandlers, ConnectionStatus, ClientConfig, OdysseyClient } from './types';

// React entry point (@odysseyml/odyssey/react)
export { useOdyssey } from './useOdyssey';
export type { UseOdysseyHandlers, OdysseyClient } from './types';

Browser Compatibility

BrowserMinimum Version
Chrome/Edge90+
Firefox88+
Safari14.1+
Requires WebRTC support (RTCPeerConnection, RTCDataChannel)