One-job limits in Sume's TTS Router: v3 5,000, v4 10,000, Sonic 20,000

Each TTS Router id has its own max_characters. A Python planner splits a script on paragraph breaks so each request fits the row you picked.

6 min readSume
All posts

Every id in Sume's TTS Router has its own request ceiling: eleven-v3 takes 5,000 characters, eleven-v4, eleven-v4-turbo and eleven-multilingual-v2 take 10,000, and eleven-turbo-v2.5 and the sonic-* ids take 20,000. A transcript above the row's max_characters is rejected with a 400 before any credit is reserved, so split first and submit second.

The numbers are from the catalog in Sume's code on main, read 2026-10-11. ElevenLabs' own models page, read the same day, lists 10,000 characters for Eleven v4, 5,000 for v3 and 10,000 for Multilingual v2, so Sume matches those. Sume sets its own 20,000-character ceiling on the Turbo v2.5 row, which is lower than the 40,000 ElevenLabs lists for Flash v2.5.

What is the limit for each id?

The count is the length of the transcript string. Spaces and punctuation count.

max_characters per router id, Sume catalog and ElevenLabs models page, read 2026-10-11
Router idSume max_charactersRequests for a 45,000-character script
eleven-v35,0009
eleven-v410,0005
eleven-v4-turbo10,0005
eleven-multilingual-v210,0005
eleven-turbo-v2.520,0003
sonic-3.620,0003

Where should I split a script?

Split on a paragraph break, never in the middle of a sentence, so each file starts and ends on a natural stop. Eleven rows do not accept segmentation, so Sume will not cut the audio for you. Keep the same voice id and settings on every part, and set seed where the row accepts it for repeatable takes.

Leave a small margin under the limit. Sume checks the string length the way JavaScript does, which counts some emoji and rare symbols as two units, so a text full of them can read longer to the API than Python's len() says.

How do I plan the requests in Python?

The function below packs whole paragraphs into parts that fit the chosen id, and refuses a single paragraph that is already too long, because splitting it would mean cutting a sentence in half. It does not call the API.

import re

LIMITS = {"eleven-v3": 5000, "eleven-v4": 10000, "eleven-v4-turbo": 10000,
          "eleven-multilingual-v2": 10000, "eleven-turbo-v2.5": 20000,
          "sonic-3.6": 20000}

def plan(text, model, margin=200):
    limit = LIMITS[model] - margin
    parts, cur = [], ""
    for para in re.split(r"\n\s*\n", text):
        para = para.strip()
        if not para:
            continue
        if len(para) > limit:
            raise ValueError(f"one paragraph is {len(para)} characters")
        if cur and len(cur) + 2 + len(para) > limit:
            parts.append(cur)
            cur = para
        else:
            cur = f"{cur}\n\n{para}" if cur else para
    if cur:
        parts.append(cur)
    return parts

print(len(plan("First.\n\nSecond.", "eleven-v4")), "request(s)")

What does the split cost?

Nothing extra: price follows characters, so five 9,000-character parts on eleven-v4 cost the same as one imaginary 45,000-character request at $0.10 per 1,000 characters, which is $4.50. Each part is its own job with its own Idempotency-Key, so a retry of one part never bills the others. Join the finished MP3 files afterwards with Sume's timeline audio concat.

See Text to speech for long text for the Sonic version of the same plan.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume