Extract the last frame of a video with an API to chain AI clips
Probe a Sume-hosted clip's duration and fps for free, extract its final frame as a PNG with video frames, then pass it to /v1/videos as the next first_frame.

To extract the last frame of a video with the Sume API, read the clip's duration_seconds and fps from a free POST /v1/video-inspect probe, then ask POST /v1/video-frames for a PNG just before the end, because every requested time must satisfy 0 <= t < duration. The returned media.sume.com image can open the next clip as a first_frame in POST /v1/videos.
The facts below come from the Video frames, Video inspect, and Video generation docs and the Sume API reference, read on 2026-09-26.
Why can't I ask for the frame at the duration?
Video frames only accepts instants inside the clip: each at value must satisfy 0 <= t < duration, or the worker fails with frame_time_out_of_range and names the probed duration. So get the duration first. An inspect with frames: false is a probe only, with no stills, and the probe is unbilled. Inspect defaults to mode: sync and answers 200 within 30 seconds when it can.
The probe carries duration_seconds and fps, among other container facts. Inspect reads your workspace's media.sume.com clips only, up to 1,800 seconds.
curl -X POST https://api.sume.com/v1/video-inspect \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: clip-a-probe-001" \
-d '{
"video_url": "https://media.sume.com/artifacts/artf_demo/clip-a.mp4",
"frames": false
}'Which timestamp is the last frame?
Ask for one frame interval before the end: t = duration_seconds - 1 / fps. That formula is our own arithmetic, not a docs rule; it stays inside [0, duration) by one frame. A 5-second clip at 24 fps gives 4.9583… seconds; if you shorten the decimals, round down, as in 4.958.
Use video frames rather than inspect stills for this: the inspect docs send exact source-size frames at one t to video frames, and inspect stills default to a 768-pixel long edge, a clamp video frames omits.
How do I extract the frame at full size?
Send at with that one time and format: "png", the lossless option, and omit max_edge to keep the source frame size, which the docs call the restage path. Submitting, polling, and the result shape work as for any extract; see How to extract frames from a video.
One detail matters for chaining: an instant that failed to extract comes back with url null without failing the job, so check frames[0].url before you hand it on.
curl -X POST https://api.sume.com/v1/video-frames \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: clip-a-last-frame-001" \
-d '{
"video_url": "https://media.sume.com/artifacts/artf_demo/clip-a.mp4",
"at": [4.958],
"format": "png"
}'How do I chain the frame into the next clip?
Pass the frame to POST /v1/videos in frame_images. Each entry is type: "image_url" with image_url.url and a frame_type of first_frame or last_frame; as first_frame, the old clip's ending opens the new one. Pin a model whose supported_frame_images in GET /v1/videos/models lists first_frame. If you also send input_references, frame_images takes precedence and the request is image-to-video. Image-to-video with first and last frames covers the generation side.
curl -X POST https://api.sume.com/v1/videos \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: clip-b-001" \
-d '{
"model": "seedance-2",
"prompt": "The camera keeps moving forward along the same path",
"frame_images": [
{
"type": "image_url",
"image_url": { "url": "https://media.sume.com/artifacts/artf_demo/last.png" },
"frame_type": "first_frame"
}
]
}'Where do I get a Sume-hosted URL for a generated clip?
Video frames and inspect need your workspace's media.sume.com URL, and the /v1/videos poll returns unsigned_urls on the API host instead. The same job is visible at GET /v1/jobs/{id}/result, and Sume returns generated outputs as Sume-hosted artifacts under media.sume.com, mirrored before they appear in results. Repeat probe, frame, and generate for each link in the chain, then join the clips with Timeline 1.0.
What are the limits?
The two media steps are free; only the generation is billed, per model. GET /v1/videos/models reports each model's pricing_skus, and GET /v1/catalog carries pricing metadata too.
| Step | Endpoint | Billing | Caps |
|---|---|---|---|
| Probe | POST /v1/video-inspect | Unbilled with frames: false | Source ≤ 1,800 s |
| Last frame | POST /v1/video-frames | Unbilled | Source ≤ 300 s; 1–24 at values, each 0 <= t < duration |
| Next clip | POST /v1/videos | Per model, pricing_skus | Per model: supported_frame_images, supported_durations |
Sources
Related posts
Written by Sume