Una API de texto a voz en Python: guardar, transmitir y reintentar
Una API de texto a voz en la nube es el camino más corto para dar voz a un script de Python: sin descargar un modelo, sin GPU, una solicitud HTTP. Esta guía muestra la API de voz de SuperClonica desde Python con la biblioteca requests, desde el primer archivo hasta transmitir textos largos y manejar los límites como debe hacerlo un script en producción.
Necesitas una clave: entra en SuperClonica con Google o GitHub y créala en la sección de API de tu espacio de trabajo. El plan gratuito da un minuto de audio al día.
Guardar un mp3
Guarda la clave en una variable de entorno y envía el texto con una voz y un idioma:
import os, requests; KEY = os.environ["SUPERCLONICA_KEY"]; r = requests.post("https://superclonica.com/api/v1/speech", headers={"Authorization": "Bearer " + KEY}, json={"text": "¡Hola desde Python!", "voice": "F1", "language": "es", "format": "mp3"}, timeout=120); r.raise_for_status(); open("hello.mp3", "wb").write(r.content)
Sin "format" la respuesta llega en Ogg Vorbis, el archivo más pequeño; también hay wav. Una solicitud acepta hasta 20 000 caracteres.
Transmitir un texto largo
Con "stream": true el servidor envía el audio mientras aún se genera, así que puedes escribirlo en disco o pasarlo a un reproductor desde la primera parte:
with requests.post("https://superclonica.com/api/v1/speech", headers={"Authorization": "Bearer " + KEY}, json={"text": long_text, "voice": "M2", "language": "es", "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()
En nuestras mediciones el primer sonido llegó desde 300 ms sea cual sea la longitud del texto, y unos 16 000 caracteres se convirtieron en 25,6 segundos.
Voces y límites
Lista las voces que tu clave puede usar; cada elemento tiene un id, un nombre, su tipo (stock, own, bought o catalog) y un idioma:
voices = requests.get("https://superclonica.com/api/v1/voices", headers={"Authorization": "Bearer " + KEY}, timeout=30).json()["items"]
Comprueba lo que queda de tu plan antes de un trabajo grande:
usage = requests.get("https://superclonica.com/api/v1/usage", headers={"Authorization": "Bearer " + KEY}, timeout=30).json(); print(usage["plan"], usage["available_seconds"])
Errores y reintentos
Envía un encabezado Idempotency-Key con cada solicitud, por ejemplo un hash del texto: así una solicitud repetida tras un timeout espera la misma tarea en lugar de convertir y contar el texto dos veces.
- 429: la ventana de 10 minutos del plan está agotada; espera los segundos de Retry-After y envía de nuevo.
- 503: la cola está llena; espera Retry-After segundos y envía de nuevo con la misma clave.
- 413: el texto es más largo de lo que tu plan permite en una ventana; divídelo.
- 401: la clave falta, es incorrecta o se borró.
- Un texto fallido no cuenta en el plan.