Pick a video model from GET /v1/videos/models, not a constant

A new video model should not need a redeploy. Filter the Sume catalog by resolution, duration, audio and frame inputs at runtime, and survive a withdrawn model.

6 min readSume
All posts

Read the model list from GET /v1/videos/models at runtime and filter it by what the request needs, instead of hard-coding a model id in your code. Each catalog row says which resolutions, aspect ratios and durations the model supports, whether it takes first or last frames, which reference types it accepts, and whether it generates audio. When a new model arrives or an old one is withdrawn, a pipeline that filters the list needs no deploy. A pipeline with a constant breaks, or never benefits.

What the catalog tells you

The video generation docs describe the response: a data array where each model has id, supported_resolutions, supported_aspect_ratios, supported_durations, supported_frame_images, supported_input_references, generate_audio and pricing_skus. Those are exactly the fields a request validator needs. Sume validates against the same catalog, so an unsupported combination returns a 400 rather than silently dropping a field.

Two other facts matter for a router. A model id that is not in the catalog gives 404 model_not_found. And sume/auto exists as a pseudo-model for when you want Sume to pick; use it when you do not need to control which model runs, and the filter below when you do.

A runtime filter

The function checks a request's resolution, duration, audio need and first-frame need against each row and returns the ids that fit. The sample catalog is trimmed from the docs plus an invented future-model-x row to show a model appearing without code changes; fetch the real list in production, cache it for a few minutes, and refresh on a 404 model_not_found. It runs as-is on Python 3.

catalog = {"data": [
    {"id": "seedance-2", "supported_resolutions": ["480p", "720p", "1080p"],
     "supported_durations": list(range(4, 16)), "supported_frame_images": ["first_frame", "last_frame"],
     "supported_input_references": ["image_url", "video_url", "audio_url"], "generate_audio": True},
    {"id": "future-model-x", "supported_resolutions": ["1080p"],
     "supported_durations": [3, 4, 5], "supported_frame_images": [],
     "supported_input_references": [], "generate_audio": False},
]}

def candidates(models, resolution, seconds, needs_audio=False, first_frame=False):
    out = []
    for m in models:
        ok = resolution in m["supported_resolutions"] and seconds in m["supported_durations"]
        ok = ok and (m["generate_audio"] or not needs_audio)
        ok = ok and ("first_frame" in m["supported_frame_images"] or not first_frame)
        if ok:
            out.append(m["id"])
    return out

print(candidates(catalog["data"], "1080p", 5))
print(candidates(catalog["data"], "1080p", 12, needs_audio=True))
print(candidates(catalog["data"], "1080p", 4, first_frame=True))

Add price and a stable fallback

Capability is the first filter and price the second. The catalog carries pricing_skus per model; sort the candidates by it, or by your own preference list, and take the first. Keep a short ordered fallback of ids you have tested, and fall to sume/auto when none of them fits, so a withdrawn model degrades to a slightly different clip rather than an outage.

Do not cache forever. A model that was in the list yesterday may not be today, and a cached id that now returns model_not_found is a 404 you can catch once, refresh the list on, and retry with a new choice. A 404 at create means nothing ran and nothing was charged.

read 2026-10-03
Catalog fieldUseEffect
supported_resolutionsResolution you needDrop models without it
supported_durationsClip lengthDrop models that cannot do it
generate_audioAudio neededDrop silent models
supported_frame_imagesfirst_frame or last_frameNeeded for i2v with a pinned start
supported_input_referencesimage, video or audio refsNeeded for reference-to-video
pricing_skusCost orderingSort remaining candidates

Test the filter with fixtures

Keep a snapshot of the catalog in your test fixtures, plus a handful of requests with known good answers. When a launch adds a row, add it to the snapshot and run the tests; you learn in a minute whether your routing rules handle it. That is a better way to adopt new models than editing constants on launch day.

Respect model-specific limits

Capability filters are necessary but not sufficient. Some models have source-clip rules that a duration filter cannot express: for example a video-to-video recast model works on a supplied source clip of 5 to 30 seconds with one to four reference images, which is a different input shape from text-to-video. If your pipeline mixes modes, filter on the input fields the catalog lists (supported_frame_images, supported_input_references) and keep a separate branch for edit-style models rather than forcing them through the same request builder.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume