Overview
A studio video is a single video composed from an ordered list of whole-frame scenes — avatar clips, still images, and existing video footage — concatenated in the order you send them. You describe the scenes; HeyGen owns the layout, derives each scene’s duration, center-crops every scene to one global output canvas, and returns a singlevideo_id for the finished MP4.
Create one by passing "type": "studio" to POST /v3/videos — the same endpoint that renders avatar, image, and cinematic_avatar videos:
Rendering is all-or-nothing: one request produces one video, and every scene renders or none do. Output settings — aspect ratio, resolution, captions — are global, set once per request.
Each scene renders up to 30 minutes. When a scene’s duration comes from an audio track longer than that, split the audio and send it as consecutive scenes — see Usage Limits.
Studio videos define their scenes in the request, which is ideal for programmatic composition. To render a reusable layout you’ve designed visually in HeyGen Studio, use a HeyGen Studio Template instead.
Quick Example
A three-scene video: a title card held for three seconds, an avatar delivering the message, and an existing clip as the outro.Response
GET /v3/videos/{video_id} until status is completed, then read the download URL — or pass a callback_url to receive a webhook when the video is ready.
Request Body
Scene framing
A scene keeps its own shape inside the canvas rather than being cropped to fill it: where the two differ, the scene is scaled to fit and the remainder is padded. On a1:1 canvas at 1080p, an avatar_video scene from a 16:9 avatar renders as 1080x612 with padding above and below, and an image scene renders as a 608x1080 column with padding to either side.
Match aspect_ratio to the shape your scenes already are when you want an edge-to-edge frame.
| brand_glossary_id | string | No | — | Brand glossary controlling how custom terms are pronounced — see Brand Glossary. |
| caption | object | No | — | Caption settings — see Captions. |
| callback_url | string | No | — | Webhook URL to receive a POST notification when the video is ready. |
| callback_id | string | No | — | Caller-defined identifier echoed back in the webhook payload. |
| watermark | object | No | — | Custom watermark image overlay (PNG or JPEG). A premium option for select Enterprise customers — contact support to request access. |
The output container is MP4.
Scene Types
Every scene fills the whole frame and carries atype discriminator that determines its remaining fields.
Avatar Video Scenes
"type": "avatar_video" renders a speaking scene. Its input object has "type": "avatar" and references an avatar you already have by avatar_id. The scene’s duration is derived from the audio.
Mirrors the standalone avatar creation mode, minus the output settings — those are global on the studio request. Any avatar look works, exactly as in the standalone mode: video avatars, studio avatars, and photo avatars. To use a photo avatar (a “talking photo”), pass its look id as avatar_id.
Provide exactly one audio source:
script (with voice_id or a default voice), audio_url, or audio_asset_id.
To lip-sync your own photo, register it as a photo avatar first via the photo-avatar API, then use its look id as
avatar_id here. A studio scene references existing avatars; it does not animate a raw image inline.Choosing an engine
Theavatar input accepts an optional engine object, defaulting to Avatar IV when omitted. Pass { "type": "avatar_v" } for cross-reference-driven animation on Avatar V — check supported_api_engines on the avatar look to confirm eligibility. On Avatar V you may also set engine.reference_look_id to a digital_twin look in the same avatar group to pin the animation reference; when omitted, video avatars self-reference and photo avatars pick an eligible look from the group. expressiveness applies on Avatar IV; motion_prompt applies to photo avatars on either engine and to video avatars on Avatar V.
Avatar V needs a usable reference look in the avatar’s group, so it is not available for every photo avatar: if the group has none, the request fails with a
400. A non-public digital_twin reference must also clear its group’s consent requirements, whether you supplied it or it was selected for you. To see what a group already has, use GET /v3/avatars/looks?group_id=...&avatar_type=digital_twin — the group id is the group_id field on any look in that group. Filtering by avatar_type alone searches your whole workspace and can return a digital twin from a different group, which is rejected. The listing shows candidates rather than guaranteeing eligibility: a non-public group needs consent. A look with status: processing (still training) can still be used as a reference.Image Scenes
"type": "image" shows a still image in one of two modes — choose exactly one:
- Silent — set
duration(seconds) and no audio source. The image holds on screen for that long. - Narrated — set exactly one audio source and omit
duration. The scene length follows the audio.
Video Scenes
"type": "video" drops an existing clip into the sequence. Like an image scene, it plays in one of two modes:
- Silent — no audio source. The clip plays full-length at its own duration.
- Narrated — set exactly one voiceover source (the same audio inputs a narrated image scene accepts). The voiceover drives the scene’s duration, and
playback.modecontrols how the clip fills that time — hold the last frame, loop, or adjust speed to fit.
In narrated mode, provide exactly one voiceover source:
script (with voice_id), audio_url, or audio_asset_id.
Playback and scene duration
Theplayback object carries two composable controls: how the clip aligns to a voiceover-driven scene duration, and the clip’s own audio level.
mode requires a voiceover, since the voiceover is what defines the target scene duration — a silent clip always plays full-length. The voiceover and the clip’s own audio mix independently: there is no automatic ducking, so set playback.volume (or mute) yourself to bring the clip down under narration. With fit_to_scene, mute the clip when its source audio shouldn’t be speed-adjusted along with the visuals.
Asset input
The image/video scenesource field takes an asset object, discriminated by type. Provide one of:
Captions
Pass acaption object to generate captions across the full composed video. Captions are derived from the speech in avatar_video scenes and narrated image scenes. A sidecar subtitle file is always returned via subtitle_url in the chosen file_format; add style to additionally burn the captions into the rendered video — the sidecar is still delivered.
Brand Glossary
A brand glossary is a set of custom pronunciations, for example speakingHeyGen as hey-jen. Glossaries are created and edited in the HeyGen web app under Brand Kit. Pass one with the top-level brand_glossary_id, a global setting that applies to the whole request.
GET /v3/brand-glossaries, and see which terms a glossary remaps with GET /v3/brand-glossaries/{brand_glossary_id}.
A glossary applies wherever HeyGen generates the speech: an avatar_video scene, or an image or video scene narrated with script. Scenes that supply finished audio (audio_url or audio_asset_id) play unchanged.
A glossary changes the spoken audio only. Captions and theAn id that does not exist in your workspace returns.srtsidecar keep the original spelling, so a term writtenHeyGenstill readsHeyGenon screen while being spoken ashey-jen.
400 and no video is created.
Rendering at Scale
A studio request composes its scenes into a single video, so it is not accepted by the batch endpoint. A"type": "studio" item in POST /v3/videos/batches is rejected. Send studio videos one per request to POST /v3/videos and track each returned video_id.
