OmniHuman 2.0 is ByteDance's audio-driven avatar model: one portrait plus one driving audio clip (and an optional prompt) becomes a lip-synced video of that person talking or singing, with expressions and gestures that follow the sound. On APIMODELS it is one model id, omnihuman-2.0, on the unified video endpoint. The video is as long as the audio (4-300 seconds), framed like the portrait at roughly 720p, with no watermark by default. Billed per second of driving audio at $0.091, rounded up to the whole second.
| Driving audio | Price |
|---|---|
| Per second (rounded up to the whole second) | $0.091 |
| 4 s (minimum) | $0.364 |
| 5.36 s (billed as 6 s) | $0.546 |
| 10 s | $0.91 |
| 30 s | $2.73 |
| 60 s | $5.46 |
| 300 s (maximum) | $27.30 |
Billed seconds = the driving audio's length rounded up, measured by us when the task is created (any length you send yourself is ignored). The image, the prompt and the watermark setting do not change the price. Audio whose length cannot be read, or that falls outside 4-300 seconds, returns a 400 before anything is charged; failed generations are not charged.
All requests carry the API key in the header:
Authorization: Bearer YOUR_API_KEYhttps://api.apimodels.app/v1/video/generations·GET/v1/video/generations?task_id=# OmniHuman 2.0 — one portrait + one driving audio -> lip-synced talking video.
# image_url and audio_url are required; prompt and enable_watermark are optional.
# The video is as long as the audio; billed $0.091 per audio second, rounded up.
curl -X POST https://api.apimodels.app/v1/video/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "omnihuman-2.0",
"image_url": "https://example.com/presenter.jpg",
"audio_url": "https://example.com/voice.mp3",
"prompt": "She smiles and gestures with her right hand; slow push-in",
"enable_watermark": false
}'
# Response (async — a task is created):
# { "code": 200, "msg": "success", "data": { "taskId": "clxxx", "state": "pending", "model": "omnihuman-2.0" } }
# Poll every 10-15 s until completed (result files are kept 30 days)
curl "https://api.apimodels.app/v1/video/generations?task_id=TASK_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
# { "code": 200, "data": { "state": "completed",
# "resultUrls": ["https://r2.apimodels.app/videos/clxxx.mp4"] } }A task moves through pending → processing → completed or failed. On completed, data.resultUrls[0] is the MP4 (with your audio track); on failed, the reason is in data.failMsg and the charge is returned. In our test on 29 October 2026 a 5.36-second clip finished in about two minutes; that is one measurement, not a promise. Polling every 10-15 seconds is plenty.
To skip polling, pass callback_url in the create request. When the task reaches completed or failed we send an HTTP POST (JSON) to it. Failed deliveries are retried with backoff for up to 30 minutes, until your endpoint returns a 2xx. The URL must be publicly reachable; localhost and private addresses return a 400 at create time. Polling keeps working either way.
POST {your callback_url}
Content-Type: application/json
{
"code": 200,
"msg": "success",
"data": {
"taskId": "clxxx...",
"model": "omnihuman-2.0",
"state": "completed", // or "failed"
"param": "<JSON string>", // your request, JSON.parse once
"resultJson": "<JSON string> | null", // {"resultUrls": ["https://...mp4"]}, JSON.parse once
"failCode": null,
"failMsg": null
}
}| Field | Required | Type | Description |
|---|---|---|---|
| model | Yes | string | omnihuman-2.0 (omnihuman-2-0, omnihuman-2 and omnihuman2 also work) |
| image_url | Yes | string | The portrait, a public URL or base64 data URI; exactly one. image, or image_urls with a single item, are accepted too. |
| audio_url | Yes | string | The driving audio (speech or singing), a public URL or base64 data URI. WAV or MP3, 4-300 seconds, under 15 MB. Its length sets the video length and the price. |
| prompt | No | string | Guides gestures, emotion, posture and camera; up to 300 characters, in Chinese, English, Japanese, Korean, Mexican Spanish or Indonesian. |
| enable_watermark | No | boolean | Adds a watermark when true; default false. |
| callback_url | No | string | We POST the result to this URL on completion; omit it and poll the GET endpoint instead. |
There is no duration or resolution parameter: the length comes from the audio and the frame from the portrait. Send a vertical image for a vertical video, and trim the audio to the length you want.
Parameter problems come back synchronously as a 400 at creation ({"code": 400, "msg": "..."}): no task is created and nothing is charged. The msg strings below are the current wording (N is the actual number).
| msg | Cause / fix |
|---|---|
image_url is required: one portrait image (jpeg / png / webp, 300–6000 px per side, aspect ratio between 0.4 and 2.5) | No image was sent. Pass one portrait as image_url (or image, or image_urls with a single item). |
OmniHuman 2.0 takes exactly one image; got N | More than one image was sent. Keep a single portrait. |
audio_url is required: the driving audio (wav or mp3, 4–300 seconds, under 15 MB) | No driving audio was sent. |
Unable to read the driving audio duration — provide a publicly reachable wav or mp3 URL | We could not read the audio length: the link needs a login, has expired, or is not a readable WAV / MP3. Use a link anyone can download directly. |
driving audio is Ns — OmniHuman 2.0 needs at least 4 seconds | The audio is shorter than 4 seconds (checked on the rounded-up length). |
driving audio is Ns — OmniHuman 2.0 accepts up to 300 seconds (5 minutes) | The audio is longer than 300 seconds. Trim it, or split it into several requests. |
prompt is N characters; OmniHuman 2.0 accepts up to 300 | The prompt is longer than 300 characters. |
enable_watermark must be true or false | enable_watermark was sent as a string or number; only a boolean is accepted. |
Try it in the Playground. Use cases, worked price examples and a comparison with OmniHuman 1.5 are on the OmniHuman 2.0 model page.
$0.091 per second of driving audio, rounded up to the whole second and measured when the task is created: 5.36 seconds bills as 6 seconds, $0.546; the minimum is 4 seconds ($0.364) and the maximum 300 seconds ($27.30). Failed generations are not charged.
model (omnihuman-2.0), image_url with exactly one portrait (image or a one-item image_urls also work) and audio_url with the driving audio. prompt (up to 300 characters), enable_watermark (default false) and callback_url are optional. There is no duration or resolution field.
WAV or MP3, 4 to 300 seconds, under 15 MB, as a public URL or a base64 data URI. The length is measured when the task is created; audio we cannot read, or outside 4-300 seconds, returns a 400 before anything is charged.
Not by default. enable_watermark is false on APIMODELS unless you send true, and the setting does not change the price.
Poll GET /v1/video/generations?task_id= every 10-15 seconds until the state is completed, then read the MP4 from resultUrls, or pass callback_url and receive the finished task by POST. Result files are kept for 30 days.