Short ends before the voice: timeline_gap_filled and last-frame hold
When Timeline clips cover less than the audio, you get a held last frame and a warning, not an error. The two codes, and how to fix them before upload.

If your video slots end before the audio does, Sume still renders. The last frame is held to the end of the audio and the result carries the warning video_coverage_shorter_than_audio; a hole between two slots is filled and flagged timeline_gap_filled. A render with warnings is billed like any other, so check warnings[] before you upload.
Both codes come from the repo's Timeline compiler and are described in the Timeline 1.0 doc; results are read through the jobs doc.
What exactly happens?
The spine sets the program length. Slots are placed by start and duration. Anything the slots do not cover is filled, so the viewer never sees black frames, but a frozen frame under live speech looks like a bug.
| Situation | Result | Warning code |
|---|---|---|
| Gap between two slots | Gap is filled | timeline_gap_filled |
| Slots end before the audio | Last frame is held | video_coverage_shorter_than_audio |
| Still image in a slot | Static hold, no motion | None, a still is a hold by design |
How do I catch it in code?
Poll GET /v1/jobs/:id/status until terminal, then read /result and test for the warning codes. Fail your own pipeline on them instead of publishing.
import os, requests
API = "https://api.sume.com"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
BAD = {"video_coverage_shorter_than_audio", "timeline_gap_filled"}
def main(job_id):
r = requests.get(f"{API}/v1/jobs/{job_id}/result", headers=H)
r.raise_for_status()
body = r.json()
found = [w.get("code") for w in body.get("warnings", []) if isinstance(w, dict)]
hit = BAD.intersection(found)
if hit:
raise SystemExit(f"fix coverage before upload: {sorted(hit)}")
print("ok")
main(os.environ["JOB_ID"])How do I fix it?
Extend the last slot's duration to the end of the audio, add another clip, or shorten audio.duration_seconds with a trim. The plan call, which is unbilled, returns the program length so you can compare it with your slots before you spend anything.
What Sume does not do
It does not decide whether a hold is acceptable. A held frame under a closing line may be fine; one under a mid-sentence is not.
Sources
Related posts
More in Developers
- Sora video ids in your database after the shutdown: what to keep
OpenAI's Videos API shut down 2026-09-24. Old video_ids no longer resolve, so store your own file URL and the model used. Schema fields included.
- Keep a source log for Shorts cut from long video: CSV from video trim
A source log shows which long video, timestamp and edit produced each Short. Build one from video trim results using actual_start_seconds.
- source_too_large on trim or filter: the 300 MiB source cap
Sume's video trim and filter refuse a hosted source over 300 MiB (314,572,800 bytes) at submit. What is checked, the free check call, and ways around it.
- Speech-to-text audio too large? Sume STT takes up to 10 MB, hosted
Sume's stt_create needs a public HTTPS audio URL on the Sume media host, 10 MB at most. What fits: 16 kHz mono wav versus mp3, and how to cut a long file.
Written by Sume