hubris
API Reference
API REFERENCE

POST /v1/audio/speech

Озвучка текста (TTS) — текст на входе, готовый аудиофайл на выходе. OpenAI-совместимый формат, работает официальный openai SDK.

Превращает текст в речь: озвучка статей и рассылок, голосовые ответы бота, аудиоверсии инструкций, реплики персонажей. OpenAI-совместимый формат — без переписывания работают openai Python/TypeScript SDK и любые клиенты под OpenAI Audio API: достаточно поменять base_url.

Ответ — сами байты аудио, а не JSON: сохраняйте их в файл или отдавайте плееру. Стрима по флагу нет — один POST возвращает один готовый ответ целиком (его можно читать потоково, но это всё тот же единственный ответ). Модели озвучки — в каталоге (фильтр «Озвучка») или запросом GET /v1/models?output_modalities=speech: MAI Voice, Aura-2, MiniMax Speech, Kokoro, Orpheus, Zonos, Voxtral TTS и другие.

Эндпоинт

POSThttps://api.hubris.pw/v1/audio/speech

Заголовки:

HeaderЗначение
AuthorizationBearer sk-gw-... (обязательно)
Content-Typeapplication/json

Тело запроса

ПолеТипПо умолчаниюОписание
modelstringID модели озвучки из каталога.
inputstringТекст для озвучки, до 50 000 символов. Тарифицируется по количеству символов.
voicestringГолос модели. Обязателен, у каждой модели свой набор — см. ниже.
response_formatstringзависит от моделиmp3 или pcm (16-bit LE). Если поле не передать, формат выбирает модель — как правило, это pcm; для файла на диске указывайте mp3 явно.

Дополнительные поля, которые понимает конкретная модель (например, скорость речи или инструкции по стилю), передаются ей как есть — схема их не отбрасывает. Тело запроса ограничено 1 МБ: это текст, а не медиа, лимита хватает с большим запасом.

Голоса

voice обязателен, и наборы голосов у моделей не пересекаются: где-то их два, где-то девяносто. Список голосов конкретной модели — в её карточке в каталоге. Часть провайдеров список не публикует — тогда берите значение из документации самой модели.

Если голос не из списка, который знает каталог, запрос отклоняется до обращения к модели — с кодом 400, code: "voice_not_supported", и в тексте ошибки перечислены доступные значения:

{
  "error": {
    "message": "Голос «нет-такого» недоступен у модели microsoft/mai-voice-2-flash. Доступные: en-US-Harper:MAI-Voice-2, …",
    "type": "invalid_request_error",
    "code": "voice_not_supported"
  }
}

Если голосов у модели много, в сообщении перечислены первые восемь и число оставшихся. За отклонённый таким образом запрос ничего не списывается.

Минимальный пример

Модель и голос всегда идут парой: сменили модель — берите голос из её карточки в каталоге.

curl -s https://api.hubris.pw/v1/audio/speech \-H "Authorization: Bearer sk-gw-..." \-H "Content-Type: application/json" \-d '{  "model": "microsoft/mai-voice-2-flash",  "voice": "en-US-Harper:MAI-Voice-2",  "input": "Привет! Это проверка озвучки.",  "response_format": "mp3"}' \--output speech.mp3
from openai import OpenAIclient = OpenAI(  base_url="https://api.hubris.pw/v1",  api_key="sk-gw-...",)# Модель и голос — из карточки модели в каталоге /modelsMODEL = "microsoft/mai-voice-2-flash"VOICE = "en-US-Harper:MAI-Voice-2"with client.audio.speech.with_streaming_response.create(  model=MODEL,  voice=VOICE,  input="Привет! Это проверка озвучки.",  response_format="mp3",) as response:  response.stream_to_file("speech.mp3")
import fs from "node:fs";import OpenAI from "openai";const client = new OpenAI({baseURL: "https://api.hubris.pw/v1",apiKey: "sk-gw-...",});// Модель и голос — из карточки модели в каталоге /modelsconst MODEL = "microsoft/mai-voice-2-flash";const VOICE = "en-US-Harper:MAI-Voice-2";const speech = await client.audio.speech.create({model: MODEL,voice: VOICE,input: "Привет! Это проверка озвучки.",response_format: "mp3",});fs.writeFileSync("speech.mp3", Buffer.from(await speech.arrayBuffer()));

Python-вариант с with_streaming_response читает тот же единственный ответ по мере поступления байтов — это удобно для длинного текста, но никакого пофразового стрима, как в чате, здесь нет.

Ответ

200 — тело целиком состоит из байтов аудио. JSON в успешном ответе не приходит, поэтому и поля usage в нём нет: расход по запросу смотрите в журнале.

ЗаголовокЗначение
Content-Typeaudio/mpeg при response_format: "mp3", audio/pcm при pcm.
Content-LengthРазмер аудио в байтах.
Cache-Controlno-store — ответ не кэшируется.

pcm — это сырые сэмплы без заголовка WAV: их либо скармливают плееру/микшеру напрямую, либо оборачивают в контейнер. Если нужен файл, который просто откроется двойным кликом, берите mp3.

Ошибки, наоборот, всегда приходят JSON-ом в обычном формате — по Content-Type ответа легко отличить одно от другого.

HTTP-коды

КодcodeКогда
200Успех, в теле — аудио.
400voice_not_supportedГолос не входит в набор этой модели (в тексте ошибки — доступные).
400invalid_requestТело не соответствует схеме: нет model, input или voice, неизвестный response_format, невалидный JSON.
401Ключ отсутствует / отозван / невалиден.
402insufficient_balanceНедостаточно средств на балансе.
404model_not_foundМодели с таким model не существует или это не модель озвучки.
413request_too_largeТело запроса больше 1 МБ.
429Превышен дневной лимит на ключе.
502pricing_unavailableУ модели нет ставки в каталоге — считать стоимость нечем, запрос не выполняется.
502no_audio_returnedМодель ответила успехом, но пустым телом. Списания нет, запрос стоит повторить.
502 / 503 / 504Транзиентные сбои провайдера, курса ЦБ или таймаут озвучки.

Формат тела ошибки и стратегия retry — Ошибки.

Биллинг

Озвучка тарифицируется за символы входного текста — не за токены и не за длительность получившегося аудио. Стоимость поэтому известна заранее: сколько символов отправили, столько и оплатили, независимо от того, насколько неторопливо модель их проговорила. Ставка каждой модели видна в её карточке в каталоге.

Списание — по факту выполненного запроса, в рублях; сумма попадает в журнал запросов вместе с моделью и временем. За отклонённые до обращения к модели запросы (voice_not_supported, model_not_found, невалидное тело) и за пустой ответ модели не списывается ничего.

Что дальше

  • POST /v1/audio/transcriptions — обратная задача: запись в текст.
  • Аудио в чате — модель рассуждает о записи или отвечает голосом внутри диалога.
  • Модели — как выбрать модель и прочитать её карточку.
  • Ошибки — что делать на 429/502.
  • Цены — как считается стоимость запроса.

Обновлено: