Platform presets in Python: build a Sume video request, refuse bad
A 28-line Python preset table for TikTok 9:16, TikTok 1:1 and Shorts ads that picks the lowest Seedance tier clearing the pixel floor and refuses bad lengths.

Keep the platform limits in one table, and build the Sume request from it. The script below holds a preset per placement, picks the cheapest Seedance tier whose frame clears the platform's pixel floor, and raises an error for a model length that does not fit. It makes no network call, so you can run it as written and read the output before you submit anything.
The presets
The numbers in the table come from two help pages. TikTok's in-feed spec lists 540x960 or more for 9:16, 640x640 or more for 1:1, and a duration up to 10 minutes. Google's Shorts ad page lists a range up to 60 seconds for the main campaign types. Seedance frame sizes and model lengths come from the Sume pricing tables and the video docs.
| Preset | Ratio | Pixel floor | Longest ad |
|---|---|---|---|
| tiktok-9x16 | 9:16 | 540x960 | 600 s |
| tiktok-1x1 | 1:1 | 640x640 | 600 s |
| shorts-ad | 9:16 | none stated | 60 s |
The script
Lengths per model are 4 to 30 seconds for Seedance 2.5, and 4 to 15 for Seedance 2.0 and Mini. The resolution loop tries 480p first, then 720p.
PRESETS = {
"tiktok-9x16": {"ratio": "9:16", "min_px": (540, 960), "max_s": 600},
"tiktok-1x1": {"ratio": "1:1", "min_px": (640, 640), "max_s": 600},
"shorts-ad": {"ratio": "9:16", "min_px": (0, 0), "max_s": 60},
}
MODELS = {"seedance-2.5": (4, 30), "seedance-2": (4, 15), "seedance-2-mini": (4, 15)}
SIZES = {("480p", "9:16"): (496, 864), ("720p", "9:16"): (720, 1280),
("480p", "1:1"): (640, 640), ("720p", "1:1"): (960, 960)}
def build(preset, model, seconds, prompt):
p, (lo, hi) = PRESETS[preset], MODELS[model]
if not lo <= seconds <= hi:
raise ValueError(f"{model} takes {lo}-{hi} s, got {seconds}")
if seconds > p["max_s"]:
raise ValueError(f"{preset} allows {p['max_s']} s")
for res in ("480p", "720p"):
w, h = SIZES[(res, p["ratio"])]
if w >= p["min_px"][0] and h >= p["min_px"][1]:
return {"model": model, "prompt": prompt, "duration": seconds,
"resolution": res, "aspect_ratio": p["ratio"]}
raise ValueError("no tier clears the pixel floor")
print(build("tiktok-9x16", "seedance-2-mini", 12, "Sneaker spin"))
print(build("tiktok-1x1", "seedance-2", 8, "Mug on a desk"))
try:
build("shorts-ad", "seedance-2", 30, "Too long for this model")
except ValueError as e:
print("refused:", e)What it prints
- The 9:16 preset skips 480p, because Seedance 480p in 9:16 is 496x864, below 540x960. It picks 720p, which is 720x1280.
- The 1:1 preset keeps 480p, because Seedance 480p in 1:1 is 640x640, which is exactly TikTok's floor.
- The 30-second Shorts ad on Seedance 2.0 is refused locally with a message that names the model's 4 to 15 second range, so you do not pay for a failed submit.
Prices for the two requests it builds
A 12-second Seedance Mini clip at 720p in 9:16 costs $2.27 on Sume. An 8-second Seedance 2.0 clip at 480p in 1:1 costs $1.35. At 720p the same square would be $3.03. Prices are the provider list times 1.25, rounded up to the cent per job.
Prices across presets
The script picks the tier. This table prices what it picks for a few common lengths, so you can budget a batch before you run it.
| Preset | Model | Length | Tier chosen | Price |
|---|---|---|---|---|
| tiktok-9x16 | Seedance Mini | 15 s | 720p | $2.84 |
| tiktok-9x16 | Seedance 2.5 | 15 s | 720p | $8.67 |
| tiktok-1x1 | Seedance Mini | 10 s | 480p | $0.84 |
| tiktok-1x1 | Seedance 2.0 | 10 s | 480p | $1.68 |
| shorts-ad | Seedance 2.0 | 15 s | 720p | $5.67 |
Sending the request and extending the table
Post the body to POST /v1/videos with your SUME_API_KEY in an Authorization: Bearer header, as the video docs show, and poll the job. The body fields used here are model, prompt, duration, resolution and aspect_ratio. Add new presets as the platforms change, and re-read their pages first. A preset table that is wrong is worse than none, so put the read date next to every number you copy from a help page, and keep the pixel floors and the length caps in separate fields so each can change on its own.
- Add a
min_sper preset for Google's 6-second Reach and 10-second Action minimums. - Add Wan 3.0 once you have its frame sizes from your own measurement, since the table above holds only Seedance sizes.
- Add
1:1for Google Ads video assets, which lists 16:9, 1:1 and 9:16.
Sources
Related posts
More in Developers
- Timeline output.fps: why a 24 fps clip judders when you force 30
Leave output.fps unset and Timeline renders at the source rate. Force 30 on a 24 fps clip and frames repeat; the job reports output_fps_resamples_sources.
- Tornado: verify a Sume webhook in a RequestHandler
A Tornado 6.5 RequestHandler that checks the Sume webhook HMAC on self.request.body, raises HTTPError 401 on failure and handles the webhook.test event.
- Transcribe a 25-minute interview on Sume: three STT jobs, $0.26
Sume STT takes up to 10 minutes per job at $0.01 a minute. A 25-minute interview is one $0.01 timeline split plus three STT jobs, $0.26 at list.
- Transcribe a file from your own bucket: what Sume STT audio_url needs
Sume speech-to-text takes a public HTTPS audio_url, preferably on media.sume.com. How to get a private recording ready, and what a neighbouring API rejects.
Written by Sume