Hand it one portrait image and one audio clip and you get back a video of that face speaking the audio, mouth and expression driven frame by frame. The portrait can be a real photo, an illustration or an AI-generated face; the audio can be an mp3 or a wav. An optional prompt lets you steer the delivery. Output length equals the audio length, billed at $0.02 per second, so a 10-second clip costs $0.20. It is what you want for digital-human voiceover, avatar messages and dub-to-lip-sync.
There is no duration parameter here. How long the clip runs is decided entirely by the audio_url you send, and that same length is what you are billed for. So the only lever on cost is trimming the audio down to what you actually need first: 10 seconds of audio means a 10-second video at $0.20, 60 seconds means $1.20.
| Input | What it decides | What it accepts |
|---|---|---|
| image | Who is speaking — the face that gets animated | A public image URL or a base64 data URI; real, illustrated or AI-generated portraits all work |
| audio_url | What is said and for how long — this sets both the output length and the price | A public mp3 / wav URL or a base64 data URI |
The prompt is optional — it guides the delivery and speaking style (for example "the person is talking to the camera"). Leave it out and the model still runs.
POST /api/v1/video/generations — async: create, then poll the same endpoint for the result, exactly like every other video model here.
# AI Lip-Sync — one portrait image + one audio clip -> a talking-head video.
# image and audio_url are required; prompt is optional. The output length
# follows the audio, billed $0.02 per second.
# Both image and audio_url take a public URL or a base64 data URI.
curl -X POST https://apimodels.app/api/v1/video/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "ai-lipsync",
"image": "https://example.com/portrait.png",
"audio_url": "https://example.com/voice.mp3",
"prompt": "the person is talking to the camera"
}'
# Poll the same endpoint until state == "completed".
# data.resultUrls[0] is the talking-head video. Result files are kept 7 days.
curl "https://apimodels.app/api/v1/video/generations?task_id=TASK_ID" \
-H "Authorization: Bearer YOUR_API_KEY"| Field | Required | Type | Description |
|---|---|---|---|
| model | Yes | string | Always ai-lipsync |
| image | Yes | string | Portrait image URL or data URI (the face to animate) |
| audio_url | Yes | string | Driving audio URL (mp3 / wav), data URI also accepted; the output length follows it |
| prompt | No | string | Optional — guides the delivery / speaking style |
| callback_url | No | string | Called when the task finishes, so you can skip polling |
POST to https://apimodels.app/api/v1/video/generations with model "ai-lipsync", an image (the portrait to animate) and an audio_url (the voice), then poll the same endpoint with the returned task_id. When state becomes "completed", data.resultUrls[0] is the talking-head video. A prompt such as "the person is talking to the camera" is optional and only guides the delivery. Billing is $0.02 per second of output.
$0.02 per second of output on apimodels.app, and the output is exactly as long as the audio you send — 10 seconds costs $0.20, 30 seconds $0.60, 60 seconds $1.20. Since there is no duration parameter, trimming the audio before you upload it is the only way to control the bill.
No — there is no duration parameter. The output length always equals the length of the audio passed in audio_url, and that same length is what you are billed for at $0.02 per second. Control the runtime by trimming the audio clip before sending it.
image is the portrait whose face gets animated and audio_url is the driving voice track in mp3 or wav. Both accept either a public URL or a base64 data URI. Only image and audio_url are required; prompt and callback_url are optional.
Yes. Any portrait works — a real photo, an illustration, or an AI-generated face — and the mouth and expression are driven frame by frame from the audio either way. Which face you animate is your call and your responsibility, so use portraits that are your own, licensed, or not of a real person.
Polling is the default: GET the same /api/v1/video/generations endpoint with task_id until state is "completed" (or read data.failMsg on "failed"). Pass callback_url instead and apimodels.app POSTs you when the task finishes. Result files are hosted for 7 days, so download or re-host anything you need to keep.