Poster frame at 2.5 seconds: video-frames returns source-size stills

Sume POST /v1/video-frames extracts up to 24 exact stills at source size. Always async (202); a failed instant gives a null url and the job still succeeds.

4 min readSume
All posts

To pull a poster frame from a video with Sume, call POST /v1/video-frames with video_url and at: [2.5]. It always returns 202, then you poll and read frames[{t,url,width,height}] as durable images on media.sume.com. Unlike video inspect, frames keep the source size unless you set max_edge.

Request

Send video_url plus exactly one of at[] (1 to 24 timestamps, each 0 or more) or fps (above 0, up to 2, mid-bin samples, limit 24). Optional format is jpeg (default) or png for lossless; max_edge is 16 to 2160. Add an Idempotency-Key so a retry does not queue a second extract.

curl -X POST https://api.sume.com/v1/video-frames \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: poster-001" \
  -d '{
    "video_url": "https://media.sume.com/artifacts/artf_demo/talk.mp4",
    "at": [2.5],
    "format": "png"
  }'

Always async

The submit pins async mode. Do not send mode: "sync"; it will not give you a 200. The resource ID is the job ID, so GET /v1/video-frames/{id} returns the object, with resource_status: ready when frames are available. There is no /v1/models/sume/.../runs alias for this family.

Frames versus inspect

video-frames vs video-inspect (Sume docs, read 2026-10-09)
Questionvideo-framesvideo-inspect
Default sizeSource sizemax_edge 768
Source limit300 seconds1800 seconds
Stills per call2424
Returns probe and transcriptNoYes (transcript optional)
Default modeasync only (202)sync, 30 s wait

Choosing the timestamp

A poster at 2.5 seconds is arbitrary; the point is that you choose the instant. Pull a handful at once, for example at: [0.5, 2.5, 5, 7.5], and keep the best. One job can return up to 24 frames, so four candidates cost the same single job as one. Use png if a downstream step will compress the image again, and jpeg for the final delivery.

If you want a smaller file, set max_edge, which clamps the long edge between 16 and 2160 pixels. If you omit it the frames keep the source size, which is what you want for a restage or a cover image.

Polling loop

After the 202, poll GET /v1/video-frames/{id} until resource_status is ready. Because the job is billed by Modal compute with a hold taken at submit, a frame request on a 300-second source holds the compute ceiling until it finishes, and the charge is never more than the hold. Keep source clips short when you only need a poster; the limit is 300 seconds, and the same job on a 30-second clip finishes sooner.

A cheap pattern is to extract four to eight candidates in one job, show them to a person or a scoring step, and keep one url. The other frames are durable media.sume.com images and can be discarded without cleanup on your side.

Failure handling

If one instant fails to extract, that frame has url: null, and the job does not fail, so check each entry before using it. An at value outside [0, duration) fails the worker with frame_time_out_of_range and tells you the probed duration, and a source over 300 seconds fails with duration_out_of_range. Clips over 90 seconds may carry a low_confidence_long_video warning, which is not a failure. Billing is the same as inspect: Modal container seconds at list times 1.25 plus the platform fee, capped at the hold, with no admission seat used.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume