Pre-render
Give a picture, a voice and a script; get back a video of the face saying it, as an MP4, with subtitles if you want them. Use it anywhere a recorded video works: a website, a course, a message.
Two kinds
| Talking head | Half-body | |
|---|---|---|
| What you see | Head and shoulders | The whole picture as it is — hands, props, illustrations too |
| The picture | A photo of a person’s face | Any picture; cut to the frame’s shape around the face (or the middle when there is none) |
| Frame | The face’s frames: portrait, landscape or square | Portrait (720×1248) or landscape (1248×720) |
| How long it takes | Usually a short wait | Minutes: about 8.5 seconds for each second of video, plus up to about 13 minutes when a renderer has to start first |
There is no crop setting: to frame the picture yourself, send it already cut.
In the console
Open Pre-render, choose the picture, the voice and the frame, write the Script and press Generate video (or Generate half-body video). The video is made in the background and shows in the Videos list on the left; pick it to watch and download it once it is ready. Picking a video also puts its settings back on the right, so you can change something and generate a new one; the first stays as it is.
With the API
Your server sends POST /v1/renders with your API key, then asks how it is going until it is ready:
Node
const API = "https://api.avatargo.ai/v1";
const headers = { authorization: `Bearer ${process.env.AVATARGO_API_KEY}`, "content-type": "application/json" };
const res = await fetch(`${API}/renders`, {
method: "POST",
headers,
body: JSON.stringify({
avatarId: "av_…", // or imageId (a picture in your gallery), or image (an https URL or base64)
voiceId: "…", // the id of a voice in GET /v1/voices
text: "Welcome to the course. Today we start with the basics.",
}),
});
let render = await res.json();
if (!res.ok) throw new Error(`${render.error.code}: ${render.error.message}`);
// queued → rendering → ready, or failed (errorCode says why)
while (render.status === "queued" || render.status === "rendering") {
await new Promise((r) => setTimeout(r, 5000));
render = await (await fetch(`${API}/renders/${render.id}`, { headers })).json();
}
console.log(render.status, render.videoUrl, render.subtitlesUrl);- The picture — exactly one of
avatarId(one of your faces, or a system face),imageIdorimage(a PNG or JPEG of at most 10 MB). type—talking_head(the default) orhalf_body.frame—portrait(the default),landscapeor, for a talking head,square.subtitles— an SRT beside the video, one cue per sentence; on by default.videoUrlandsubtitlesUrlwork for an hour: ask for the render again for fresh ones. The video is kept until you delete it (DELETE /v1/renders/{id}).- Instead of asking, you can have AvatarGo tell your server: the
render.readyandrender.failedwebhooks. POST /v1/renders/{id}/cancelstops one that waits or renders.POST /v1/renders/estimatetells how long a script’s video will be before you make it.
Limits
- The script is at most 4,000 characters, and the video at most 5 minutes — a longer script is cut
there, and the render says so in
error. - At most 2 of your videos render at once; the rest wait their turn. At most 100 a day.
- When every renderer is busy, a video waits for one — live calls go first — for at most 15 minutes
(talking head) or 30 (half-body), then fails with
engine_unavailable.
The full list of fields and error codes is in the API reference, under Pre-render.