Route a Kling video job in Python: scene, motion clip or 30 seconds
A small Python router for Sume: performance copies go to Kling motion control, 4-15 s scenes to kling-3, and longer jobs to a catalog id that lists 30 s.

A Kling job on Sume goes to one of three places: the motion control route if you hold a reference performance, kling-3 on /v1/videos if it is a 4 to 15 second scene, and a catalog id that lists 30 seconds, such as wan-3.0 or seedance-2.5, if it is longer. A 15-line function makes that choice, so your app never sends a request that the catalog will reject.
The three branches
Each branch follows from a limit that Sume documents. Motion control takes a motion_video_url and a length of 1 to 30 seconds. kling-3 takes 4 to 15 seconds and no reference urls. wan-3.0 takes 2 to 30 seconds, and seedance-2.5 takes 4 to 30.
The function
It returns the path and the model so that you can build the body in the next step. It is a pure function, so you can test it without a key.
def route(seconds: int, has_motion_clip: bool) -> tuple[str, str | None]:
"""Return (path, model) for a Sume Kling-family request."""
if has_motion_clip:
if not 1 <= seconds <= 30:
raise ValueError("motion control takes 1 to 30 s")
return "/v1/kling/3.0/motion-control", None
if 4 <= seconds <= 15:
return "/v1/videos", "kling-3"
if 15 < seconds <= 30:
return "/v1/videos", "wan-3.0"
raise ValueError("split the job or pick another model")
for s, m in ((12, True), (10, False), (28, False)):
print(s, m, route(s, m))What each branch costs
Prices are provider list times 1.25, read from Sume's docs. Wan 3.0 is tiered by resolution.
| Branch | Length | Per second | 30 s total |
|---|---|---|---|
| Motion control | 1 to 30 s | 0.1575 | 4.725 |
| kling-3 silent | 4 to 15 s | 0.14 | not reachable in one job |
| wan-3.0 at 720p | 2 to 30 s | 0.125 | 3.75 |
| wan-3.0 at 1080p | 2 to 30 s | 0.25 | 7.50 |
Keep the catalog as the truth
Limits change. Before a release, read GET /v1/videos/models and compare supported_durations with the numbers in your function. If a new Kling id such as a 4.0 row shows up with 30 seconds, add a branch for it and keep the old ones as a fallback.
The fallback matters more than the first choice. A router that returns one answer fails when a model is down. Return an ordered list of rows that fit the brief, and try the next one on a retryable error. The fallback chain post shows that pattern in full.
What the router does not decide
The function picks a route from two facts: the length and the presence of a motion clip. It does not choose the resolution, the ratio or the audio setting. Those are fields on the body, and each has its own limits in the catalog row: kling-3 takes 720p or 1080p in 16:9, 9:16 or 1:1, while wan-3.0 has three resolution tiers and its own ratios.
Keep that second step separate. First route, then read the row for the chosen id, then build a body from the allowed values. Splitting the two keeps each function small and testable, and an unsupported ratio becomes a clear error in your code instead of a 400 from the API.
Sources
Related posts
More in Developers
- Route low-confidence transcripts to review: STT language_probability
Sume STT returns language_code and language_probability. Flag results under a threshold you set and send them to a person. Python, about 10 cents per file.
- Ruby Net::HTTP never follows redirects: saving a Sume video
Net::HTTP returns the 302 from /v1/videos/{id}/content as-is. A 26-line Ruby script submits Seedance 2.5, polls, follows the redirect and saves the MP4.
- Ruby Net::HTTP: POST to Sume images and save the file
Net::HTTP.start with use_ssl and read_timeout, one POST to /v1/images, a string comparison on res.code, and File.binwrite for the image. No gems needed.
- Run create 503 studio_agent_upstream_timeout: the run may exist
A 502 or 503 on a Sume run create can mean the run already exists and is spending. Retry with the same Idempotency-Key and the original run is replayed.
Written by Sume