# LTX Lipsync (lipsync) > LTX 2.3 turns a still image and a voice track into a short talking clip, with an optional prompt for a small camera or body motion. It is the default lipsync model of the platform. Status: roasOS API v1.1. Catalog `model-catalog@2026-10-06.v5`, pricing `customer-pricing@2026-11-05.v15`. The endpoint `POST /v1/lipsync/ltx-lipsync` is live. `POST /v1/generations` stays for one minor version as a deprecated alias (see "Today"). ## Endpoint POST https://api.roasos.com/v1/lipsync/ltx-lipsync Auth: Authorization: Bearer roasos_sk_… (scope api:write). Idempotency-Key required. quote_only / quote_id / webhook_url as in https://docs.roasos.com/llms.txt. ## Good at Short social cut-downs of 2 to 10 seconds from one image and one audio file. The prompt describes how the image moves ("a woman whispering to the microphone"). Choose it when the take is short and speed matters. It does not re-lip an existing video (use /v1/lipsync/veed-lipsync-v2) and it does not hold identity over a long take (use /v1/lipsync/kling-avatar-v2-pro when it ships). Audio limit: fal states 2–20 s and "pro models support a maximum of 10 seconds". TBD: which limit applies (spec open question 1); keep the audio at 10 s or shorter. ## Pricing Unit: second. Pricing key: `ltx-lipsync`. | request | credits | |---|---| | `10s` | 12 | Credits come from the roasOS pricing table (`MODEL_COSTS`) through the catalog. No other field changes the price. ## Modes - `image-audio-to-video` Provider endpoints: `fal-ai/ltx-2.3/audio-to-video`. ## Request fields | field | type | required | default | rule | |---|---|---|---|---| | `aspect_ratio` | enum | no | — | `auto`, `16:9`, `9:16` | | `audio_url` | string | yes | — | https URL; ≤ 4,096 characters | | `avatar_id` | string | no | — | UUID | | `guidance_scale` | number | no | — | 1–20 | | `image_url` | string | no | — | https URL; ≤ 4,096 characters | | `prompt` | string | no | — | ≥ 1 character; ≤ 5,000 characters | | `quote_id` | string | no | — | UUID | | `quote_only` | boolean | no | `false` | — | | `wait_timeout_seconds` | integer | no | `0` | 0–60 | | `webhook_url` | string | no | — | https URL; ≤ 4,096 characters | The schema is strict: a field that is not in this table returns `400 unsupported_option`. Field names are the roasOS role names, one name per role across every family. ## Media - `avatar_id` — identity; the saved character reference sheet, with a derived portrait only where the model requires a single face or source frame - `image_url` — first frame (or the single source image) - `audio_url` — the driving audio track | role | items | max size | content types | duration | |---|---|---|---|---| | `audio_url` | ≤ 1 | 15 MB | `audio/mp3`, `audio/mpeg`, `audio/wav`, `audio/wave`, `audio/x-wav` | 0–20 s | | `image_url` | ≤ 1 | 10 MB | `image/jpeg`, `image/png`, `image/webp` | — | - Refused: `elements`, `product_id`, `product_images`, `references`, `reference_images`, `end_image_url`, `scene_id`, `scene_image`, `video_urls`, `video_url`, `audio_urls`, `voice_id`. A refused role returns `400 unsupported_option`. - Every URL must be an immutable object on `https://cdn.roasos.com/…` that your workspace owns; any other URL is `400 reference_media_not_workspace_owned`. Upload with `POST /v1/uploads` (direct POST of the bytes to `put_url`, or a `source_url` import), then use the returned CDN URL. ## Prompt - Limit 5,000 characters. No wrapper is added; the prompt is sent verbatim. - Keep it short and physical: "a woman whispering to the microphone". - Describe the motion of the image, not the words; the audio carries the words. - Add one small camera move at most. ## Not exposed - `guidance_scale`: pinned to `above 20; fal accepts 1-50`. - `image_url`: pinned to `required here; fal allows a prompt-only audio-to-video call`. ## Result Result kind `lipsync`. Always present: `url`. ```json { "data": { "id": "gen_…", "kind": "lipsync", "model": "ltx-lipsync", "status": "completed", "result": {"url":"https://cdn.roasos.com/workspaces/ws_01/result"} } } ``` Files live on `https://cdn.roasos.com` and are immutable; a result URL can be a media input to the next call. Poll `GET /v1/jobs/{id}/status` → `{ id, status, updated_at }`, then `GET /v1/jobs/{id}/result` (`409 run_not_completed` until the job is `completed`, `failed` or `canceled`). Statuses: `queued → processing → completed | failed | canceled`. ## Example ```bash # 1. quote — nothing is spent curl -X POST https://api.roasos.com/v1/lipsync/ltx-lipsync \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-ltx-lipsync-0001" \ -H "Content-Type: application/json" \ -d '{"quote_only":true,"audio_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/audio_url.mp3","image_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/image_url.png"}' # → 200 { "data": { "kind": "quote", "quote_id": "q_7Hk…", "credits": 12, "expires_at": "…", "confirmation": { "model": "ltx-lipsync", "example": "10s" } } } # 2. run — the same body and the same Idempotency-Key, quote_id instead of quote_only curl -X POST https://api.roasos.com/v1/lipsync/ltx-lipsync \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-ltx-lipsync-0001" \ -H "Content-Type: application/json" \ -d '{"quote_id":"q_7Hk…","audio_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/audio_url.mp3","image_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/image_url.png"}' # → 201 { "data": { "id": "gen_…", "kind": "lipsync", "model": "ltx-lipsync", "status": "queued", "credits_reserved": 12, "links": { "status": "/v1/jobs/gen_…/status", "result": "/v1/jobs/gen_…/result" } } } # 3. poll curl https://api.roasos.com/v1/jobs/gen_…/status -H "Authorization: Bearer roasos_sk_live_…" curl https://api.roasos.com/v1/jobs/gen_…/result -H "Authorization: Bearer roasos_sk_live_…" ``` ## Today The endpoint is `POST /v1/lipsync/ltx-lipsync` with `image_url` (or `avatar_id`) and `audio_url`, plus the optional `prompt`, `guidance_scale` and `aspect_ratio`. The deprecated alias is `POST /v1/generations` `{ "type": "lipsync", "model": "ltx-lipsync", "options": { "image": "", "audio_url": "", "aspect_ratio": "9:16" } }`. On the alias the prompt is the top-level `prompt` field, `guidance_scale` is not reachable, and `avatar_id` is not accepted. ## See also https://docs.roasos.com/models/lipsync/ltx-lipsync · https://api.roasos.com/v1/catalog/lipsync/ltx-lipsync · fal-ai/ltx-2.3/audio-to-video