A text to speech API in Python: save, stream and retry
A cloud text to speech API is the shortest way to give a Python script a voice: no model to download, no GPU, one HTTP request. This guide shows the SuperClonica speech API from Python with the requests library, from the first file to streaming long texts and handling limits the way a production script should.
You need a key: sign in to SuperClonica with Google or GitHub and create one in the Speech API section of your workspace. The free plan gives a minute of audio a day.
Save an mp3
Keep the key in an environment variable and post the text with a voice and a language:
import os, requests; KEY = os.environ["SUPERCLONICA_KEY"]; r = requests.post("https://superclonica.com/api/v1/speech", headers={"Authorization": "Bearer " + KEY}, json={"text": "Hello from Python!", "voice": "F1", "language": "en", "format": "mp3"}, timeout=120); r.raise_for_status(); open("hello.mp3", "wb").write(r.content)
Without "format" the answer is Ogg Vorbis, the smallest file; wav is also available. A request takes up to 20,000 characters.
Stream a long text
With "stream": true the server sends the audio while it is still being made, so you can write it to disk or pipe it to a player from the first piece:
with requests.post("https://superclonica.com/api/v1/speech", headers={"Authorization": "Bearer " + KEY}, json={"text": long_text, "voice": "M2", "language": "en", "stream": True}, stream=True, timeout=120) as r: r.raise_for_status(); f = open("speech.ogg", "wb"); [f.write(chunk) for chunk in r.iter_content(8192)]; f.close()
In our measurements the first sound came from 300 ms whatever the length of the text, and about 16,000 characters were voiced in 25.6 seconds.
Voices and limits
List the voices your key may use; each item has an id, a name, its kind (stock, own, bought or catalog) and a language:
voices = requests.get("https://superclonica.com/api/v1/voices", headers={"Authorization": "Bearer " + KEY}, timeout=30).json()["items"]
Check what is left of your plan before a big job:
usage = requests.get("https://superclonica.com/api/v1/usage", headers={"Authorization": "Bearer " + KEY}, timeout=30).json(); print(usage["plan"], usage["available_seconds"])
Errors and retries
Send an Idempotency-Key header with every request, for example a hash of the text: a request repeated after a timeout then waits for the same task instead of voicing and counting the text twice.
- 429: the plan's 10-minute window is used up; wait the seconds in Retry-After and send again.
- 503: the queue is full; wait Retry-After seconds and send again with the same key.
- 413: the text is longer than your plan allows in one window; split it.
- 401: the key is missing, wrong or deleted.
- A failed text counts nothing against the plan.