Videos
Talking-head videos
One continuous shot of your character presenting to camera — the workhorse format for updates, promos, and UGC-style ads. Up to 59 seconds, vertical, studio lipsync always on, ready to post.
How a job runs
POST /videos with mode: "talking_head" queues an async job and returns immediately. The workflow then: plans the shot from your video_idea (or takes your ready-made first frame) → gets the speech audio (synthesized from your script, or your uploaded audio) → renders the character speaking it → runs the studio lipsync pass (always — there's no tier to pick) → burns in captions if you asked for them. You poll the job until it hands you a video_url.
The request
| Field | Type | Description |
|---|---|---|
| mode | "talking_head" required | Or "scenes" — see Multi-scene videos. |
| character_id | uuid required | Who is on camera. |
| voice_id + script | strings | Audio source A — the job runs TTS on script with your voice. Spoken verbatim, never trimmed. |
| audio_url | https url | Audio source B — pre-recorded speech (yours or from POST /tts). Provide exactly one source: A or B, never both. Duration is probed server-side automatically. |
| video_idea | string ≤2000 | The scene to stage ("standing in a bright modern kitchen…"). Required unless first_frame_url is given. |
| first_frame_url | https url | Skip scene planning and animate exactly this still — usually one you made via first-frame images. |
| resolution | "480p" | "720p" | Default 480p. 720p costs ~2× per second on the render line. |
| use_dynamic_captions | boolean | Burn in dynamic captions (bold, word-by-word, on a solid legible band). Omit or false for none. Flat 10 credits — see below. |
| captions_language | string | Optional speech language for the captions, e.g. "en" or "ar". Omit to auto-detect. Latin and Arabic scripts both render correctly. |
| captions_position | "top" | "bottom" | Which edge the caption band sits on. Default "bottom". Use it to keep captions off your subject — see below. |
Every talking-head gets the studio lipsync pass — the best mouths we can produce, no knob to turn. It's included in the price below (~13.4 credits/second). If an older integration still sends a lipsync field, it's silently ignored.
Dynamic captions
Set use_dynamic_captions: true to burn in dynamic captions — big, bold captions that reveal word by word as your character speaks, with the key words popped in colour for emphasis. They render in a heavy weight on a solid background band, so they stay readable over any footage, and cover both Latin and Arabic scripts (pass captions_language: "ar" for Arabic). Flat 10 credits, quoted and charged like every other line item.
The captions sit in a band at the bottom of the frame by default, and emphasized words pop larger toward the centre. So when you pick or generate the shot, leave room for them: keep the speaker's face in the upper-to-middle of the frame and don't put anything you can't cover along the bottom edge. If your composition needs the bottom clear instead, move the band up with captions_position: "top" and keep the top clear. When you build the opening still on first-frame images, frame it with that clear strip in mind.
The 59-second cap
Over-length input is rejected with 400 at queue time — an over-long script (estimated) or audio_url (measured) never starts a job or touches your balance. Scripts that estimate under the cap but measure over it after TTS fail the job with a full refund. Rule of thumb: ~140 spoken words ≈ 55s — keep scripts under that.
What it costs
Line items sum: render seconds × rate, the always-on studio lipsync at ~13.4/s, plus speech synthesis (when using a script), a first frame (when the job generates one), and captions if chosen. Two worked examples for a 30-second script:
| Line item | Everyday clip (480p) | Hero clip (720p + captions) |
|---|---|---|
| Render (30s) | 240 | 450 |
| Studio lipsync (30s, always on) | 400 | 400 |
| TTS (script ≤1k chars) | 10 | 10 |
| First frame (generated) | 6 | 6 |
| Dynamic captions | — | 10 |
| Total | 656 credits | 876 credits |
Don't do this math yourself — POST /videos/estimate quotes any request exactly, for free, before you commit. The exact estimate is reserved at queue time (credits_reserved) and settles to the measured actual on completion — how billing settles.
Quote it, then queue it
curl -X POST https://platform.promoat.ai/api/partner/v1/videos/estimate \
-H "Authorization: Bearer $PROMOAT_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "talking_head",
"character_id": "CHARACTER_ID",
"voice_id": "VOICE_ID",
"script": "Hi! Three quick updates from the shop this week…",
"video_idea": "standing in a bright modern kitchen, smiling at the camera",
"resolution": "720p",
"use_dynamic_captions": true
}'
# → { "credits_required": 290, "credits_balance": 961, "sufficient_credits": true,
# "estimated_seconds": 7.4,
# "breakdown": { "render_credits": 111, "lipsync_credits": 99, "tts_credits": 10,
# "first_frame_credits": 6, "captions_credits": 10 } }curl -X POST https://platform.promoat.ai/api/partner/v1/videos \
-H "Authorization: Bearer $PROMOAT_KEY" \
-H "Content-Type: application/json" \
-d '{ ...same body... }'
# → { "workflow_id": "partner_thv_1783…", "status": "queued", "credits_reserved": 290 }curl https://platform.promoat.ai/api/partner/v1/jobs/partner_thv_1783…/status \
-H "Authorization: Bearer $PROMOAT_KEY"
# → { "status": "completed",
# "video_url": "https://…/final.mp4",
# "credits_consumed": 284, … }Typical wall-clock: 4–8 minutes for a 480p clip (the lipsync pass is part of every run). Up to 5 jobs can run at once (429 beyond that).
The other two audio/frame sources
Instead of voice_id + script, drop in pre-recorded audio; instead of video_idea, drop in a ready-made frame:
curl -X POST https://platform.promoat.ai/api/partner/v1/videos \
-H "Authorization: Bearer $PROMOAT_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "talking_head",
"character_id": "CHARACTER_ID",
"audio_url": "https://your-cdn.com/audio/narration.mp3",
"first_frame_url": "https://your-cdn.com/frames/opening-shot.jpg",
"resolution": "720p",
"use_dynamic_captions": true
}'