Loading API documentation
Start Session
The client provides a convenient way to interact with the model API.
npm install @fal-ai/client@alpha @fal-ai/server-proxy@alphafal.realtime.open is currently available on the alpha release and may change in a minor version.
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.
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/reference-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,
"reference_audio": [],
"prompt": "A traveler explores",
"dialogue_words_per_second": 2,
"reference_images": [],
"prompt_version": 1,
"resolution": "480p",
"num_inference_steps": 10,
"aspect_ratio": "16:9",
"reference_image_urls": [],
"type": "configure",
"mxfp8_ref2va_attention": false,
"reference_audio_urls": [],
"pin_audio": false,
"memory": 12
});
// Later, release the peer connection and network resources:
// await session.close();The browser connects through your server proxy, which reads FAL_KEY from the server environment. Never put that key in browser code.
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.
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.
No send media tracks.
{
"frameRate": 24
}type: "configure"payload: objectAdditional properties: not allowed
promptstring* requiredAt least 1 character · At most 50000 characters
resolutionstringDefault: "480p"
Values: "480p", "544p", "640p", "704p", "768p", "1080p", "1440p"
aspect_ratiostringDefault: "16:9"
Values: "16:9", "9:16", "1:1"
reference_images(object & object)[]Default: []
maxItems: 9
object & objectMust match all of the following:
objectAdditional properties: not allowed
namestring | nullDefault: null
At most 64 characters when not null
urlstring* requiredAt least 1 character
fidelitystring | nullVision-conditioning detail for image references: high (768px), medium (512px) or low (256px). Omitted keeps the reference's previous fidelity, or high for a new reference. Ignored for audio references.
Default: null
When not null:
Values: "high", "medium", "low"
idstring | nullDefault: null
pattern: ^ref-[1-9][0-9]*$ when not null
objecturlunknownreference_image_urlsstring[]Default: []
maxItems: 9
stringscriptobject[] | nullDefault: null
Must match at least one of the following:
object[]minItems: 1 · maxItems: 64
objectAdditional properties: not allowed
offsetnumber* requiredSeconds from the start of the first video generated under this script; fractions are allowed and quantize to the 24 fps frame grid. Text and audio placed here start at this moment. A beat carrying reference_images makes those identities available from the whole second at or before this offset, so its own prompt can show them immediately.
minimum: 0
promptstring | nullDefault: null
At least 1 character when not null · At most 50000 characters when not null
audio_urlstring | nullDefault: null
At least 1 character when not null
reference_images(object & object)[]Default: []
maxItems: 9
object & objectMust match all of the following:
objectAdditional properties: not allowed
namestring | nullDefault: null
At most 64 characters when not null
urlstring* requiredAt least 1 character
fidelitystring | nullVision-conditioning detail for image references: high (768px), medium (512px) or low (256px). Omitted keeps the reference's previous fidelity, or high for a new reference. Ignored for audio references.
Default: null
When not null:
Values: "high", "medium", "low"
idstring | nullDefault: null
pattern: ^ref-[1-9][0-9]*$ when not null
objecturlunknownnullreference_audio(object & object)[]Default: []
maxItems: 3
object & objectMust match all of the following:
objectAdditional properties: not allowed
namestring | nullDefault: null
At most 64 characters when not null
urlstring* requiredAt least 1 character
fidelitystring | nullVision-conditioning detail for image references: high (768px), medium (512px) or low (256px). Omitted keeps the reference's previous fidelity, or high for a new reference. Ignored for audio references.
Default: null
When not null:
Values: "high", "medium", "low"
idstring | nullDefault: null
pattern: ^ref-[1-9][0-9]*$ when not null
objecturlunknownreference_audio_urlsstring[]Default: []
maxItems: 3
stringpin_audiobooleanDefault: false
memoryintegerNumber of prior segment prompts retained as context for future prompt expansion.
Default: 12
minimum: 1 · maximum: 50
audio_bitrateinteger | nullSession audio target in bits/s: 96000, 128000, or 192000. Explicit values use Opus audio mode on direct WebRTC; LiveKit uses its native mode with the same bitrate target. Null preserves transport defaults (WebRTC: 96000, voip). Immutable; reconnect to compare.
Default: null
When not null:
Values: 96000, 128000, 192000
seedinteger | nullDefault: null
num_inference_stepsintegerDefault: 10
minimum: 1 · maximum: 50
mxfp8_ref2va_attentionbooleanUse MXFP8 attention for dense generation steps.
Default: false
forced_cut_max_segmentsinteger | nullMost segments in one unbroken continuation run before a forced hard cut opens a fresh shot (Ref2VA burn-in mitigation). 0 disables forced cuts; omitted keeps the deployment default. Pinned for the whole session.
Default: null
minimum: 0 when not null · maximum: 64 when not null
dialogue_words_per_secondnumberSpoken words per second of new screen time the planner budgets dialogue against. The default keeps delivery calm; raise it for deliberately fast talkers, lower it for sparser dialogue.
Default: 2
minimum: 0.5 · maximum: 6
typestring* requiredConstant: "configure"
protocol_versionintegerConstant: 1
prompt_versioninteger* requiredminimum: 1
Begin a continuous scene without references.
{
"protocol_version": 1,
"reference_audio": [],
"prompt": "A traveler explores",
"dialogue_words_per_second": 2,
"reference_images": [],
"prompt_version": 1,
"resolution": "480p",
"num_inference_steps": 10,
"aspect_ratio": "16:9",
"reference_image_urls": [],
"type": "configure",
"mxfp8_ref2va_attention": false,
"reference_audio_urls": [],
"pin_audio": false,
"memory": 12
}type: "ping"payload: objectAdditional properties: not allowed
typestring* requiredConstant: "ping"
tsnumber* required{
"type": "ping",
"ts": 0
}type: "prompt"payload: objectAdditional properties: not allowed
promptstring | nullDefault: null
At least 1 character when not null · At most 50000 characters when not null
reference_images(object & object)[] | nullDefault: null
Must match at least one of the following:
(object & object)[]maxItems: 9
object & objectMust match all of the following:
objectAdditional properties: not allowed
namestring | nullDefault: null
At most 64 characters when not null
urlstring* requiredAt least 1 character
fidelitystring | nullVision-conditioning detail for image references: high (768px), medium (512px) or low (256px). Omitted keeps the reference's previous fidelity, or high for a new reference. Ignored for audio references.
Default: null
When not null:
Values: "high", "medium", "low"
idstring | nullDefault: null
pattern: ^ref-[1-9][0-9]*$ when not null
objecturlunknownnullreference_image_urlsstring[] | nullDefault: null
Must match at least one of the following:
string[]maxItems: 9
stringnullscriptobject[] | nullDefault: null
Must match at least one of the following:
object[]minItems: 1 · maxItems: 64
objectAdditional properties: not allowed
offsetnumber* requiredSeconds from the start of the first video generated under this script; fractions are allowed and quantize to the 24 fps frame grid. Text and audio placed here start at this moment. A beat carrying reference_images makes those identities available from the whole second at or before this offset, so its own prompt can show them immediately.
minimum: 0
promptstring | nullDefault: null
At least 1 character when not null · At most 50000 characters when not null
audio_urlstring | nullDefault: null
At least 1 character when not null
reference_images(object & object)[]Default: []
maxItems: 9
object & objectMust match all of the following:
objectAdditional properties: not allowed
namestring | nullDefault: null
At most 64 characters when not null
urlstring* requiredAt least 1 character
fidelitystring | nullVision-conditioning detail for image references: high (768px), medium (512px) or low (256px). Omitted keeps the reference's previous fidelity, or high for a new reference. Ignored for audio references.
Default: null
When not null:
Values: "high", "medium", "low"
idstring | nullDefault: null
pattern: ^ref-[1-9][0-9]*$ when not null
objecturlunknownnullaudio_behaviorstring'replace' cuts to this audio at the next chunk; 'queue' appends it.
Default: "replace"
Values: "replace", "queue"
replanbooleanWhen a prompt is included: true (default) busts the planned prompt queue so the new direction applies at the next undispatched chunk; false appends the direction after the already-planned chunks.
Default: true
reference_audio(object & object)[] | nullDefault: null
Must match at least one of the following:
(object & object)[]maxItems: 3
object & objectMust match all of the following:
objectAdditional properties: not allowed
namestring | nullDefault: null
At most 64 characters when not null
urlstring* requiredAt least 1 character
fidelitystring | nullVision-conditioning detail for image references: high (768px), medium (512px) or low (256px). Omitted keeps the reference's previous fidelity, or high for a new reference. Ignored for audio references.
Default: null
When not null:
Values: "high", "medium", "low"
idstring | nullDefault: null
pattern: ^ref-[1-9][0-9]*$ when not null
objecturlunknownnullreference_audio_urlsstring[] | nullDefault: null
Must match at least one of the following:
string[]maxItems: 3
stringnulltypestring* requiredConstant: "prompt"
prompt_versioninteger* requiredminimum: 1
script_modestring'replace' cuts to the script at the next chunk; 'append' queues it.
Default: "replace"
Values: "replace", "append"
Update ref-1 after configuring Mira's arrival; replace the example URL with your asset.
{
"script_mode": "replace",
"reference_images": [
{
"url": "https://example.com/new-coat.jpg"
}
],
"type": "prompt",
"prompt_version": 2,
"audio_behavior": "replace",
"replan": true
}type: "stop"payload: objectAdditional properties: not allowed
typestring* requiredConstant: "stop"
{
"type": "stop"
}type: "audio_applied"payload: objectAn audio update was accepted; it conditions the next eligible chunk.
starts_at_chunk_index is the first chunk that can carry it (the next
undispatched chunk for replace; for queue the chunk where the
preceding sources end, if already known).
transcribedboolean* requiredremaining_secondsnumber* requiredminimum: 0
typestring* requiredConstant: "audio_applied"
behaviorstring* requiredValues: "replace", "queue"
sourcestring* requiredprompt_versioninteger* requiredminimum: 1
queued_sourcesinteger* requiredminimum: 0
duration_secondsnumber* requiredexclusiveMinimum: 0
{
"transcribed": true,
"remaining_seconds": 0,
"type": "audio_applied",
"behavior": "replace",
"source": "string",
"prompt_version": 1,
"queued_sources": 0,
"duration_seconds": 5e-324
}type: "audio_exhausted"payload: objectAccepted audio ran out inside this chunk; the rest is silence.
Later chunks continue without audio conditioning (checkpoint continuation on the same family) until new audio is accepted.
source_versioninteger | nullDefault: null
minimum: 0 when not null
chunk_indexinteger* requiredminimum: 0
silent_secondsnumber* requiredminimum: 0
typestring* requiredConstant: "audio_exhausted"
{
"chunk_index": 0,
"silent_seconds": 0,
"type": "audio_exhausted"
}type: "audio_pending"payload: objecttypestring* requiredConstant: "audio_pending"
prompt_versioninteger* requiredminimum: 1
behaviorstring* requiredValues: "replace", "queue"
{
"type": "audio_pending",
"prompt_version": 1,
"behavior": "replace"
}type: "audio_rejected"payload: objectreasonstring* requiredValues: "invalid_audio", "content_policy", "preparation_failed", "queue_full", "stale_prompt_version"
typestring* requiredConstant: "audio_rejected"
prompt_versioninteger* requiredminimum: 1
errorstring* required{
"reason": "invalid_audio",
"type": "audio_rejected",
"prompt_version": 1,
"error": "string"
}type: "chunk"payload: objectroutestring* requiredConstant: "k10-reference"
scheduling_slack_msnumber* requirednext_generation_estimate_secondsnumber* requiredminimum: 0
requested_duration_secondsinteger* requiredminimum: 5 · maximum: 15
trimmed_context_framesinteger* requiredminimum: 0
script_end_keyframeboolean | nullDefault: null
hard_cutbooleanDefault: false
native_playable_frame_countinteger | nullDefault: null
exclusiveMinimum: 0 when not null
prompt_versioninteger* requiredminimum: 1
buffer_depth_chunksinteger* requiredminimum: 0
script_offset_secondsinteger | nullDefault: null
minimum: 0 when not null
script_versioninteger | nullDefault: null
minimum: 1 when not null
typestring* requiredConstant: "chunk"
dispatchobject* requiredclassified_msnumber* requiredminimum: 0
wall_msnumber* requiredminimum: 0
phases_msobject* requiredAdditional properties: number
numberoverhead_msnumber* requiredminimum: 0
scheduling_lead_msnumber* requiredgeneration_secondsnumber* requiredminimum: 0
generated_frame_countinteger* requiredexclusiveMinimum: 0
buffer_depth_secondsnumber* requiredminimum: 0
presented_frame_countinteger | nullDefault: null
exclusiveMinimum: 0 when not null
chunk_indexinteger* requiredminimum: 0
playback_secondsnumber* requiredexclusiveMinimum: 0
{
"route": "k10-reference",
"scheduling_slack_ms": 0,
"next_generation_estimate_seconds": 0,
"requested_duration_seconds": 5,
"trimmed_context_frames": 0,
"prompt_version": 1,
"buffer_depth_chunks": 0,
"type": "chunk",
"dispatch": {
"classified_ms": 0,
"wall_ms": 0,
"phases_ms": {},
"overhead_ms": 0
},
"scheduling_lead_ms": 0,
"generation_seconds": 0,
"generated_frame_count": 1,
"buffer_depth_seconds": 0,
"chunk_index": 0,
"playback_seconds": 5e-324
}type: "chunk_metrics"payload: objectroutestring* requiredConstant: "k10-reference"
chunk_consumable_interval_msnumber | nullDefault: null
minimum: 0 when not null
typestring* requiredConstant: "chunk_metrics"
phases_msobject* requiredAdditional properties: number
numberunitsstring* requiredConstant: "ms"
gaugesobject* requiredAdditional properties: number
numberchunk_indexinteger* requiredminimum: 0
chunk_consumable_ready_msnumber | nullDefault: null
minimum: 0 when not null
{
"route": "k10-reference",
"type": "chunk_metrics",
"phases_ms": {},
"units": "ms",
"gauges": {},
"chunk_index": 0
}type: "configured"payload: objectprompt_versioninteger* requiredminimum: 1
has_initial_imageboolean | nullDefault: null
aspect_ratiostring | nullDefault: null
When not null:
Values: "16:9", "9:16", "1:1"
typestring* requiredConstant: "configured"
accelerationstring | nullDefault: null
When not null:
Values: "none", "regular"
resolutionstring | nullDefault: null
When not null:
Values: "480p", "544p", "640p", "704p", "768p", "1080p", "1440p"
enable_safety_checkerboolean* requiredmemoryinteger | nullDefault: null
minimum: 1 when not null · maximum: 50 when not null
audio_bitrateinteger | nullDefault: null
When not null:
Values: 96000, 128000, 192000
chunk_durationinteger | nullDefault: null
minimum: 5 when not null · maximum: 15 when not null
has_initial_audioboolean | nullDefault: null
{
"prompt_version": 1,
"type": "configured",
"enable_safety_checker": true
}type: "deadline_missed"payload: objectlate_by_secondsnumber* requiredminimum: 0
typestring* requiredConstant: "deadline_missed"
chunk_indexinteger* requiredminimum: 0
behaviorstring* requiredConstant: "freeze_video_and_silence_audio_until_ready"
{
"late_by_seconds": 0,
"type": "deadline_missed",
"chunk_index": 0,
"behavior": "freeze_video_and_silence_audio_until_ready"
}type: "error"payload: objectdetailobject[] | nullDefault: null
Must match at least one of the following:
object[]objectnulltypestring* requiredConstant: "error"
prompt_versioninteger | nullDefault: null
minimum: 1 when not null
codestring* requiredValues: "balance_unavailable", "content_policy", "configuration_timeout", "generation_failed", "generation_timeout", "immutable_settings", "initialization_timeout", "invalid_initial_image", "invalid_initial_audio", "invalid_initial_script", "invalid_input", "invalid_message", "not_configured", "stale_prompt_version"
errorstring* required{
"type": "error",
"code": "balance_unavailable",
"error": "string"
}type: "pong"payload: objectclient_tsnumber* requiredtypestring* requiredConstant: "pong"
{
"client_ts": 0,
"type": "pong"
}type: "prompt_applied"payload: objectA direction (or script) is admitted; the script fields report scripts.
script_origin_chunk_index is the first chunk generated under the
script when that is already fixed (a replacement binds to the next
undispatched chunk); an appended script reports None until it starts.
script_origin_chunk_indexinteger | nullDefault: null
minimum: 0 when not null
script_modestring | nullDefault: null
When not null:
Values: "replace", "append"
script_beatsinteger | nullDefault: null
minimum: 1 when not null
typestring* requiredConstant: "prompt_applied"
script_queuedinteger | nullDefault: null
minimum: 0 when not null
prompt_versioninteger* requiredminimum: 1
{
"type": "prompt_applied",
"prompt_version": 1
}type: "prompt_pending"payload: objecttypestring* requiredConstant: "prompt_pending"
prompt_versioninteger* requiredminimum: 1
{
"type": "prompt_pending",
"prompt_version": 1
}type: "prompt_rejected"payload: objectreasonstring* requiredValues: "content_policy", "preparation_failed", "stale_prompt_version", "invalid_script", "infeasible_timing", "invalid_audio", "invalid_image", "queue_full"
typestring* requiredConstant: "prompt_rejected"
prompt_versioninteger* requiredminimum: 1
errorstring | nullDefault: null
{
"reason": "content_policy",
"type": "prompt_rejected",
"prompt_version": 1
}type: "reference_state"payload: objectreferencesobject[]* requiredobjectnamestring | nullDefault: null
idstring* requiredkindstring* requiredValues: "image", "audio"
revisioninteger* requiredtypestring* requiredConstant: "reference_state"
prompt_versioninteger* required{
"references": [],
"type": "reference_state",
"prompt_version": 0
}type: "session_info"payload: objectbillable_units_per_playable_secondobjectDefault: {"704p":1.15,"544p":1.04,"640p":1.1,"1080p":1.2,"1440p":1.2,"768p":1.2,"480p":1}
Additional properties: number
numberprotocol_versionintegerConstant: 1
fpsintegerDefault: 24
appstringConstant: "minimax-h3-max-reference-director"
forced_cut_max_segmentsintegermax_chunk_durationintegerDefault: 15
resolutionsstring[]Default: ["480p","544p","640p","704p","768p","1080p","1440p"]
stringValues: "480p", "544p", "640p", "704p", "768p", "1080p", "1440p"
scriptsbooleanDefault: true
dialogue_words_per_secondnumberDefault: 2
accelerationsstring[]Default: ["none"]
stringpricing_statusstringDefault: "provisional-experiment"
one_session_per_machinebooleanDefault: true
prompt_deck_sizeintegerDefault: 6
max_session_secondsnumber | nullDefault: null
continuation_context_framesintegerDefault: 39
session_limit_scopestringDefault: "configured"
typestring* requiredConstant: "session_info"
reference_audio_modestringDefault: "sequential-content-windows"
default_pin_audiobooleanDefault: false
max_num_inference_stepsintegerDefault: 50
default_chunk_durationintegerDefault: 10
default_num_inference_stepsintegerDefault: 10
min_num_inference_stepsintegerDefault: 1
controller_machine_typestringDefault: "GPU-B300/GPU-B200 (8 GPUs)"
backend_selectionstringDefault: "resident-k10-reference"
min_chunk_durationintegerDefault: 5
default_resolutionstringDefault: "480p"
Values: "480p", "544p", "640p", "704p", "768p", "1080p", "1440p"
{
"protocol_version": 1,
"app": "minimax-h3-max-reference-director",
"type": "session_info"
}type: "session_metrics"payload: objectsession_wall_msnumber* requiredminimum: 0
history_limitinteger* requiredminimum: 1
typestring* requiredConstant: "session_metrics"
finalbooleanDefault: false
unitsstring* requiredConstant: "ms"
gaugesobject* requiredAdditional properties: number
numberhistory_sizeinteger* requiredminimum: 0
phasesobject* requiredAdditional properties: object
objectp50_msnumber* requiredminimum: 0
total_msnumber* requiredminimum: 0
p95_msnumber* requiredminimum: 0
max_msnumber* requiredminimum: 0
countinteger* requiredminimum: 0
{
"session_wall_ms": 0,
"history_limit": 1,
"type": "session_metrics",
"units": "ms",
"gauges": {},
"history_size": 0,
"phases": {}
}type: "stream_exhausted"payload: objectreasonstring* requiredValues: "stopped", "session_limit"
chunksinteger* requiredminimum: 0
typestring* requiredConstant: "stream_exhausted"
{
"reason": "stopped",
"chunks": 0,
"type": "stream_exhausted"
}