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 modeloPosicionamientoLímite de texto
speech-2.8-hdMáxima calidad4,096 caracteres en /v1/audio/speech, 10,000 en /v1/t2a_v2
speech-2.8-turboMás rápido y con tarifa menorigual

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.

CampoValoresNotas
modelspeech-2.8-hd / speech-2.8-turboobligatorio
inputtexto, hasta 4,096 caracteresobligatorio
voiceun 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_formatmp3 (predeterminado) / opus / flac / wav / pcmaac no es compatible (400); opus se entrega en un contenedor OGG
speed0.25-4fuera de ese rango devuelve 400; dentro de él, el valor se ajusta a 0.5-2
instructionsse 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.mp3

Con 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_format solo admite hex (el predeterminado); url devuelve 400.
  • voice_setting.speed se ajusta a 0.5-2.
  • Con audio_setting.format: "opus", indique sample_rate de forma explícita (por ejemplo 24000); sin él, la solicitud falla con un error de parámetro.
  • stream: true cambia a SSE: cada evento data: {...} lleva un fragmento de audio, y el evento final tiene data.status 2 más extra_info. Por defecto, el data.audio de ese fragmento final es el audio completo agregado; use stream_options.exclude_aggregated_audio: true para 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 facturados

Streaming: 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 facturados

Pará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

CampoValoresPredeterminadoNotas
modelspeech-2.8-hd / speech-2.8-turboobligatorio
texthasta 10,000 caracteresobligatorio; 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
streamtrue / falsefalsetrue cambia la respuesta a SSE
stream_options.exclude_aggregated_audiotrue / falsefalsetrue quita el audio completo del fragmento final
language_boostauto, 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, Afrikaanssin definirRefuerza el reconocimiento de ese idioma o dialecto; auto deja que el modelo lo detecte. Las voces en cantonés necesitan Chinese,Yue
pronunciation_dict.tonearray de cadenas original/sustituciónLa 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_modifypitch, intensity, timbre: enteros de -100 a 100; sound_effects: spacious_echo / auditorium_echo / lofi_telephone / roboticSemá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_formathexhexurl devuelve 400

voice_setting

CampoValoresPredeterminadoNotas
voice_idun ID de voz del sistema, vea Voces del sistemaobligatorio
speed0.5-21.0los valores fuera del rango se ajustan a él
volmayor que 0, hasta 101.0volumen
pitchentero de -12 a 1200 conserva el tono original
emotionhappy / sad / angry / fearful / disgusted / surprised / calm / fluent / whisperse elige automáticamente según el textoIndí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_normalizationtrue / falsefalseLectura normalizada de números en chino / inglés, con algo más de latencia
latex_readtrue / falsefalseSolo chino; envuelva las fórmulas en $$; fuerza language_boost a Chinese

audio_setting

CampoValoresPredeterminadoNotas
formatmp3 / pcm / flac / wav / opusmp3opus es Ogg/Opus y exige un sample_rate explícito
sample_rate8000 / 16000 / 22050 / 24000 / 32000 / 44100no consta oficialmente; los ejemplos oficiales usan 32000
bitrate32000 / 64000 / 128000 / 256000no consta oficialmente; los ejemplos oficiales usan 128000solo mp3
channel1 / 21mono / estéreo
force_cbrtrue / falsefalsetasa de bits constante; solo mp3 en streaming

Controles en línea dentro del texto

  • Pausa: <#x#> con x en 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_idIdiomaNombre
English_expressive_narratorInglésExpressive Narrator
English_radiant_girlInglésRadiant Girl
English_magnetic_voiced_manInglésMagnetic-voiced Male
English_compelling_lady1InglésCompelling Lady
English_Aussie_BlokeInglésAussie Bloke
English_captivating_female1InglésCaptivating Female
English_Upbeat_WomanInglésUpbeat Woman
English_Trustworth_ManInglésTrustworthy Man
Chinese (Mandarin)_Reliable_ExecutiveMandarínReliable Executive
Chinese (Mandarin)_News_AnchorMandarínNews Anchor
Chinese (Mandarin)_Unrestrained_Young_ManMandarínUnrestrained Young Man
Chinese (Mandarin)_Mature_WomanMandarínMature Woman
Arrogant_MissMandarínArrogant Miss
Robot_ArmorMandarínRobot Armor
Chinese (Mandarin)_Kind-hearted_AntieMandarínKind-hearted Antie
Chinese (Mandarin)_HK_Flight_AttendantMandarínHK Flight Attendant
Japanese_IntellectualSeniorJaponésIntellectual Senior
Japanese_DecisivePrincessJaponésDecisive Princess
Japanese_LoyalKnightJaponésLoyal Knight
Spanish_SereneWomanEspañolSerene Woman
Spanish_MaturePartnerEspañolMature Partner
Spanish_CaptivatingStorytellerEspañolCaptivating Storyteller
Cantonese_GentleLadyCantonésGentle 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.

EstadoCausaQué hacer
400Parámetro inválido: un valor fuera de rango, stream_format, output_format: "url" u opus sin sample_rateCorrija el campo que indica message; no reintente tal cual
400ID de voz desconocidoUse un ID de Voces del sistema tal cual
400Texto por encima del límite (4,096 / 10,000 caracteres)Divida el guion y envíelo por partes
400Formato no compatible, como response_format: "aac"Use mp3 / opus / flac / wav / pcm
402Saldo de la cuenta o cuota de la clave agotadosRecargue o amplíe la cuota de la clave; no reintente en bucle
404El modelo no está en el grupo de la claveConfírmelo con GET /v1/models
429Límite de tasa o de concurrenciaReintente según Retry-After y reduzca la concurrencia
503No hay servicio disponible en este momentoEspere 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_rate junto con opus.

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.

En esta página