API de texto a voz
Síntesis de voz MiniMax Speech 2.8 HD y Turbo a través del endpoint compatible con OpenAI y del nativo: parámetros, voces del sistema, streaming y facturación por carácter.
HopBase sirve la síntesis de voz MiniMax Speech 2.8 en la misma Base URL y con la misma cabecera Authorization: Bearer sk-your-key que el resto de modelos: no hay un host ni una credencial de audio aparte. Los dos modelos de voz pertenecen a su propio grupo, MiniMax Speech oficial; una clave vinculada a un grupo de chat o video no llega a ellos.
MiniMax Speech 2.8 convierte texto en audio de forma síncrona: la respuesta es el propio audio, sin ninguna tarea que consultar. Los dos endpoints comparten la Base URL https://api.hop-base.com y la autenticación Bearer: el POST /v1/audio/speech compatible con OpenAI, para usarlo directamente con los SDK de OpenAI, y el nativo POST /v1/t2a_v2, con el conjunto completo de parámetros de MiniMax y streaming.
| ID de modelo | Posicionamiento | Límite de texto |
|---|---|---|
speech-2.8-hd | Máxima calidad | 4,096 caracteres en /v1/audio/speech, 10,000 en /v1/t2a_v2 |
speech-2.8-turbo | Más rápido y con tarifa menor | igual |
Los ID distinguen mayúsculas y minúsculas y no tienen alias; tts-1 / tts-1-hd no se reconocen. Use una clave con el grupo MiniMax Speech oficial habilitado y confirme los ID con GET /v1/models.
Endpoint compatible con OpenAI
POST /v1/audio/speech acepta la estructura de solicitud de OpenAI y responde con los bytes de audio sin envolver.
| Campo | Valores | Notas |
|---|---|---|
model | speech-2.8-hd / speech-2.8-turbo | obligatorio |
input | texto, hasta 4,096 caracteres | obligatorio |
voice | un ID de voz de MiniMax como English_expressive_narrator o Chinese (Mandarin)_News_Anchor, o un nombre de OpenAI (alloy, nova, …) | los nombres de OpenAI caen en una voz predeterminada elegida según el idioma del texto: mandarín si contiene caracteres chinos, inglés en caso contrario |
response_format | mp3 (predeterminado) / opus / flac / wav / pcm | aac no es compatible (400); opus se entrega en un contenedor OGG |
speed | 0.25-4 | fuera de ese rango devuelve 400; dentro de él, el valor se ajusta a 0.5-2 |
instructions | se acepta y se ignora | — |
stream_format no es compatible y devuelve 400. El Content-Type de la respuesta es audio/mpeg, audio/ogg, audio/flac, audio/wav o audio/pcm, según response_format.
curl https://api.hop-base.com/v1/audio/speech \
-H "Authorization: Bearer sk-tu-clave" \
-H "Content-Type: application/json" \
-d '{
"model": "speech-2.8-turbo",
"input": "Hola, mundo.",
"voice": "English_expressive_narrator",
"response_format": "mp3"
}' \
--output hola.mp3Con los SDK oficiales de openai solo cambian la Base URL y los valores de model / voice:
from openai import OpenAI
client = OpenAI(base_url="https://api.hop-base.com/v1", api_key="sk-tu-clave")
response = client.audio.speech.create(
model="speech-2.8-turbo",
voice="English_expressive_narrator",
input="Hola, mundo.",
response_format="mp3",
)
response.write_to_file("hola.mp3")
# Texto largo: escriba los bytes en disco a medida que llegan en lugar de acumular todo el clip
with client.audio.speech.with_streaming_response.create(
model="speech-2.8-turbo",
voice="English_expressive_narrator",
input="Aquí va un guion más largo.",
) as streamed:
streamed.stream_to_file("largo.mp3")Endpoint nativo
POST /v1/t2a_v2 toma el cuerpo de solicitud T2A v2 de MiniMax tal cual: model, text (hasta 10,000 caracteres), voice_setting (voice_id, speed, vol, pitch, emotion), audio_setting (format, sample_rate, bitrate, channel), language_boost, stream y stream_options pasan sin cambios; cada campo y sus valores admitidos están en Parámetros de la solicitud. La respuesta JSON también sigue la estructura oficial: data.audio es el audio codificado en hexadecimal y extra_info incluye usage_characters y los metadatos del audio.
output_formatsolo admitehex(el predeterminado);urldevuelve 400.voice_setting.speedse ajusta a 0.5-2.- Con
audio_setting.format: "opus", indiquesample_ratede forma explícita (por ejemplo24000); sin él, la solicitud falla con un error de parámetro. stream: truecambia a SSE: cada eventodata: {...}lleva un fragmento de audio, y el evento final tienedata.status2másextra_info. Por defecto, eldata.audiode ese fragmento final es el audio completo agregado; usestream_options.exclude_aggregated_audio: truepara omitirlo.
import requests
resp = requests.post(
"https://api.hop-base.com/v1/t2a_v2",
headers={"Authorization": "Bearer sk-tu-clave"},
json={
"model": "speech-2.8-hd",
"text": "你好,世界",
"voice_setting": {"voice_id": "Chinese (Mandarin)_News_Anchor", "speed": 1.0},
"audio_setting": {"format": "mp3", "sample_rate": 32000},
},
)
body = resp.json()
open("hola.mp3", "wb").write(bytes.fromhex(body["data"]["audio"]))
print(body["extra_info"]["usage_characters"]) # caracteres facturadosStreaming: lea el cuerpo SSE línea a línea, decodifique el fragmento hexadecimal de cada evento data: y añádalo al archivo. Ponga exclude_aggregated_audio: true para que el evento final (status 2) lleve solo extra_info; de lo contrario su data.audio repite el clip completo y un append ingenuo duplica el audio.
import json
import requests
with requests.post(
"https://api.hop-base.com/v1/t2a_v2",
headers={"Authorization": "Bearer sk-tu-clave"},
json={
"model": "speech-2.8-turbo",
"text": "Aquí va un guion más largo.",
"stream": True,
"stream_options": {"exclude_aggregated_audio": True},
"voice_setting": {"voice_id": "Spanish_SereneWoman"},
"audio_setting": {"format": "mp3", "sample_rate": 32000},
},
stream=True,
timeout=(10, 300),
) as resp, open("largo.mp3", "wb") as out:
resp.raise_for_status()
for line in resp.iter_lines():
if not line.startswith(b"data:"):
continue
event = json.loads(line[5:])
data = event.get("data") or {}
if data.get("audio"):
out.write(bytes.fromhex(data["audio"]))
if data.get("status") == 2:
print(event["extra_info"]["usage_characters"]) # caracteres facturadosParámetros de la solicitud
El endpoint nativo acepta el cuerpo oficial de T2A v2. Los valores y predeterminados de abajo son los oficiales; la última columna indica dónde HopBase se comporta distinto o simplemente reenvía el campo.
Campos de nivel superior
| Campo | Valores | Predeterminado | Notas |
|---|---|---|---|
model | speech-2.8-hd / speech-2.8-turbo | — | obligatorio |
text | hasta 10,000 caracteres | — | obligatorio; separe los párrafos con saltos de línea; controles en línea más abajo. Oficialmente se recomienda streaming a partir de 3,000 caracteres |
stream | true / false | false | true cambia la respuesta a SSE |
stream_options.exclude_aggregated_audio | true / false | false | true quita el audio completo del fragmento final |
language_boost | auto, o uno de Chinese, Chinese,Yue, English, Arabic, Russian, Spanish, French, Portuguese, German, Turkish, Dutch, Ukrainian, Vietnamese, Indonesian, Japanese, Italian, Korean, Thai, Polish, Romanian, Greek, Czech, Finnish, Hindi, Bulgarian, Danish, Hebrew, Malay, Persian, Slovak, Swedish, Croatian, Filipino, Hungarian, Norwegian, Slovenian, Catalan, Nynorsk, Tamil, Afrikaans | sin definir | Refuerza el reconocimiento de ese idioma o dialecto; auto deja que el modelo lo detecte. Las voces en cantonés necesitan Chinese,Yue |
pronunciation_dict.tone | array de cadenas original/sustitución | — | La sustitución puede ser texto plano (omg/oh my god), pinyin con números de tono 1-5 entre paréntesis (处理/(chu3)(li3)), IPA entre paréntesis (resume/(rɪˈzjuːm)) o kana japonés (東京/トウキョウ); todas las reglas se aplican a la vez |
voice_modify | pitch, intensity, timbre: enteros de -100 a 100; sound_effects: spacious_echo / auditorium_echo / lofi_telephone / robotic | — | Semántica oficial: pitch más grave → más brillante, intensity más fuerte → más suave, timbre más lleno → más nítido; un solo efecto a la vez; mp3 / wav / flac sin streaming, solo mp3 con streaming. Se reenvía según la semántica oficial, sin validación en el lado de la pasarela |
output_format | hex | hex | url devuelve 400 |
voice_setting
| Campo | Valores | Predeterminado | Notas |
|---|---|---|---|
voice_id | un ID de voz del sistema, vea Voces del sistema | — | obligatorio |
speed | 0.5-2 | 1.0 | los valores fuera del rango se ajustan a él |
vol | mayor que 0, hasta 10 | 1.0 | volumen |
pitch | entero de -12 a 12 | 0 | 0 conserva el tono original |
emotion | happy / sad / angry / fearful / disgusted / surprised / calm / fluent / whisper | se elige automáticamente según el texto | Indíquelo solo cuando necesite una emoción fija. fluent y whisper están documentados para la serie 2.6; whisper no es compatible con Speech 2.8 de forma explícita |
text_normalization | true / false | false | Lectura normalizada de números en chino / inglés, con algo más de latencia |
latex_read | true / false | false | Solo chino; envuelva las fórmulas en $$; fuerza language_boost a Chinese |
audio_setting
| Campo | Valores | Predeterminado | Notas |
|---|---|---|---|
format | mp3 / pcm / flac / wav / opus | mp3 | opus es Ogg/Opus y exige un sample_rate explícito |
sample_rate | 8000 / 16000 / 22050 / 24000 / 32000 / 44100 | no consta oficialmente; los ejemplos oficiales usan 32000 | — |
bitrate | 32000 / 64000 / 128000 / 256000 | no consta oficialmente; los ejemplos oficiales usan 128000 | solo mp3 |
channel | 1 / 2 | 1 | mono / estéreo |
force_cbr | true / false | false | tasa de bits constante; solo mp3 en streaming |
Controles en línea dentro del texto
- Pausa:
<#x#>conxen segundos, de 0.01 a 99.99 y hasta dos decimales (Hola<#0.5#>mundo). Colóquela entre dos segmentos pronunciables; dos marcas seguidas se rechazan. Cada marca se factura como 1 carácter. - Pronunciación en línea: justo después de la palabra objetivo, escriba entre paréntesis de ancho medio pinyin con números de tono 1-5, IPA o jyutping cantonés con tonos 1-6:
This is (he2)平, not (huo4)面.,pronounced (lɪv) as a verb,去街市買啲(sung3)。 - Interjecciones (solo Speech 2.8):
(laughs),(chuckle),(coughs),(clear-throat),(groans),(breath),(pant),(inhale),(exhale),(gasps),(sniffs),(sighs),(snorts),(burps),(lip-smacking),(humming),(hissing),(emm),(sneezes).
Voces del sistema
Use la columna voice_id tal cual: mayúsculas, espacios y paréntesis incluidos. Nombre es la etiqueta oficial.
voice_id | Idioma | Nombre |
|---|---|---|
English_expressive_narrator | Inglés | Expressive Narrator |
English_radiant_girl | Inglés | Radiant Girl |
English_magnetic_voiced_man | Inglés | Magnetic-voiced Male |
English_compelling_lady1 | Inglés | Compelling Lady |
English_Aussie_Bloke | Inglés | Aussie Bloke |
English_captivating_female1 | Inglés | Captivating Female |
English_Upbeat_Woman | Inglés | Upbeat Woman |
English_Trustworth_Man | Inglés | Trustworthy Man |
Chinese (Mandarin)_Reliable_Executive | Mandarín | Reliable Executive |
Chinese (Mandarin)_News_Anchor | Mandarín | News Anchor |
Chinese (Mandarin)_Unrestrained_Young_Man | Mandarín | Unrestrained Young Man |
Chinese (Mandarin)_Mature_Woman | Mandarín | Mature Woman |
Arrogant_Miss | Mandarín | Arrogant Miss |
Robot_Armor | Mandarín | Robot Armor |
Chinese (Mandarin)_Kind-hearted_Antie | Mandarín | Kind-hearted Antie |
Chinese (Mandarin)_HK_Flight_Attendant | Mandarín | HK Flight Attendant |
Japanese_IntellectualSenior | Japonés | Intellectual Senior |
Japanese_DecisivePrincess | Japonés | Decisive Princess |
Japanese_LoyalKnight | Japonés | Loyal Knight |
Spanish_SereneWoman | Español | Serene Woman |
Spanish_MaturePartner | Español | Mature Partner |
Spanish_CaptivatingStoryteller | Español | Captivating Storyteller |
Cantonese_GentleLady | Cantonés | Gentle Lady |
Las voces en cantonés necesitan language_boost: "Chinese,Yue". La tabla anterior es solo una selección inicial: todas las voces de la lista oficial de voces del sistema de MiniMax — 332 voces en 24 idiomas — funcionan aquí; pase el voice_id exactamente como aparece allí. Verificado el 2026-09-16: todas resuelven salvo Cantonese_ProfessionalHost (F) y Cantonese_ProfessionalHost (M), que figuran en la lista oficial pero el servicio rechaza con "voice id not exist". HopBase aún no ofrece un endpoint para consultar voces.
Rendimiento y tiempos de espera
Medido con texto corto (una o dos frases): los endpoints síncronos devuelven el clip completo en unos 1.5-2.4 s, y con stream: true el primer fragmento de audio llega en aproximadamente 1 s. La latencia crece con la longitud del texto, así que use streaming para todo lo largo (MiniMax recomienda streaming a partir de 3,000 caracteres) y escriba los fragmentos a medida que llegan, como en el ejemplo SSE de arriba. Para las solicitudes síncronas, siga la misma pauta de cliente que los demás endpoints síncronos en Concurrencia, tiempos de espera y facturación: un tiempo de lectura de 300 s o más.
Facturación
La voz se factura por carácter facturado. El recuento autoritativo es extra_info.usage_characters en la respuesta nativa; el endpoint compatible con OpenAI solo devuelve audio, así que consulte la misma cifra como tts_characters en el registro de uso de la consola. Cada carácter Unicode cuenta 1, y cada carácter chino (CJK) cuenta 1 más, de modo que un carácter chino cuenta 2; la puntuación, los espacios, los emoji y las marcas de pausa como <#0.5#> cuentan 1 cada uno.
Hello, world.→ 13 caracteres facturados你好,世界→ 5 caracteres, 4 de ellos chinos → 9 caracteres facturados
Una solicitud rechazada con 400 o que falla durante la síntesis no se factura, y un stream que termina antes del evento final tampoco. Los precios de lista oficiales por millón de caracteres están en la página de precios; la tarifa de su grupo aparece en el catálogo de modelos con la sesión iniciada.
Errores y recomendaciones
Todos los 400 tienen el cuerpo {"error":{"message":…,"type":"invalid_request_error","code":…}}; message nombra el campo problemático.
| Estado | Causa | Qué hacer |
|---|---|---|
| 400 | Parámetro inválido: un valor fuera de rango, stream_format, output_format: "url" u opus sin sample_rate | Corrija el campo que indica message; no reintente tal cual |
| 400 | ID de voz desconocido | Use un ID de Voces del sistema tal cual |
| 400 | Texto por encima del límite (4,096 / 10,000 caracteres) | Divida el guion y envíelo por partes |
| 400 | Formato no compatible, como response_format: "aac" | Use mp3 / opus / flac / wav / pcm |
| 402 | Saldo de la cuenta o cuota de la clave agotados | Recargue o amplíe la cuota de la clave; no reintente en bucle |
| 404 | El modelo no está en el grupo de la clave | Confírmelo con GET /v1/models |
| 429 | Límite de tasa o de concurrencia | Reintente según Retry-After y reduzca la concurrencia |
| 503 | No hay servicio disponible en este momento | Espere y reintente (2 s, 5 s, 15 s, hasta tres intentos) |
- Use una voz en mandarín para texto en chino.
- Divida usted mismo los guiones largos: 4,096 caracteres por solicitud en el endpoint compatible con OpenAI, 10,000 en el nativo.
- Envíe siempre
sample_ratejunto conopus.
Frente al TTS propio de OpenAI: no existe el nombre de modelo tts-1 (use los dos ID anteriores), stream_format no está disponible, instructions no tiene efecto y los valores de voice son ID de voz de MiniMax.
Video de Gemini Omni
gemini-omni-flash-preview devuelve un MP4 de 720p y 3-10 segundos de forma síncrona mediante la API de Interactions, facturado por token y no por segundo.
Modelos disponibles
Referencia rápida de los modelos de HopBase: qué ID se recomienda en cada familia, qué otros ID están disponibles, las reglas de facturación de contexto largo y qué guía consultar.