Python TTS cost calculator: Sume job rounding vs per-character rates
A runnable Python function that prices narration lines on Sume (cent rounding, 1-cent minimum) and at flat per-million rates for MAI-Voice-2.1 and Flash.

Per-million prices hide a billing detail. Sume rounds each job up to the cent, with a one-cent minimum, so many tiny jobs cost more than one job of the same total length. Microsoft lists MAI-Voice-2.1 at $22 and Flash at $15 per million characters (Digital Applied, read 2026-10-06); the function below applies those as flat rates and does not model any rounding Microsoft might apply.
The function takes a list of job lengths in characters, so it answers both "one big job" and "one job per line".
The calculator
def sume_cents(chars):
return max(1, -(-chars * 19 // 4000)) # $0.0475 per 1,000, ceil to cent
def flat(chars, per_million):
return chars * per_million / 1_000_000
def report(jobs):
total = sum(jobs)
print("chars", total, "jobs", len(jobs))
print("sume $%.2f" % (sum(sume_cents(j) for j in jobs) / 100))
print("mai $%.4f" % flat(total, 22))
print("flash $%.4f" % flat(total, 15))
report([900])
report([90] * 10)
report([40] * 100)What it shows
| Split | Sume | MAI-Voice-2.1 | Flash |
|---|---|---|---|
| 1 job of 900 | $0.05 | $0.0198 | $0.0135 |
| 10 jobs of 90 | $0.10 | $0.0198 | $0.0135 |
| 100 jobs of 40 | $1.00 | $0.0880 | $0.0600 |
Takeaway
Batch lines into fewer jobs when audio is going to be one narration anyway. A hundred 40-character jobs cost $1.00 on Sume because each is rounded to the one-cent minimum, while the same 4,000 characters in one job is $0.19. The only constraint is the 20,000-character cap per job.
Sources
Related posts
More in Developers
- Python urllib timeout vs Sume's 30 second sync wait
A client read timeout shorter than Sume's sync wait fails before the server answers. A tested demo of the timeout behavior and how to pick a margin above 30 s.
- Python video fallback ladder when a model id is gone
A short Python ladder posts to Sume's /v1/videos with the first id that exists and moves on after a 404 model_not_found. Needs SUME_API_KEY, and runs.
- R httr2: submit an AI video job, poll it, and save the MP4 (Wan 3.0)
An R script posts a Wan 3.0 job to Sume with httr2, loops on /v1/jobs/{id}/status using next_poll_after_seconds and writes the finished clip to disk.
- Rails Sidekiq job that polls an AI video API with perform_in
A Sidekiq worker reads Sume's /v1/jobs/{id}/status once, then reschedules itself with perform_in using next_poll_after_seconds until the job is terminal.
Written by Sume