About
Start Session
1. Calling the API#
Install the client#
The client provides a convenient way to interact with the model API.
npm install @fal-ai/client@alpha @fal-ai/server-proxy@alphaExperimental realtime API
fal.realtime.open is currently available on the alpha release and may change in a minor version.
Set up the server proxy#
Keep FAL_KEY on your server and expose an authenticated proxy route to your browser. For a Next.js App Router application, create app/api/fal/proxy/route.ts:
import { route } from "@fal-ai/server-proxy/nextjs";
export const { GET, POST, PUT } = route;Set FAL_KEY in the server environment, and protect this route with your application's authentication before deploying it.
Real-time via WebRTC#
This deployment publishes a WMA WebRTC contract. The example uses fal.realtime.open; its media handlers, capture constraints, and control message are generated from the linked AsyncAPI document.
import { createFalClient } from "@fal-ai/client";
import { wma } from "@fal-ai/client/realtime";
const fal = createFalClient({ proxyUrl: "/api/fal/proxy" });
const session = fal.realtime.open(wma("minimax/h3-max/director"), {
receive: [
"video",
"audio"
],
onMedia: (stream) => {
const element = document.querySelector("video");
if (element) element.srcObject = stream;
},
onData: (raw) => {
const message = JSON.parse(raw);
console.log(message);
},
onState: (state) => console.log("realtime:", state),
onError: (error) => console.error(error),
});
// Send any client message described below.
session.send({
"protocol_version": 1,
"prompt": "A continuous original live-action stream following a group of friends as they explore a new city.",
"type": "configure",
"prompt_version": 1
});
// Later, release the peer connection and network resources:
// await session.close();2. Authentication#
The browser connects through your server proxy, which reads FAL_KEY from the server environment. Never put that key in browser code.
API Key#
Protect your API Key
When running code on the client-side (e.g. in a browser, mobile app or GUI applications), make sure to not expose your FAL_KEY. Instead, use a server-side proxy to make requests to the API. For more information, check out our server-side integration guide.
3. Schema#
Media#
Client contract for the WebRTC session created by the linked OpenAPI operation.
Tracks are described from the browser's perspective. Send tracks are captured by the browser and sent to the model; receive tracks come back from the model.
Send
No send media tracks.
Receive
{
"frameRate": 24
}Client messages#
Client configure message
type: "configure"payload: objectAdditional properties: not allowed
memoryintegerNumber of prior segment prompts retained as context for future prompt expansion.
Default: 12
minimum: 1 · maximum: 50
protocol_versionintegerConstant: 1
promptstring* requiredminLength: 1 · maxLength: 50000
seedinteger | nullDefault: null
typestring* requiredConstant: "configure"
resolutionstringDefault: "768p"
Values: "480p", "768p"
aspect_ratiostringDefault: "16:9"
Values: "16:9", "9:16", "1:1"
prompt_versioninteger* requiredminimum: 1
{
"protocol_version": 1,
"prompt": "A continuous original live-action stream following a group of friends as they explore a new city.",
"type": "configure",
"prompt_version": 1
}Client ping message
type: "ping"payload: objectAdditional properties: not allowed
typestring* requiredConstant: "ping"
tsnumber* required{
"type": "ping",
"ts": 0
}Client prompt message
type: "prompt"payload: objectAdditional properties: not allowed
promptstring* requiredminLength: 1 · maxLength: 50000
prompt_versioninteger* requiredminimum: 1
typestring* requiredConstant: "prompt"
{
"prompt": "string",
"prompt_version": 1,
"type": "prompt"
}Client stop message
type: "stop"payload: objectAdditional properties: not allowed
typestring* requiredConstant: "stop"
{
"type": "stop"
}Server messages#
Server chunk message
type: "chunk"payload: objectbuffer_depth_secondsnumber* requiredminimum: 0
scheduling_lead_msnumber* requiredplayback_secondsnumber* requiredexclusiveMinimum: 0
routestring* requiredValues: "gorgonea", "betelgeuse", "regulus", "unknown"
typestring* requiredConstant: "chunk"
prompt_versioninteger* requiredminimum: 1
dispatchobject* requiredphases_msobject* requiredAdditional properties: number
numberoverhead_msnumber* requiredminimum: 0
wall_msnumber* requiredminimum: 0
classified_msnumber* requiredminimum: 0
chunk_indexinteger* requiredminimum: 0
next_generation_estimate_secondsnumber* requiredminimum: 0
generation_secondsnumber* requiredminimum: 0
requested_duration_secondsinteger* requiredminimum: 5 · maximum: 15
scheduling_slack_msnumber* requiredtrimmed_context_framesinteger* requiredminimum: 0
buffer_depth_chunksinteger* requiredminimum: 0
generated_frame_countinteger* requiredexclusiveMinimum: 0
{
"buffer_depth_seconds": 0,
"scheduling_lead_ms": 0,
"playback_seconds": 5e-324,
"route": "gorgonea",
"type": "chunk",
"prompt_version": 1,
"dispatch": {
"phases_ms": {},
"overhead_ms": 0,
"wall_ms": 0,
"classified_ms": 0
},
"chunk_index": 0,
"next_generation_estimate_seconds": 0,
"generation_seconds": 0,
"requested_duration_seconds": 5,
"scheduling_slack_ms": 0,
"trimmed_context_frames": 0,
"buffer_depth_chunks": 0,
"generated_frame_count": 1
}Server chunk_metrics message
type: "chunk_metrics"payload: objectchunk_indexinteger* requiredminimum: 0
phases_msobject* requiredAdditional properties: number
numbergaugesobject* requiredAdditional properties: number
numberunitsstring* requiredConstant: "ms"
routestring* requiredValues: "gorgonea", "betelgeuse", "regulus", "unknown"
typestring* requiredConstant: "chunk_metrics"
chunk_consumable_ready_msnumber | nullDefault: null
numberminimum: 0
nullchunk_consumable_interval_msnumber | nullDefault: null
numberminimum: 0
null{
"chunk_index": 0,
"phases_ms": {},
"gauges": {},
"units": "ms",
"route": "gorgonea",
"type": "chunk_metrics"
}Server configured message
type: "configured"payload: objectmemoryinteger | nullDefault: null
integerminimum: 1 · maximum: 50
nullchunk_durationinteger | nullDefault: null
integerminimum: 5 · maximum: 15
nullaccelerationstring | nullDefault: null
stringValues: "none", "regular"
nulltypestring* requiredConstant: "configured"
has_initial_imageboolean | nullDefault: null
enable_safety_checkerboolean* requiredresolutionstring | string | nullDefault: null
stringValues: "480p", "544p", "640p", "704p", "768p"
stringValues: "480p", "768p"
nullprompt_versioninteger* requiredminimum: 1
aspect_ratiostring | nullDefault: null
stringValues: "16:9", "9:16", "1:1"
null{
"type": "configured",
"enable_safety_checker": true,
"prompt_version": 1
}Server deadline_missed message
type: "deadline_missed"payload: objectbehaviorstring* requiredConstant: "freeze_video_and_silence_audio_until_ready"
chunk_indexinteger* requiredminimum: 0
typestring* requiredConstant: "deadline_missed"
late_by_secondsnumber* requiredminimum: 0
{
"behavior": "freeze_video_and_silence_audio_until_ready",
"chunk_index": 0,
"type": "deadline_missed",
"late_by_seconds": 0
}Server error message
type: "error"payload: objectdetailobject[] | nullDefault: null
object[]objectnullcodestring* requiredValues: "content_policy", "configuration_timeout", "generation_failed", "generation_timeout", "immutable_settings", "initialization_timeout", "invalid_initial_image", "invalid_message", "not_configured", "stale_prompt_version"
prompt_versioninteger | nullDefault: null
integerminimum: 1
nulltypestring* requiredConstant: "error"
errorstring* required{
"code": "content_policy",
"type": "error",
"error": "string"
}Server pong message
type: "pong"payload: objectclient_tsnumber* requiredtypestring* requiredConstant: "pong"
{
"client_ts": 0,
"type": "pong"
}Server prompt_applied message
type: "prompt_applied"payload: objectprompt_versioninteger* requiredminimum: 1
typestring* requiredConstant: "prompt_applied"
{
"prompt_version": 1,
"type": "prompt_applied"
}Server prompt_pending message
type: "prompt_pending"payload: objectprompt_versioninteger* requiredminimum: 1
typestring* requiredConstant: "prompt_pending"
{
"prompt_version": 1,
"type": "prompt_pending"
}Server prompt_rejected message
type: "prompt_rejected"payload: objectreasonstring* requiredConstant: "content_policy"
prompt_versioninteger* requiredminimum: 1
typestring* requiredConstant: "prompt_rejected"
{
"reason": "content_policy",
"prompt_version": 1,
"type": "prompt_rejected"
}Server session_info message
type: "session_info"payload: objectprotocol_versionintegerConstant: 1
prompt_deck_sizeintegerConstant: 3
chunk_secondsintegerConstant: 10
min_chunk_durationintegerConstant: 5
resolutionsstring[]Default: ["480p","768p"]
stringValues: "480p", "768p"
server_message_typesstring[]Default: ["chunk","chunk_metrics","configured","deadline_missed","error","pong","prompt_applied","prompt_pending","prompt_rejected","session_info","session_metrics","stream_exhausted"]
stringValues: "chunk", "chunk_metrics", "configured", "deadline_missed", "error", "pong", "prompt_applied", "prompt_pending", "prompt_rejected", "session_info", "session_metrics", "stream_exhausted"
appstringConstant: "minimax-h3-max-director"
accelerationsstring[]Default: ["none","regular"]
stringValues: "none", "regular"
typestring* requiredConstant: "session_info"
continuation_playback_secondsnumberDefault: 8.5
client_message_typesstring[]Default: ["configure","ping","prompt","stop"]
stringValues: "configure", "ping", "prompt", "stop"
default_memoryintegerConstant: 12
max_chunk_durationintegerConstant: 15
continuation_context_framesintegerConstant: 39
prompt_expanderstringConstant: "fast"
default_chunk_durationintegerConstant: 10
controller_machine_typestringConstant: "XL"
backend_selectionstringConstant: "minimax-h3-turbo-balancer"
default_accelerationstringConstant: "regular"
max_memoryintegerConstant: 50
min_memoryintegerConstant: 1
audio_sample_rateintegerConstant: 32000
prompt_context_segmentsintegerConstant: 12
one_session_per_machinebooleanConstant: true
aspect_ratiosstring[]Default: ["16:9","9:16","1:1"]
stringValues: "16:9", "9:16", "1:1"
fpsintegerConstant: 24
max_session_secondsnumber | nullDefault: null
{
"protocol_version": 1,
"prompt_deck_size": 3,
"chunk_seconds": 10,
"min_chunk_duration": 5,
"app": "minimax-h3-max-director",
"type": "session_info",
"default_memory": 12,
"max_chunk_duration": 15,
"continuation_context_frames": 39,
"prompt_expander": "fast",
"default_chunk_duration": 10,
"controller_machine_type": "XL",
"backend_selection": "minimax-h3-turbo-balancer",
"default_acceleration": "regular",
"max_memory": 50,
"min_memory": 1,
"audio_sample_rate": 32000,
"prompt_context_segments": 12,
"one_session_per_machine": true,
"fps": 24
}Server session_metrics message
type: "session_metrics"payload: objectfinalbooleanDefault: false
gaugesobject* requiredAdditional properties: number
numberunitsstring* requiredConstant: "ms"
history_sizeinteger* requiredminimum: 0
typestring* requiredConstant: "session_metrics"
history_limitinteger* requiredminimum: 1
session_wall_msnumber* requiredminimum: 0
phasesobject* requiredAdditional properties: object
objectp50_msnumber* requiredminimum: 0
total_msnumber* requiredminimum: 0
max_msnumber* requiredminimum: 0
p95_msnumber* requiredminimum: 0
countinteger* requiredminimum: 0
{
"gauges": {},
"units": "ms",
"history_size": 0,
"type": "session_metrics",
"history_limit": 1,
"session_wall_ms": 0,
"phases": {}
}Server stream_exhausted message
type: "stream_exhausted"payload: objectreasonstring* requiredValues: "stopped", "session_limit"
chunksinteger* requiredminimum: 0
typestring* requiredConstant: "stream_exhausted"
{
"reason": "stopped",
"chunks": 0,
"type": "stream_exhausted"
}