API озвучки на Python: сохранить, получить потоком, повторить
Облачный API синтеза речи — самый короткий способ дать Python-скрипту голос: не нужно скачивать модель и иметь видеокарту, хватит одного HTTP-запроса. В гайде — API озвучки SuperClonica из Python с библиотекой requests: от первого файла до потоковой озвучки длинных текстов и обработки лимитов, как положено рабочему скрипту.
Нужен ключ: войдите в SuperClonica через Google или GitHub и создайте его в разделе «API озвучки» рабочего пространства. Бесплатный тариф даёт минуту звука в сутки.
Сохранить mp3
Храните ключ в переменной окружения и отправьте текст с голосом и языком:
import os, requests; KEY = os.environ["SUPERCLONICA_KEY"]; r = requests.post("https://superclonica.com/api/v1/speech", headers={"Authorization": "Bearer " + KEY}, json={"text": "Привет из Python!", "voice": "F1", "language": "ru", "format": "mp3"}, timeout=120); r.raise_for_status(); open("hello.mp3", "wb").write(r.content)
Без "format" ответ приходит в Ogg Vorbis — это самый маленький файл; доступен и wav. Один запрос принимает до 20 000 символов.
Длинный текст потоком
С "stream": true сервер отправляет звук, пока он ещё готовится, поэтому писать на диск или отдавать плееру можно с первого куска:
with requests.post("https://superclonica.com/api/v1/speech", headers={"Authorization": "Bearer " + KEY}, json={"text": long_text, "voice": "M2", "language": "ru", "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()
В наших замерах первый звук приходил от 300 мс при любой длине текста, а около 16 000 символов озвучивались за 25,6 секунды.
Голоса и лимиты
Список голосов, доступных ключу; у каждого есть id, имя, вид (stock, own, bought или catalog) и язык:
voices = requests.get("https://superclonica.com/api/v1/voices", headers={"Authorization": "Bearer " + KEY}, timeout=30).json()["items"]
Перед большой задачей проверьте остаток тарифа:
usage = requests.get("https://superclonica.com/api/v1/usage", headers={"Authorization": "Bearer " + KEY}, timeout=30).json(); print(usage["plan"], usage["available_seconds"])
Ошибки и повторы
Отправляйте с каждым запросом заголовок Idempotency-Key, например хеш текста: тогда запрос, повторённый после таймаута, дождётся той же задачи, а не озвучит и не посчитает текст дважды.
- 429: 10-минутное окно тарифа исчерпано; подождите секунды из Retry-After и отправьте снова.
- 503: очередь заполнена; подождите Retry-After секунд и отправьте снова с тем же ключом.
- 413: текст длиннее, чем тариф позволяет за одно окно; разделите его.
- 401: ключа нет, он неверный или удалён.
- Неудачный текст не учитывается в тарифе.