Перейти к содержанию

OpenAI-совместимый API (аудио)

Методы распознавания и синтеза речи в формате OpenAI Audio API. Вы можете использовать официальный клиент openai, указав в нём base_url вашего экземпляра сервиса.

Настройка клиента

Задайте в клиенте два параметра:

  • Base URL: —
  • API-ключ: действующий ключ платформы (как и для остальных методов, см. Аутентификация).

Клиент openai передаёт ключ по схеме Authorization: Bearer <ключ> — эта схема поддерживается, поэтому достаточно указать ключ в api_key:

from openai import OpenAI

client = OpenAI(
    base_url="<BASE_URL>",
    api_key="<ваш-ключ>",
)

Распознавание речи (STT)

POST /api/v1/audio/transcriptions

Метод соответствует client.audio.transcriptions.create(). Запрос отправляется в формате multipart/form-data.

Модели

Модель Описание Стриминг
SpeechExpert-STT-RU Файловое распознавание русской речи, в том числе телефонных записей используйте SpeechExpert-STT-RU-stream
SpeechExpert-STT-UZ Файловое распознавание узбекской речи используйте SpeechExpert-STT-UZ-stream
SpeechExpert-STT-EN Файловое распознавание английской речи нет
Parakeet-EN Английская речь да (stream=true)
SpeechExpert-STT-RU-stream Потоковая выдача результата для русской речи да (stream=true)
SpeechExpert-STT-UZ-stream Потоковая выдача результата для узбекской речи да (stream=true)
SpeechExpert-STT-KK-stream Потоковая выдача результата для казахской речи да (stream=true)
SpeechExpert-STT-TG-stream Потоковая выдача результата для таджикской речи да (stream=true)
Whisper-Large-v3-Turbo Whisper Large v3 Turbo (офлайн) нет
GigaAM-Multilingual-Large-CTC Файловое распознавание для ru, kk, ky нет
ElevenLabs-Scribe-v2 Внешняя модель ElevenLabs для 75 курируемых языков, включая ru, en, kk, ky, uz, tg нет
ElevenLabs-Scribe-v2-Medical Scribe v2 для медицинской и клинической речи; тот же набор 75 языков нет
ElevenLabs-Scribe-v2-Realtime Потоковое распознавание через ElevenLabs для 75 языков сервиса; без дополнительного файлового уточнения только stream=true
gemini-3.5-transcribe Внешняя мультиязычная Gemini 3.5 Transcribe через Google API; публичный профиль включает ru, en, kk, ky, uz, tg нет

Для ElevenLabs-Scribe-v2 и ElevenLabs-Scribe-v2-Medical загруженный аудио- или видеоконтейнер передаётся провайдеру одним запросом. Поддерживается до пяти каналов. Дублирующие каналы dual-mono перед отправкой сводятся в один, чтобы итоговый text не содержал повторов.

Medical использует model_id=scribe_v2_medical у провайдера и тот же тариф, что Scribe v2. Обе модели предназначены для файлового распознавания; для живой речи используйте отдельную ElevenLabs-Scribe-v2-Realtime через WebSocket или gRPC STT v3. Здесь она доступна с stream=true после загрузки файла; stream=false отклоняется. Короткий алиас scribe_v2_realtime также принимается. Языковой набор сервиса описан в разделе Языки и распознавание.

Для gemini-3.5-transcribe аудио передаётся Google API. Модель умеет возвращать нативные word timestamps и нативную диаризацию через STT v1/v3, однако короткий OpenAI-совместимый ответ json|text публикует только текст. Поэтому этот маршрут использует лимит до 60 минут; для режимов STT v1/v3 с word timestamps или диаризацией действует лимит 30 минут. Диаризация Gemini поддерживает до восьми спикеров.

Стриминг

Для потоковой выдачи результата передайте stream=true и потоковую модель, например SpeechExpert-STT-RU-stream для ru или SpeechExpert-STT-UZ-stream для uz. Также доступны SpeechExpert-STT-KK-stream для kk, SpeechExpert-STT-TG-stream для tg и Parakeet-EN для en. Для 75 языков сервиса можно выбрать ElevenLabs-Scribe-v2-Realtime. Файл сначала загружается целиком; живой аудиовход доступен через WebSocket и gRPC.

Параметры запроса

Параметр Тип Обязательный По умолчанию Описание
file file да — Аудио- или видеофайл с аудиодорожкой (WAV PCM/IEEE Float, MP3, M4A, MP4, MOV, WebM, MKV и др.)
model string нет SpeechExpert-STT-RU Идентификатор из таблицы моделей; для потокового ответа выберите совместимую потоковую модель
language string нет ru Короткий код языка, например ru, en, kk, ky, uz или tg; обе модели Scribe v2 также принимают 75 языков курируемого набора. Совместимость зависит от модели
response_format string нет json Формат ответа: json или text (при stream=false)
stream boolean нет false Потоковая выдача результата в формате SSE
prompt string нет — Принимается для совместимости с OpenAI, но сейчас не влияет на распознавание
temperature number нет — Принимается для совместимости с OpenAI, но сейчас игнорируется

Для GigaAM-Multilingual-Large-CTC поле language обязательно должно разрешаться в один из кодов публичного профиля ru, kk, ky; остальные значения отклоняются с HTTP 400 до чтения файла. Для других моделей действуют их собственные языковые ограничения.

Для kk и ky рекомендуется проверить качество GigaAM на своих записях, акцентах и словаре. Таджикский tg не поддерживается этой моделью. Он, как и ru, en, kk, ky, uz, доступен через gemini-3.5-transcribe и обе модели ElevenLabs Scribe v2.

OpenAI-совместимый метод использует короткие коды, в отличие от STT v1/v3:

OpenAI Audio STT v1/v3 Язык
ru ru-RU русский
en en-US английский
kk kk-KZ казахский
ky ky-KG кыргызский
uz uz-UZ узбекский
tg tg-TJ таджикский

Код языка не выбирает модель автоматически. Для казахского и кыргызского файла с локальной моделью передавайте language и model=GigaAM-Multilingual-Large-CTC. Для узбекского файла используйте language=uz и model=SpeechExpert-STT-UZ. Для таджикского выбирайте model=gemini-3.5-transcribe, model=ElevenLabs-Scribe-v2 или model=ElevenLabs-Scribe-v2-Medical; все три внешние модели совместимы со всеми кодами таблицы.

OpenAI-совместимый контракт с response_format=json|text возвращает только текст и не публикует таймкоды. Для результата с временной разметкой используйте STT v1 или STT v3.

Поле multipart file обычно содержит бинарный файл. Для совместимости можно передать в нём и чистую Base64-строку поддерживаемого аудио/видеоконтейнера: сервис распознает сигнатуру после декодирования. Data URL с префиксом data:...;base64, не поддерживается.

Ответ

Без стриминга (stream=false или параметр не указан).

При response_format=json:

{
  "text": "распознанный текст"
}

При response_format=text тело ответа — обычный текст (text/plain).

Потоковый ответ (SSE)

При stream=true и потоковой модели потоково выдаётся только ответ: файл сначала загружается целиком. Для живого входящего аудио используйте WebSocket или gRPC.

Для ElevenLabs-Scribe-v2-Realtime файл декодируется в mono PCM16 и передаётся ElevenLabs со скоростью, близкой к длительности аудио. Окончательные фразы выдаёт Realtime; Scribe v2 и Medical дополнительно не вызываются. Таймкоды провайдера появляются вместе с окончательными фрагментами; при их недоступности выдаются оценённые границы фразы без words. Завершение после последнего аудиофрагмента может занять до 15 секунд при стандартной настройке. Текст этой модели возвращается без восстановления пунктуации и нормализации сервиса, сохраняя соответствие пословным таймкодам. На сервере требуется ELEVENLABS_API_KEY, webhook не нужен; аудио передаётся внешнему сервису. Подробнее — Scribe Realtime.

Ответ — поток Server-Sent Events (SSE). События:

  • transcript.text.delta — очередной фрагмент текста;
  • transcript.text.done — завершение с полным текстом после восстановления пунктуации.

Кадры содержат только строку data:. Значения transcript.text.delta и transcript.text.done находятся в JSON-поле type, а не в отдельном поле SSE event:. После финального объекта поток завершается обычным EOF; маркер data: [DONE] не отправляется.

Помимо OpenAI-совместимых полей type, delta и text, Speech Expert добавляет тайминги, когда выбранная модель их вернула:

Поле Тип Описание
start_ms integer Начало текущей гипотезы или финального диапазона на шкале исходного аудио
end_ms integer Конец диапазона
timing_source string Источник таймингов, например native-asr
words object[] Слова с полями text, start_ms, end_ms

Пример промежуточного события:

data: {"type":"transcript.text.delta","delta":"добрый день","start_ms":340,"end_ms":1080,"timing_source":"native-asr","words":[{"text":"добрый","start_ms":340,"end_ms":720},{"text":"день","start_ms":760,"end_ms":1080}]}

Финальное событие сохраняет последний диапазон и полный список доступных слов:

data: {"type":"transcript.text.done","text":"Добрый день.","start_ms":340,"end_ms":1080,"timing_source":"native-asr","words":[{"text":"добрый","start_ms":340,"end_ms":720},{"text":"день","start_ms":760,"end_ms":1080}]}

Поля таймингов являются расширением Speech Expert и могут отсутствовать у модели, который не возвращает временные границы. Клиентам следует воспринимать их как необязательные. Если финальный текст отличается от предварительного, поле words у события done может отсутствовать. Клиенту, которому важны промежуточные тайминги, следует сохранять words из delta, а не рассчитывать только на финальный объект.

Если распознавание аварийно завершилось уже после отправки SSE-заголовков, сервер закрывает поток финальным transcript.text.done с накопленным текстом; отдельного error-события сейчас нет, а HTTP status остаётся 200. Критичным клиентам следует считать такой поток best-effort и отдельно контролировать полноту входной длительности.

Примеры использования

from openai import OpenAI

client = OpenAI(base_url="https://api.speech.example.com/api/v1", api_key="<ваш-ключ>")

with open("audio.wav", "rb") as f:
    transcript = client.audio.transcriptions.create(
        model="SpeechExpert-STT-RU",
        file=f,
        language="ru",
        response_format="json",
    )

print(transcript.text)
with open("audio.wav", "rb") as f:
    stream = client.audio.transcriptions.create(
        model="SpeechExpert-STT-RU-stream",
        file=f,
        language="ru",
        stream=True,
    )
    for event in stream:
        if hasattr(event, "delta") and event.delta:
            print(event.delta, end="", flush=True)
        if hasattr(event, "text") and event.type == "transcript.text.done":
            print("\n[Done]", event.text)
curl -X POST "https://api.speech.example.com/api/v1/audio/transcriptions" \
  -H "Authorization: Api-Key $API_KEY" \
  -F "file=@audio.wav" \
  -F "model=SpeechExpert-STT-RU" \
  -F "language=ru" \
  -F "response_format=json"
curl -X POST "https://api.speech.example.com/api/v1/audio/transcriptions" \
  -H "Authorization: Api-Key $API_KEY" \
  -F "file=@audio.wav" \
  -F "model=SpeechExpert-STT-RU-stream" \
  -F "language=ru" \
  -F "stream=true"

Синтез речи (TTS)

POST /api/v1/audio/speech

Метод соответствует client.audio.speech.create(). Тело запроса — application/json.

Параметры запроса

Параметр Тип Обязательный По умолчанию Описание
model string нет tts-1 Модель (игнорируется, оставлена для совместимости)
input string да — Текст для синтеза (до 4096 символов)
voice string нет первый доступный Имя встроенного голоса
response_format string нет mp3 Формат аудио: mp3, opus, aac, flac, wav, pcm
speed number нет 1.0 Скорость от 0.25 до 4.0

Только встроенные голоса

OpenAI-совместимый метод использует только встроенные голоса. GET /api/tts/v1/voices также возвращает пользовательские user-voice-*, но этот endpoint их не поддерживает. Для собственного голоса вызывайте POST /api/tts/v1. Если voice не найден среди встроенных, сервер без ошибки выбирает первый доступный голос.

Ответ

В ответе сервис возвращает бинарный аудиофайл. Тип содержимого зависит от response_format:

response_format Content-Type
mp3 audio/mpeg
opus audio/ogg
wav audio/wav
flac audio/flac
aac audio/aac
pcm audio/basic

Примеры использования

from openai import OpenAI

client = OpenAI(base_url="https://api.speech.example.com/api/v1", api_key="<ваш-ключ>")

response = client.audio.speech.create(
    model="tts-1",
    input="Привет, это синтез речи через OpenAI-совместимый API.",
    voice="elena-speech-expert-tts",
    response_format="mp3",
    speed=1.0,
)

with open("speech.mp3", "wb") as f:
    f.write(response.read())
curl -X POST "https://api.speech.example.com/api/v1/audio/speech" \
  -H "Authorization: Api-Key $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "tts-1",
    "input": "Привет, мир!",
    "voice": "elena-speech-expert-tts",
    "response_format": "mp3"
  }' \
  --output speech.mp3

Ошибки

Код Когда возникает
400 Пустой файл (STT), неизвестная модель, неподдерживаемый стриминг, ошибка декодирования/конвертации или отсутствие доступных голосов (TTS)
401 Не аутентифицирован (отсутствует или неверный API-ключ)
402 Недостаточно кредитов
413 Multipart-файл превышает серверный лимит загрузки
422 Некорректная форма или тело запроса, например неизвестен response_format
500 Внутренняя ошибка синтеза или распознавания
503 Сервис распознавания недоступен

Неизвестный голос (TTS)

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

Формат ошибки — JSON с полем detail:

{
  "detail": "Описание ошибки"
}

См. также