Assemble a three-clip montage with fades through the Sume API
A working Timeline 1.0 request that joins three hosted clips over one audio spine with fade and dissolve transitions, plus the Python to poll it, for $0.10.

Post one audio spine and an ordered video[] list to /v1/timeline-1.0/render: three clips with fade and dissolve transitions over a 30-second spine render as one MP4 for $0.10 (Timeline 1.0). The first slot must start at 0, later starts must increase, and every URL must already be on media.sume.com.
Python request
Python has no top-level await, so this is plain synchronous code. The job is async by default; poll the job envelope.
import os, time, requests
API = "https://api.sume.com"
h = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
m = "https://media.sume.com/artifacts/artf_demo/"
body = {
"audio": {"url": m + "music.wav", "duration_seconds": 30},
"video": [
{"source_url": m + "a.mp4", "start": 0, "duration": 10},
{"source_url": m + "b.mp4", "start": 10, "duration": 10,
"transition": {"type": "fade", "duration": 0.5}},
{"source_url": m + "c.mp4", "start": 20, "duration": 10,
"transition": {"type": "dissolve", "duration": 0.5}},
],
}
r = requests.post(API + "/v1/timeline-1.0/render",
headers={**h, "Idempotency-Key": "montage-001"}, json=body)
r.raise_for_status()
j = r.json()
jid = j.get("data", j)["request_id"]
while True:
s = requests.get(API + "/v1/jobs/" + jid + "/status", headers=h).json()
s = s.get("data", s)
if s["terminal"]:
break
time.sleep(s.get("next_poll_after_seconds") or 3)
res = requests.get(API + "/v1/jobs/" + jid + "/result", headers=h).json()
print(res.get("data", res))
Rules the compiler enforces
| Rule | Detail |
|---|---|
| Transition types | fade, wipeleft, wiperight, slideup, slidedown, dissolve |
| Transition length | At most 1 s and 50% of the shorter neighbour |
| First slot | No transition (transition_on_first_segment) |
| Chained fades | More than 8 adjacent: too_many_chained_transitions |
| Slots | 1 to 200; strategy auto chunks past 12 |
| Default output | 1080x1920 MP4 |
Frame rate
Leave output.fps out unless you need it. If an explicit rate differs from your sources the job resamples and reports output_fps_resamples_sources.
Check the plan first
POST /v1/timeline-1.0/plan takes the same body and returns duration_seconds, segment_count, billable_minutes and estimated_cost_usd_micros without creating a job or reserving credits, and it does not need an Idempotency-Key. For this request the plan should show 30 seconds, 3 segments and 1 billable minute. A plan cannot predict short-source pad or loop warnings, so read warnings[] on the finished result as well.
Sources
Related posts
More in Developers
- Balance needed to submit 10 or 50 video jobs: reserve per model
Sume reserves each job's estimate at submit. A table of the balance 10 and 50 ten-second clips need on six video models, and where a 402 lands in a batch.
- callback_url on /v1/videos: the Sume job envelope that arrives
A /v1/videos callback_url delivers Sume's job.completed, job.failed or job.canceled envelope, not video.generation.* events. Payload, signature, checks.
- Cancel queued Sume jobs after queue_full; handle 409 already started
How to free capacity after a 429 queue_full: cancel queued jobs, read job_generation_already_started on running ones, and why a cancel releases the reserve.
- Can't choose a video model? Send sume/auto and let Sume pick
model: sume/auto lets Sume select the video family for you: 3 to 10 seconds, 16:9 or 9:16, default 720p and 8 seconds. What it does and does not tell you.
Written by Sume