Video model aliases from config that fail at boot, not at submit

Map your own names like hero-clip to Sume model ids in config, then check each against GET /v1/video-router/models at startup so a retired id stops the deploy.

6 min readSume
All posts

Keep a small config file that maps your product's names to Sume model ids and per-alias defaults, and at process start fetch GET /v1/video-router/models and verify every alias. An id missing from the catalog, or a duration outside capabilities.duration_seconds, raises before you accept traffic. That is cheaper than a failed submit, and your callers keep one job shape whatever the model underneath.

What the catalog provides

The catalog returns data.models[]. Each item has an id, a capabilities object with resolutions, aspect_ratios and duration_seconds {min, max}, plus pricing and constraints. The id enum in the schema lists these twelve models.

Video Router catalog fields used at boot (read 2026-10-04)
FieldUse
idMust equal the alias target
capabilities.duration_seconds.min / .maxCheck your default duration
capabilities.resolutionsCheck your default resolution
capabilities.aspect_ratiosCheck your default aspect ratio
gatedWhen true the model is omitted from public listings until GA

Boot check

The aliases below use seedance-2.5, which the Video Router docs describe as 4 to 30 seconds at 480p, 720p and 1080p. The check runs on every boot, so a catalog change shows up in the next deploy.

import asyncio, json, os, sys, urllib.request
ALIASES = {
    "hero-clip": {"model": "seedance-2.5", "duration": 8, "resolution": "720p", "aspect_ratio": "9:16"},
}
def catalog():
    req = urllib.request.Request("https://api.sume.com/v1/video-router/models",
                                 headers={"x-api-key": os.environ["SUME_API_KEY"]})
    with urllib.request.urlopen(req, timeout=30) as r:
        return {m["id"]: m for m in json.load(r)["data"]["models"]}
def problems(models):
    out = []
    for name, a in ALIASES.items():
        m = models.get(a["model"])
        if not m:
            out.append(f"{name}: model {a['model']} not in catalog"); continue
        cap = m["capabilities"]
        d = cap["duration_seconds"]
        if not d["min"] <= a["duration"] <= d["max"]:
            out.append(f"{name}: duration {a['duration']} outside {d['min']}-{d['max']}")
        if a["resolution"] not in cap["resolutions"]:
            out.append(f"{name}: resolution {a['resolution']} not in {cap['resolutions']}")
        if a["aspect_ratio"] not in cap["aspect_ratios"]:
            out.append(f"{name}: aspect {a['aspect_ratio']} not in {cap['aspect_ratios']}")
    return out
async def main():
    bad = problems(await asyncio.to_thread(catalog))
    if bad:
        sys.exit("model config invalid:\n" + "\n".join(bad))
    print("model aliases ok")
asyncio.run(main())

What happens on a retirement

Fail the deploy on a problem, not just log it. A dropped model should be a config change you make on purpose: edit the alias to a different id and redeploy. Only the alias map changes, so the code that submits and polls stays the same.

Also note

POST /v1/video-1.0/generate is documented as retiring soon and remains an alias for the Video Router Auto pipe. New code should use /v1/video-router/generate with a catalog model, as above.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume