ModelsPrunaAIp-video-avatar
providerPrunaAI /

p-video-avatar

15.75 DZD/ second

P-Video-Avatar does one thing and does it fast: it makes a still portrait speak. Give it a single image and either a script or an audio track, and it returns a lip-synced video of that person delivering the words — with body movement, expression, and a background that behaves. Speech can come from your own recording or from thirty built-in voices across ten languages, so a script-to-video pipeline needs no external text-to-speech step. Output follows the aspect ratio of the input image, which makes the same portrait serve both a landscape hero cut and a vertical social clip. It is built for volume: ad variants, localized support explainers, and education segments where one approved face has to say many different things.

PublicVideoAudioAvatarLipSyncTTS1080p
p-video-avatar
ArchitectureProprietary
Context Windowvideo

P-Video-Avatar

Pruna AI's avatar model. It turns a single portrait image into a speaking video — lip-synced, with body movement and expression.

It is narrow on purpose. It does not generate scenes, retarget motion from a driver clip, or edit existing footage. It makes a still talk, and it is built to do that at production volume.


⚠️ Safety Filtering Is Off by Default

disable_safety_filter defaults to true. Prompt and image safety checks are disabled unless you turn them on.

This is the reverse of most generation APIs, and it matters more here than it would elsewhere. This model takes an arbitrary portrait and makes it say an arbitrary script. Deployed with the default and without your own controls, that is a tool for putting words in someone's mouth.

Pruna's own guidance is to keep the default behaviour only where you have an explicit moderated workflow. If you do not have one:

JSON
{ "disable_safety_filter": false }

Regardless of this setting, you remain responsible for the likeness you upload. Pruna states it directly: respect the copyright of the images you use as input, and of the speech and video you generate. A portrait of a real person requires that person's consent, and no API parameter supplies it.


How It Works

You give the model two things.

A portrait image — required. This is the first frame, and it determines identity, framing, and aspect ratio. Formats: jpg, jpeg, png, webp.

Words — either a script for the built-in voices, or an audio file to lip-sync against. If both are supplied, the audio wins and the script is ignored.

Everything else shapes the result rather than defining it.


Parameters

Required

ParameterTypeDescription
imagefile / URLFirst frame. jpg, jpeg, png, webp. Determines identity and aspect ratio.

Plus either voice_script or audio.

Optional

ParameterDefaultDescription
audio—Audio track driving speech and timing. Overrides voice_script.
voice_script""What the avatar says, when no audio is supplied.
voiceZephyr (Female)Which built-in voice speaks.
voice_languageEnglish (US)Output language for generated speech.
voice_promptSay the following.How it is said — tone, pace, energy. Not the words.
video_promptThe person is talking.On-camera motion, framing, background behaviour.
resolution720p720p or 1080p.
seedrandomFor reproducible generations.
disable_safety_filtertrueSee the warning above.
disable_prompt_upsamplingfalsePass raw prompt text instead of enhanced.
negative_prompt""Experimental. Elements to suppress.
negative_prompt_strength0Experimental. Both must be set for either to apply.

The two prompt fields do different jobs, and mixing them degrades both. voice_prompt controls delivery: "warm support specialist, calm pace", "no sales hype, clear consonants". video_prompt controls the picture: "fixed eye-level shot, small hand gestures", "soft office blur behind subject, no zoom". Do not restate the script in either.


Voices and Languages

Ten languages: English (US), English (UK), Spanish, French, German, Italian, Portuguese (Brazil), Japanese, Korean, Hindi.

Thirty built-in voices, named after stars: Achernar, Achird, Algenib, Algieba, Alnilam, Aoede, Autonoe, Callirrhoe, Charon, Despina, Enceladus, Erinome, Fenrir, Gacrux, Iapetus, Kore, Laomedeia, Leda, Orus, Puck, Pulcherrima, Rasalgethi, Sadachbia, Sadaltager, Schedar, Sulafat, Umbriel, Vindemiatrix, Zephyr, Zubenelgenubi.

Align the voice with the face. Pruna is explicit about this: voice gender, language, and the identity in the start frame should match. A mismatch reads as wrong immediately, even when every individual element is good.

Rewrite scripts per locale rather than translating them. Shipping English phrasing through a French voice produces speech that is technically correct and audibly foreign.


The Prompt Formula

Pruna publishes a four-part structure worth following literally.

SlotFast passLocked-in
Start frame (image)One line: who, outfit, basic light. Single subject.Age, wardrobe, expression, light direction, set, lens and aspect spelled out.
voice_scriptShort lines, one beat per sentence, in the target language.Ear-tested for speech synthesis, rewritten per locale, with natural pauses.
voice_promptTone and pace in a few words.Role, register, and what to avoid — hype, theatrical delivery.
video_promptSteady shot, small motion, simple background.Fixed camera, repeatable gestures, static or softly blurred background.

When lip sync drifts, lock the camera. Pruna's recommendation: no pan, no zoom, no handheld if the mouth or frame wobbles. A fixed camera is the single most effective fix for unstable sync.

"Single subject" belongs in the start frame prompt. A second face in the image is the most common cause of an unusable result.


Aspect Ratio Comes From the Image

Output follows the input image. A landscape start frame gives a landscape video; a portrait start frame gives a vertical one.

There is no aspect ratio parameter. Generate the still at the ratio you need — 16:9 for a web hero cut, 9:16 for social — and the video follows.

This is also how you get one identity across formats: same person, same wardrobe, same lighting, two start frames at two ratios.


Capabilities

CapabilityValue
input_typesimage (required), text, audio
output_typesvideo
audio_outputYes — lip-synced speech
resolutions720p, 1080p
languages10
voices30 built-in
recommended_max_durationUnder 3 minutes
endpoint/v1/video/generations
requires_promptNo — but an image and either a script or audio are required

Using P-Video-Avatar on DEVUP AI

Endpoint: POST https://api.devupai.com/v1/video/generations

Video generation on this platform is synchronous — a request can hold the connection open for several minutes. Set a generous timeout.

The response returns a signed URL in data[0].url that expires 300 seconds after the response is produced, after which the proxy returns HTTP 403. Download immediately, or request response_format: "b64_json" for inline bytes. Videos above the 20 MB inline limit fall back to a URL automatically, with a note inside _devup.

Every response carries _devup with cost_dzd for the request and balance_dzd for what remains.

Verify the request shape before building

This model requires an image input. Confirm how that field is accepted on your path before writing a pipeline around it — a video model that takes a mandatory image is a different request shape from a prompt-only text-to-video model.

BASH
curl -X POST "https://api.devupai.com/v1/video/generations" \
  -H "Authorization: Bearer $DEVUP_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 900 \
  -d '{
    "model": "PrunaAI/p-video-avatar",
    "image": "https://example.com/portrait.jpg",
    "voice_script": "Bienvenue. Configurons votre premier flux en deux minutes.",
    "voice": "Kore (Female)",
    "voice_language": "French",
    "voice_prompt": "Professional onboarding, clear articulation, approachable tone.",
    "video_prompt": "Fixed camera, centered; light hand motion, stable framing.",
    "resolution": "720p",
    "disable_safety_filter": false
  }'

Read what comes back. A success tells you the shape is accepted; an error tells you which fields are not. Either answer is worth knowing before you build.

Downloading the result — Python

PYTHON
import os
import requests

DEVUP_API_KEY = os.environ["DEVUP_API_KEY"]

response = requests.post(
    "https://api.devupai.com/v1/video/generations",
    headers={
        "Authorization": f"Bearer {DEVUP_API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "model": "PrunaAI/p-video-avatar",
        "image": portrait_url,
        "voice_script": "Welcome. Let's connect your data in under two minutes.",
        "voice": "Zephyr (Female)",
        "voice_language": "English (US)",
        "voice_prompt": "Warm support specialist, calm pace.",
        "video_prompt": "Fixed eye-level shot, small hand gestures, soft office blur behind subject.",
        "resolution": "720p",
        "seed": 42,
        "disable_safety_filter": False,
    },
    timeout=900,  # synchronous generation — minutes, not seconds
)
response.raise_for_status()

result = response.json()

# Download immediately — the signed URL expires 300 seconds after the response.
with open("avatar.mp4", "wb") as handle:
    handle.write(requests.get(result["data"][0]["url"], timeout=120).content)

print(f"Cost: {result['_devup']['cost_dzd']} DZD · Balance: {result['_devup']['balance_dzd']} DZD")

seed is set deliberately here. When you are testing prompt changes, a fixed seed is what lets you attribute a difference to the change rather than to sampling.

Node.js

JAVASCRIPT
import { writeFile } from "node:fs/promises";

const response = await fetch("https://api.devupai.com/v1/video/generations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.DEVUP_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "PrunaAI/p-video-avatar",
    image: portraitUrl,
    voice_script: "Welcome. Let's get you set up.",
    voice: "Puck (Male)",
    resolution: "720p",
    disable_safety_filter: false,
  }),
  signal: AbortSignal.timeout(900_000),
});

if (!response.ok) {
  throw new Error(`Request failed with status ${response.status}`);
}

const result = await response.json();
const video = await fetch(result.data[0].url);
await writeFile("avatar.mp4", Buffer.from(await video.arrayBuffer()));

Production Workflow

The pattern this model was designed around, and the one that keeps cost sane.

Iterate at 720p, deliver at 1080p. Cost scales per second of output and by resolution. Get the prompt, voice, and timing right at the lower tier, then rerun the final asset at the higher one. Composition, delivery, and motion carry across — only the pixels change.

Fix the seed while iterating. Change one variable at a time. With a random seed you cannot tell whether a difference came from your edit or from the sampler.

Reuse one approved start frame across a campaign. The identity is in the image. One portrait, many scripts, many languages — that is the whole point of the model, and it is what separates it from re-shooting.

Prefer uploaded audio when pronunciation matters. Brand names, product names, technical terms, and anything in a language you are not certain the synthesiser handles well. The built-in voices are fast and scale; a recording is exact.


Limitations

  • Safety filtering is off by default. disable_safety_filter defaults to true. Set it to false unless you have your own moderation layer.
  • Likeness and consent are your responsibility. The model will animate any face you give it. No parameter supplies permission.
  • Ten languages only — Arabic is not among them.
  • No aspect ratio parameter. Output follows the input image; control it there.
  • Clips under three minutes are recommended. Longer generations show gradual consistency drift, which Pruna describes as a current limitation across diffusion video models generally.
  • One subject only. A second face in the start frame is the most common cause of failure.
  • Not for motion retargeting or footage editing. This model generates new speech from one still. Animating a still from existing footage, swapping characters in footage, or editing footage are different models.
  • Negative prompting is experimental. Both negative_prompt and negative_prompt_strength must be set for either to apply, and higher strengths can affect identity, motion, or background unpredictably.
  • Synchronous generation. Requests hold the connection for minutes; plan timeouts accordingly.
  • Signed URLs expire after 300 seconds.
  • No architecture, parameter count, or technical report is published.
  • No per-request spending limit exists on this platform. Bound generation volume in your own application layer.
  • Not a safety layer. Apply your own moderation to input images, scripts, and output before publishing.