Video frames caps at 24 stills: a 15 s hook needs fps 1.6, not 2

Video frames returns at most 24 stills and fps up to 2. At 2 fps only 12 s are covered, so a 15 s hook needs fps 1.6; the Python below checks any length.

5 min readSume
All posts

Video frames returns at most 24 stills per call, and fps is capped at 2. The two limits meet at 12 seconds: at 2 fps a 12-second clip yields exactly 24 frames, and a longer clip is cut off at 24. A 15-second hook needs fps 1.6, since 24 / 15 = 1.6.

Limits

From the Sume docs.

Video frames limits, read 2026-10-08
FieldLimit
at[]1 to 24 values, each 0 <= t < duration
fps0 < fps <= 2, expanded to mid-bin samples (0.5/fps, 1.5/fps, ...), 24 frames max
Source length300 s or less
max_edge16 to 2160, optional
PriceModal compute, not a fixed fee

Choose fps for a length

Send only one of at[] or fps. This function picks the highest allowed rate for a clip so every second is covered, and shows the first sample times.

def pick_fps(seconds):
    if seconds <= 0 or seconds > 300:
        raise ValueError("source must be 0-300 s")
    return min(2.0, 24 / seconds)

for s in (6, 12, 15, 30):
    f = pick_fps(s)
    n = min(24, round(s * f))
    first = [round((i + 0.5) / f, 2) for i in range(3)]
    print(s, "s -> fps", round(f, 3), n, "frames", first)

Why mid-bin samples matter

Mid-bin sampling takes a frame from the middle of each time slot, not at 0 s. At 1.6 fps the first three stills fall at 0.31 s, 0.94 s and 1.56 s. A hook that cuts at second 1 is therefore seen in the second still. If you need a specific instant, use at[] and name the seconds yourself.

For a 30-second clip the cap sets fps at 0.8, about one still every 1.25 seconds. Video inspect samples eight mid-bin stills instead, with a default max_edge of 768, plus a probe and optional speech to text.

Longer clips

Video frames accepts a source up to 300 seconds. The 24-still cap is a hard stop, so a 300-second clip gives one still per 12.5 seconds at best (300 / 24). If you need finer coverage of part of a long clip, trim that part first for $0.02 and then extract frames from the trim, or name exact instants with at[].

Frames are billed by their Modal compute with a hold taken at submit, and the bill never exceeds the hold, so the cost is not a flat fee and is not shown here. Frames are returned as durable media.sume.com images at source size unless you set max_edge.

When to use at instead

fps samples evenly. If you care about specific moments, such as the first frame after a cut, use at[] with explicit times. Both forms count against the same 24-frame ceiling, and a time at or past the clip's duration fails with frame_time_out_of_range, so probe the length first with video inspect.

For a Short check you usually want the first second, the middle and the end: three values, nowhere near the cap.

A review routine

For a quick hook review, extract frames at 0.25, 0.75, 1.5, 3, 6, 9, 12 and 14.5 seconds with at[] on a 15-second clip: eight values, well inside the 24 cap. For a pass over the whole clip with no choice of instants, use fps 1.6, which gives 24 stills. The frames come back as durable images, so you can attach them to a review or pass them to an image-reading model.

If the clip is not yet hosted on media.sume.com, import it first with POST /v1/media-imports; the frames route does not fetch from the open internet.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume