Seedance 2.5 price per second: read it from the Sume catalog before Q4
Seedance 2.5 renders 4 to 30 seconds at up to 1080p on Sume. Read its live price from the catalog, then run one 4-second draft to get your real cost per second.

The reliable way to price Seedance 2.5 on Sume is to read its row from GET /v1/videos/models and then bill one 4-second draft to learn your real cost per second. The model accepts 4 to 30 seconds at 480p, 720p and 1080p, and Sume bills the provider list times 1.25.
This post does not quote a per-second figure for Seedance 2.5, because the references it reads do not record one, and a guessed number in a budget is worse than none. The other posts in this series use rates that are written down; this one shows how to get a rate that is not.
What is documented
Sume's Video Router docs list seedance-2.5 with resolutions of 480p, 720p and 1080p and durations of 4 to 30 seconds, with no bitrate_mode. The older Seedance 2.0 family (seedance-2, seedance-2-fast, seedance-2-mini) stays routable by explicit id, but no default or routing preset selects the 2.0 and mini models now. The video docs say Seedance 2.x models accept audio and video references, which most other rows do not.
The catalog response for a model carries pricing_skus, a map from a SKU name to a price string. The docs' own example for Seedance 2.0 shows a key named per-1000-video-tokens, which tells you the unit is token-based, not per-second.
Method: catalog row, then one draft
Step one is the catalog row. Step two is a 4-second 480p draft, which is the cheapest legal request. A completed job returns usage.cost, the Sume billable amount, so divide by 4 for a draft rate. Repeat once at 1080p to see how resolution scales, and keep both numbers in your budget sheet.
import os, requests
BASE = "https://api.sume.com/v1"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
models = requests.get(f"{BASE}/videos/models", headers=H).json()["data"]
row = next(m for m in models if m["id"] == "seedance-2.5")
print(row["supported_resolutions"], row["supported_durations"][:2], row["pricing_skus"])
job = requests.post(
f"{BASE}/videos",
headers={**H, "Idempotency-Key": "seedance-price-probe-480p"},
json={"model": "seedance-2.5", "prompt": "A gift box opening on a snowy table",
"resolution": "480p", "duration": 4},
).json()
print("poll:", job["polling_url"], "then read usage.cost and divide by 4")
Turn the probe into a budget
Once you have a draft rate, build the sheet the same way as the rows in the other posts: rate × seconds, rounded up per job, then clips × price. Suppose your 4-second 480p probe returns a cost of X dollars. Then ten 4-second drafts cost 10X, and a 15-second 1080p final costs 15 × (your 1080p rate). The formula is simple, and the number is the only unknown.
| Line | How to get it | Formula |
|---|---|---|
| Draft rate per second | usage.cost of a 4 s, 480p job | cost / 4 |
| Final rate per second | usage.cost of a 4 s, 1080p job | cost / 4 |
| Ten drafts of 4 s | draft rate | 10 x 4 x draft rate |
| Five finals of 15 s | final rate | 5 x 15 x final rate |
| Retry line | one in four finals | 1 or 2 x one final |
Why this beats a published number
Provider prices move, and the Sume docs name the date of each recorded list rate for a reason. A rate you measured today, from the same API your production job will call, includes the 1.25 factor and the rounding, which a number copied from a blog post does not. Idempotency keys make the probe safe to repeat.
If the figure matters to a client quote, ask the admission preview route what a request would reserve before you submit: the lip-sync docs name POST /v1/generation/admission-preview for exactly that purpose, and it takes the public id.
Sources
Related posts
More in Developers
- Seedance 2.5 reference video over 30 s: trim it first with Video Trim
fal lists Seedance 2.5 reference video and audio at 30 seconds in total. Cut a longer source to fit with Sume's video-trim, $0.02 a job, before you generate.
- Send a WAV file to MAI-Transcribe-2-Streaming: PCM16, no WAV header
MAI streaming wants raw PCM16 mono at 16 or 24 kHz as base64 in 10-20 ms chunks, no header. Python's wave module strips it; Sume's STT shape is 16 kHz mono.
- service_account_callback_domain_not_allowed 403: fix the callback host
The 403 means webhook_url's host is outside the key's allowed callback domains. An exact host or any subdomain of an allowed domain passes.
- Sume 429 concurrency cap or queue cap: which service-account limit?
service_account_concurrency_cap_exceeded counts active jobs; service_account_queue_cap_exceeded counts queued ones. Both are 429. Wait for a job to finish.
Written by Sume