Twilio Play 40-minute file limit vs Sume TTS 1,200-second cap
Twilio warns that a played file over 40 minutes can drop the call. Sume TTS fails audio past 1,200 seconds, so a hold message fits. Format and caching notes.

Twilio's <Play> documentation lists mp3, wav, aiff, gsm and ulaw as supported formats and warns that playing a file longer than 40 minutes can drop the call. Sume TTS fails any synthesized audio over 1,200 seconds (20 minutes) with tts_duration_exceeded, so a single Sume prompt can never hit Twilio's ceiling. Use mp3 for convenience or pcm_mulaw at 8,000 Hz for a phone-native file.
Twilio's page versus Sume's output
Twilio's page also recommends lossless 8 kbps formats over 128 kbps mp3 for voice, and notes that caching depends on ETag and Last-Modified headers.
| Item | Twilio Play | Sume TTS 1.0 |
|---|---|---|
| Formats | mp3, wav, aiff, gsm, ulaw | mp3, wav or raw; encodings pcm_f32le, pcm_s16le, pcm_mulaw, pcm_alaw |
| Length ceiling | Over 40 minutes can drop the call | Over 1,200 seconds fails with tts_duration_exceeded |
| Phone-native option | ulaw | pcm_mulaw at 8000 Hz |
| Text limit | n/a | 20,000 characters per request |
A phone-ready request
Ask for wav, pcm_mulaw and an 8,000 Hz sample rate. Host the artifact at a public HTTPS URL and point <Play> at it.
import os, requests
r = requests.post(
"https://api.sume.com/v1/tts-1.0/generate",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
"Idempotency-Key": "hold-msg-001"},
json={"transcript": "Thanks for holding. An agent will be with you soon.",
"avatar_id": os.environ["SUME_AVATAR_ID"],
"output_format": {"container": "wav", "encoding": "pcm_mulaw",
"sample_rate": 8000}},
)
print(r.status_code, r.json())Check before launch
Test the file on a real call. Whether Twilio treats your hosted URL as cacheable depends on the headers your host returns, which Twilio's page says matter.
Worked example
Think about the two ways this fails.
- Long file: a 45-minute recording will drop the call on Twilio even if the file is valid; Sume TTS refuses to produce more than 1,200 seconds anyway.
- Wrong format: an mp3 plays on Twilio, but Twilio's page recommends lossless 8 kbps formats for voice, which is why
pcm_mulawat 8,000 Hz is offered. - Cache surprises: Twilio's page says caching depends on ETag and Last-Modified.
Checklist before you commit
Host the file where you control headers if your prompt changes often.
- Test the prompt on a real handset.
- Keep hold messages short.
- Regenerate with a new filename when the text changes.
Sources
Related posts
More in Developers
- TypeScript 7: an exhaustive switch over Sume job statuses
Turn a Sume job record into done, failed, canceled or running with a never check, so a new status breaks the build. Compiled with tsc 7.0.2 in strict mode.
- Bulk run says completed but UGC variants failed: read counts
A Sume bulk queue is completed once every item is terminal, not once every item succeeds. Read counts.failed and each item's status before shipping.
- One bad item in a 100-variant bulk run: 400 and nothing runs
A Sume bulk run checks every item before it creates the queue. One bad row returns 400 invalid_request with details.index, and none of the 100 videos start.
- Re-ran a UGC variant bulk run and got the old queue: why
Replaying a Sume bulk-run Idempotency-Key with the same body returns 202 and the existing queue, no new videos. A changed body is 409. Mint a key per batch.
Written by Sume