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
- 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.
- Rails Active Job that polls an AI video API: retry_job and wait
An Active Job on Solid Queue reads Sume's job status once and calls retry_job with wait from next_poll_after_seconds until the video job is terminal.
- Read Sume TTS raw PCM in Python: f32le samples at 24 kHz
Ask the TTS Router for container raw, 24000 Hz and pcm_f32le, then load the samples with the standard library for DSP or a custom player.
Written by Sume