Introduction
P-Video 2 Pro Talking avatar takes a portrait (image_url) and a recording of speech or singing (audio_url) and returns a clip of that person delivering it, with the mouth, face and head moving to the audio. Your recording becomes the soundtrack. There is no duration field: the audio sets the length, anywhere from 1 to 180 seconds. An optional prompt directs movement, expression and framing, and nothing is filtered.
Choose a P-Video 2 Pro mode by starting material
| P-Video 2 Pro inputs | Generation mode |
|---|---|
| a written scene or script | P-Video 2 Pro Text to video |
| an opening frame, and optionally a closing frame | P-Video 2 Pro Image to video |
| a clip to borrow motion from, or a voice or music track | P-Video 2 Pro Reference to video |
| a portrait and a recording for that person to say | P-Video 2 Pro Talking avatar (you are here) |
Key features & highlights
Your recording drives the clip
The finished file matched the audio to within a few hundredths of a second in our runs: 4.55 seconds of audio came back as a 4.58-second clip, 4.8 seconds as 4.83, 5.21 as 5.25. Trim the recording to the length you want before you send it.
Two resolutions, the portrait's shape
Pick 480p or 768p. Pruna documents that the output takes the aspect ratio of the portrait, and our 16:9 portraits came back at 832x480 and 1344x768.
Quick turnaround
Our five-second test clips took 27 to 39 seconds from submit to finished file, at either resolution.
No content filter
SpicyAPI adds no filter on the portrait, the prompt or the result. In our tests a NSFW direction rendered as written at 480p.
Request parameters
| Parameter | Required | Description |
|---|---|---|
prompt | No | Optional. Gestures, expression, where the eyes go and camera movement. |
image_url | Yes | The portrait that speaks, JPEG, PNG or WebP. One clear face works best; the clip keeps the image's aspect ratio. |
audio_url | Yes | Speech or singing, MP3 or WAV, 1 to 180 seconds. It sets the clip length and the price, and it is kept as the soundtrack. |
resolution | No | 480p or 768p (default 768p). 768p costs more per second. |
enable_prompt_expansion | No | Off by default, so your direction is used as written. Turn it on to have it rewritten into a fuller one first; this does not change the price. Default: |
seed | No | Fix the random starting state to compare two runs with the same portrait and audio; it does not promise frame-identical output. |
Pricing
Billed per second of the input audio, rounded up to a whole second, from 1 to 180 seconds; 768p costs more per second than 480p. The hold follows the audio length (or the 180-second maximum when it cannot be read) and the difference is released on delivery. Prompt expansion and seed do not change the price. A failed request is not charged.
| Specification | Price |
|---|---|
| $0.02 / second |
| $0.04 / second |
Use cases
Presenter and explainer clips
Record a script once, pair it with a headshot and get a host who reads it to camera, for course intros, product walk-throughs or announcements.
Character voices
Give a character portrait the line a voice actor or a text-to-speech model recorded, and keep the same face across a series of short clips.
Localised versions
Run the same portrait with the recording in each language you publish in; every clip lip-syncs to its own track.
Prompt guide & pro tips
Direct the delivery, not the look
The portrait already fixes the face, outfit and room. Use the prompt for small beats: a lean toward the microphone, raised eyebrows on a key phrase, a hand drifting to the collar, a slow push-in.
The prompt can move the scene
A prompt that describes a different place or outfit from the portrait can override it: in one of our runs the setting changed to match the text. Leave the background out of the prompt when the portrait should stay as it is.
Expansion is off by default
enable_prompt_expansion lets the service rewrite your direction into a fuller one before generating. It does not change the price, but the result can drift from your wording.
API quick start
# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-d '{
"model": "pruna-ai/p-video-2-pro/talking-avatar",
"input": {
"audio_url": "https://example.com/reference.mp3",
"image_url": "https://example.com/reference.png",
"prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
"resolution": "768p"
}
}'
# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"
See the API reference for authentication, the complete schema, polling, and error handling.



