Preview Sume TTS sentence ids, lengths and job cost before you submit
A short Python script that splits a script like Sume's source API, groups sentences under 20,000 characters and prices each job at $0.0475 per 1,000 characters.

Before you accept a script and generate, you can predict three things offline: the sentence ids the source API will assign, the character count of each, and what each job will cost. The cost rule is Sume TTS's list price of $0.0475 per 1,000 characters, rounded up to the next cent per job, with a one-cent minimum and a 20,000-character cap per request.
Integer math avoids float surprises: cents = ceil(characters x 19 / 4000), which is the same as 4.75 cents per 1,000.
The script
It uses the same sentence rule as the source API (cut after ., !, ?), then packs consecutive sentences into jobs under the cap. It does not call the API, so it needs no key.
import re
def cents(chars):
return max(1, -(-chars * 19 // 4000))
def plan(text, cap=20000):
parts = [p for p in re.findall(r"[^.!?]*[.!?]|[^.!?]+\Z", text) if p.strip()]
jobs, cur = [], ""
for p in parts:
if cur and len((cur + p).strip()) > cap:
jobs.append(cur.strip())
cur = ""
cur += p
if cur.strip():
jobs.append(cur.strip())
return jobs
script = "Welcome back. Today we cover three tips! Ready? " * 400
jobs = plan(script)
for i, j in enumerate(jobs):
print(i, len(j), cents(len(j)))
print("total cents", sum(cents(len(j)) for j in jobs))What it prints
The sample script is 19,200 characters before trimming. Cost depends on how the packing lands, so run it on your own text. The per-job rounding is the only place the total can exceed a flat per-character estimate.
Caveats
- The server also adds a newline when a selection crosses a block boundary; keep a small margin under 20,000.
- This predicts the price of the literal characters. It does not know your voice or model; the table price is for Sume TTS 1.0 at the list rate.
- A sentence longer than the cap needs a rewrite; the splitter above would put it in a job of its own and the API would refuse it.
Sources
Related posts
More in Developers
- Why Sume's video models list shows 11 ids, not 12
Docs describe 12 video router ids, but GET /v1/videos/models can return 11. higgsfield-genjutsu lists only when its provider is configured. Check yours.
- Sume waitForJob pollInterval is a floor; next_poll_after_seconds wins
waitForJob never polls faster than pollInterval, and a longer next_poll_after_seconds from the server raises the gap. Defaults, timing table, sample.
- Sume webhook delivery statuses: pending, retrying, exhausted
A Sume webhook delivery moves through pending, delivering, delivered, retrying, failed or exhausted. What each means for your receiver.
- Sume webhook fails the 300-second window: find the clock drift
A valid Sume signature still fails if your server clock is more than five minutes off. Tell drift from a bad secret with a small Python check.
Written by Sume