Put a still image above or beside a video with an API
POST /v1/timeline-1.0/compose stacks a still and a video into one MP4 (a half-banner), or overlays the still. Layout keys, limits and the flat price.

To put a still image above or beside a video, call POST /v1/timeline-1.0/compose with operation: "stack", one image.url and one video.url. It returns one MP4 with both on screen at once; by default the still is on top and takes half the frame, the layout the docs call a half-banner. Use operation: "overlay" to lay the still on top of the video instead.
Facts here are from the Timeline compose page, read 2026-09-29. Both URLs must be your workspace's media.sume.com files.
What does a stack request look like?
The HTTP field is operation, not mode; mode is the usual async or sync communication option.
curl -X POST https://api.sume.com/v1/timeline-1.0/compose \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: compose-001" \
-d '{
"operation": "stack",
"image": { "url": "https://media.sume.com/artifacts/artf_demo/banner.png" },
"video": { "url": "https://media.sume.com/artifacts/artf_demo/talk.mp4" },
"layout": { "split": "horizontal", "image_region": "top", "ratio": 0.5 },
"output": { "width": 720, "height": 1280, "fps": 25 }
}'Which layout keys go with which operation?
| Key | `stack` | `overlay` |
|---|---|---|
split | horizontal or vertical | Not allowed |
image_region | top/bottom on horizontal, left/right on vertical | Not allowed |
ratio | Still's share, 0.1 to 0.9 | Not allowed |
position | Not allowed | top, center or bottom |
width_ratio | Not allowed | 0.05 to 1 (default 0.9) |
How long is the result, and what does it cost?
Length always comes from the video layer: video.duration, or the rest of the file from source_in. The still is held for the whole clip and cannot lengthen it. The ceiling is 300 seconds. The price is $0.02 flat per job, because the duration may be unknown until the worker probes the file.
What happens to the audio, and what fails?
Audio passes through from the video. A mute video is a warning (compose_video_has_no_audio), not a failure. Mixing stack and overlay keys is a 400 (compose_stack_takes_no_overlay_layout or compose_overlay_takes_no_stack_layout), and image.url must be a still (compose_image_not_still). Drop the finished MP4 into a video[] slot of a Timeline render to join it with other shots.
When do I overlay instead of stack?
Use overlay when the video should fill the frame and the still is a badge or plate over it.
layout.position:top,centerorbottom.layout.width_ratio: 0.05 to 1 of the width, default 0.9; the plate keeps its aspect.layout.margin_ratio: 0 to 0.45 of the height, default 0.05.layout.video_fitis the only fit key;bluris not a compose fit.
Sources
Related posts
More in Developers
- Speech to text Korean API: send language_code or auto-detect?
Sume STT 1.0 takes an optional language_code such as ko; omit it and the language is auto-detected. When to pin Korean, when to omit it, and how TTS differs.
- Java subtitle generator API: burn captions with HttpClient
Generate subtitles from Java with the JDK HttpClient: POST the video URL to a captions API, poll the job, then read the captioned video_url.
- 503 provider_capacity_exceeded: same idempotency key or new?
A Sume 503 provider_capacity_exceeded means the provider queue is full. Docs say retry later with the same key; code replays the refusal, so use a new key.
- Which field do I branch on in a Sume API error: code or next_action?
Branch on the HTTP status, then on error.code. Use retryable, retry_after_seconds and next_action to decide on a resend. Never match on message.
Written by Sume