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;
}
| Handler | Parameters | Description |
|---|
onConnected | mediaStream: MediaStream | Called when video stream is established |
onDisconnected | - | Called when video stream is closed |
onStreamStarted | streamId: string | Called when interactive stream is ready (streamId can be used for recordings) |
onStreamEnded | - | Called when interactive stream has ended |
onInteractAcknowledged | prompt: string | Called when interaction is processed |
onStreamError | reason: string, message: string | Called on stream error (e.g., model crash) |
onError | error: Error, fatal: boolean | Called on general error |
onStatusChange | status: ConnectionStatus, message?: string | Called when connection status changes |
onBroadcastReady | info: BroadcastInfo | Called 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;
}
| Property | Type | Required | Description |
|---|
apiKey | string | Yes | Your Odyssey API key |
handlers | UseOdysseyHandlers | No | Event handlers |
Configuration
ClientConfig
Configuration for the Odyssey client constructor.
interface ClientConfig {
/** API key for authentication (required) */
apiKey: string;
}
| Property | Type | Description |
|---|
apiKey | string | API 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;
}
| Property | Type | Description |
|---|
stream_id | string | The stream ID (unique per startStream/endStream) |
video_url | string | null | Presigned URL for full recording video (MP4) |
events_url | string | null | Presigned URL for events log (JSONL) |
thumbnail_url | string | null | Presigned URL for thumbnail image (JPEG) |
preview_url | string | null | Presigned URL for preview video (MP4) |
frame_count | number | null | Total frames in recording |
duration_seconds | number | null | Recording 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;
}
| Property | Type | Description |
|---|
stream_id | string | Unique stream identifier (per startStream/endStream) |
width | number | Stream resolution width |
height | number | Stream resolution height |
started_at | string | ISO timestamp when stream started |
ended_at | string | null | ISO timestamp when stream ended |
duration_seconds | number | null | Stream duration in seconds |
ListStreamRecordingsOptions
Options for listStreamRecordings().
interface ListStreamRecordingsOptions {
limit?: number;
offset?: number;
}
| Property | Type | Default | Description |
|---|
limit | number | 50 | Maximum recordings to return (max 100) |
offset | number | 0 | Number of recordings to skip (pagination) |
StreamRecordingsListResponse
Response from listStreamRecordings().
interface StreamRecordingsListResponse {
recordings: StreamRecordingSummary[];
total: number;
limit: number;
offset: number;
}
| Property | Type | Description |
|---|
recordings | StreamRecordingSummary[] | Array of stream recording summaries |
total | number | Total recordings available |
limit | number | Limit used in request |
offset | number | Offset 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';
| Status | Description |
|---|
pending | Job is queued and waiting to start |
dispatched | Job has been dispatched to a worker |
processing | Job is currently being processed |
completed | Job finished successfully |
failed | Job encountered an error |
cancelled | Job 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)
}
| Property | Type | Description |
|---|
timestamp_ms | number | When 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;
}
| Property | Type | Description |
|---|
script | ScriptEntry[] | Single script to run (provide one of script, scripts, or script_url) |
scripts | ScriptEntry[][] | Batch mode: multiple scripts to run in a single job |
script_url | string | URL to a JSON file containing the script |
portrait | boolean | Portrait mode (default: true) |
bypassPromptExpansion | boolean | Skip 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;
}
| Property | Type | Description |
|---|
stream_id | string | Unique stream identifier |
video_url | string | null | Presigned URL for the video file (MP4) |
events_url | string | null | Presigned URL for the events log (JSONL) |
thumbnail_url | string | null | Presigned URL for the thumbnail image (JPEG) |
preview_url | string | null | Presigned URL for the preview video (MP4) |
frame_count | number | null | Total number of frames in the video |
duration_seconds | number | null | Duration of the video in seconds |
script_index | number | Index 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;
}
| Property | Type | Description |
|---|
job_id | string | Unique identifier for the job |
status | SimulationJobStatus | Current job status |
priority | string | Job priority |
created_at | string | ISO timestamp when job was created |
estimated_wait_minutes | number | null | Estimated 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[];
}
| Property | Type | Description |
|---|
job_id | string | Unique identifier for the job |
status | SimulationJobStatus | Current job status |
priority | string | Job priority |
created_at | string | ISO timestamp when job was created |
dispatched_at | string | null | ISO timestamp when job was dispatched to a worker |
started_at | string | null | ISO timestamp when processing started |
completed_at | string | null | ISO timestamp when job completed |
error_message | string | null | Error message if job failed |
assigned_region | string | null | Region where the job is being processed |
retry_count | number | Number of times the job has been retried |
streams | SimulationStream[] | 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;
}
| Property | Type | Description |
|---|
job_id | string | Unique identifier for the job |
status | SimulationJobStatus | Current job status |
priority | string | Job priority |
created_at | string | ISO timestamp when job was created |
completed_at | string | null | ISO timestamp when job completed |
error_message | string | null | Error message if job failed |
ListSimulationsOptions
Options for listSimulations().
interface ListSimulationsOptions {
status?: SimulationJobStatus;
active?: boolean;
limit?: number;
offset?: number;
}
| Property | Type | Default | Description |
|---|
status | SimulationJobStatus | — | Filter by job status |
active | boolean | — | Only show active jobs (pending/dispatched/processing) |
limit | number | 20 | Maximum jobs to return (max 100) |
offset | number | 0 | Number of jobs to skip (pagination) |
SimulationJobsList
Response from listSimulations().
interface SimulationJobsList {
jobs: SimulationJobInfo[];
total: number;
limit: number;
offset: number;
}
| Property | Type | Description |
|---|
jobs | SimulationJobInfo[] | Array of simulation job summaries |
total | number | Total jobs available |
limit | number | Limit used in request |
offset | number | Offset 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;
}
| Property | Type | Description |
|---|
prompt | string | Initial prompt to generate the stream |
portrait | boolean | True for portrait (704x1280), false for landscape (1280x704). Default: true |
image | File | Blob | Optional image for image-to-video generation |
bypassPromptExpansion | boolean | Skip prompt expansion (safety-only mode). Requires the expansion bypass privilege. |
broadcast | boolean | Enable broadcast for spectators (HLS/WebRTC). Default: false |
BroadcastInfo
Represents broadcast playback details delivered via onBroadcastReady.
interface BroadcastInfo {
webrtcUrl: string;
spectatorToken: string;
hlsUrl: string | null;
}
| Property | Type | Description |
|---|
webrtcUrl | string | WebRTC (WHEP) endpoint URL for spectator playback |
hlsUrl | string | null | HLS playlist URL for broad compatibility |
spectatorToken | string | Authentication 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:
| Fatal | Description | Action Required |
|---|
true | Connection cannot continue | Return user to connect page |
false | Recoverable error | May retry or notify user |
Common Error Messages
| Error | Description |
|---|
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 key | The provided API key is invalid (401) |
Invalid API key format... | API key format is malformed (422) |
API key access denied | The API key is valid but access is denied (403, e.g., suspended account) |
Maximum concurrent sessions (N) reached | Concurrent session quota exceeded (429) |
No available sessions | No streamers available, try again later |
Streamer not available | Assigned streamer is not responding |
Streamer disconnected | Streamer disconnected during session |
Timed out waiting for a streamer | Queue 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
| Browser | Minimum Version |
|---|
| Chrome/Edge | 90+ |
| Firefox | 88+ |
| Safari | 14.1+ |
Requires WebRTC support (RTCPeerConnection, RTCDataChannel)