OvozAI
EnglishРусскийO'zbekchaЎзбекчаالعربيةПолучить ключ API

OvozAI API

Расшифровка речи и озвучка текста для ваших приложений · https://api.ovozai.uz/v1

Быстрый стартНачать с ИИ-ассистентомАвторизацияЦеныРасшифровка записиЗадачи: длинные записи и ссылки YouTubeТаймкоды и субтитрыВебхукиОзвучка текстаБалансОшибкиОграниченияВаши данные

Быстрый старт

API OvozAI превращает речь в текст, а текст — в речь. Он создан для узбекского языка (латиница или кириллица) и так же хорошо работает с русским, английским и другими языками, на которых говорят в одной записи: каждая часть записывается на том языке, на котором её произнесли.

  1. Войдите на app.ovozai.uz и откройте раздел API, чтобы создать ключ.
  2. Отправьте запись:
curl https://api.ovozai.uz/v1/audio/transcriptions \
  -H "Authorization: Bearer $OVOZAI_API_KEY" \
  -F file=@voice.ogg

В ответ придёт текст:

{ "id": "6f1c…", "text": "Assalomu alaykum, …", "duration": 12.4, "credits": 12 }

Метод расшифровки устроен так же, как у OpenAI, поэтому библиотеки OpenAI работают с OvozAI — достаточно поменять базовый URL:

from openai import OpenAI

client = OpenAI(base_url="https://api.ovozai.uz/v1", api_key="ovz_…")
with open("lecture.mp3", "rb") as audio:
    result = client.audio.transcriptions.create(model="ovozai-transcribe", file=audio)
print(result.text)
import OpenAI from "openai";
import fs from "node:fs";

const client = new OpenAI({ baseURL: "https://api.ovozai.uz/v1", apiKey: process.env.OVOZAI_API_KEY });
const result = await client.audio.transcriptions.create({
  model: "ovozai-transcribe",
  file: fs.createReadStream("voice.ogg"),
});
console.log(result.text);

Начать с ИИ-ассистентом

Пользуетесь ChatGPT, Claude, Cursor или другим ассистентом для кода? Вставьте в него этот промпт, допишите, что вы делаете, — и у него будет всё, чтобы написать интеграцию. Промпт на английском, так ассистенты понимают его точнее всего; отвечать вам по-русски он их попросит сам.

I want to use the OvozAI API in my project. OvozAI does speech to text and text to speech, built for Uzbek (Latin or Cyrillic) and also good with Russian, English and recordings that mix languages. Help me integrate it: first ask me what I'm building and in which language/framework, unless I've said so below, then write working code. Reply to me in Russian.

What I'm building: <describe it here, e.g. "a Telegram bot in Python that transcribes voice messages">

## The API
- Base URL: https://api.ovozai.uz/v1
- Auth: header `Authorization: Bearer ovz_…` (my key; keep it on the server, read it from an environment variable such as OVOZAI_API_KEY, never ship it to a browser or app).
- Docs: https://api.ovozai.uz/docs

### Transcribe a file and wait for the text
POST /audio/transcriptions, multipart/form-data. OpenAI-compatible: the official OpenAI SDKs work with base_url set to https://api.ovozai.uz/v1 (model: "ovozai-transcribe").
- file (required): audio or video, up to 500 MB (ogg, mp3, m4a, wav, mp4, webm…)
- language (optional): "uz-Cyrl" writes Uzbek in Cyrillic; otherwise Latin. Other languages are written as spoken.
- response_format (optional): json (default) → {"id","text","duration","credits"}; text → plain text; verbose_json, srt or vtt → with timestamps (segments; add timestamp_granularities[]=word for word timings).
Response headers: OvozAI-Transcription-Id, OvozAI-Credits. A minute of audio takes a few seconds; an hour a few minutes.

### Jobs: long recordings and YouTube links
POST /transcriptions answers at once (202) with a job.
- A file as multipart (fields: file, language, timestamps=true|false, webhook_url), or JSON {"url": "https://www.youtube.com/watch?v=…", "language": …, "webhook_url": …} for a public YouTube video up to 3 hours (no timestamps for links).
- Job: {"id","status": "queued"|"processing"|"completed"|"failed","source","title","duration","credits","text","segments","words","error": {"code","message"}|null}
- GET /transcriptions/{id} (?format=text|srt|vtt for the result as a file), GET /transcriptions (latest, ?limit=), DELETE /transcriptions/{id}. Poll every few seconds, or use the webhook. Results are kept 7 days.
- Webhook: POST to webhook_url with {"id","type": "transcription.completed"|"transcription.failed","created_at","data": <job>}. Verify the OvozAI-Signature header "t=<unix time>,v1=<hex>": v1 = HMAC-SHA256 of "<t>.<raw body>" with my webhook secret (from the API page); reject if t is older than 5 minutes. Answer 2xx within 10 seconds; failed deliveries are retried.

### Text to speech
POST /audio/speech, JSON {"input": "<20–20000 characters>", "voice": "female"|"male"|<a voice name>, "response_format": "mp3"|"opus"|"wav"}. Answers with the audio bytes (OpenAI-compatible, model "ovozai-speech"). About a minute for 5,000 characters. Headers: OvozAI-Audio-Seconds, OvozAI-Credits.
- Voices (case doesn't matter): Zephyr (female, bright), Leda (female, youthful), Achernar (female, soft), Callirrhoe (female, easygoing), Charon (male, informative), Achird (male, friendly), Algieba (male, smooth), Iapetus (male, clear). "female" is Zephyr (the default), "male" is Charon.
- Expressions: sounds go inside input in angle brackets, in English whatever the text's language, where they should be heard: <laugh>, <chuckle>, <sigh>, <gasp>, <breath>, <cough>, <cry>, <short pause>, <long pause>; <whispers> whispers to the end of the sentence. They're not read aloud. A word in CAPITALS is stressed.

### Balance
GET /balance → {"credits","available_credits","unlimited","top_up_url"}.

### Prices (credits, rounded down)
- Transcription: 1 credit per second of audio (files and YouTube links)
- With timestamps: 2 credits per second
- Text to speech: 400 credits per 1,000 characters
- No speech, failures and jobs cancelled before they start cost nothing.

### Errors and limits
Errors: HTTP status + {"error": {"code","message"}}. 400 invalid_request/file_missing/unreadable_file/unsupported_url/timestamps_unavailable, 401 unauthorized, 402 insufficient_balance (message says how many credits are needed), 404 not_found, 409 not_ready/conflict, 413 file_too_large, 429 rate_limited/too_many_jobs, 502 transcription_failed/timestamps_failed/speech_failed (retry), 503 server_busy/links_unavailable (retry later).
Limits: 120 requests a minute per key; 2 transcriptions at a time per account (up to 20 waiting); 2 speech requests at a time.

## How to write it
- Use the OpenAI SDK where it fits (transcription, speech); plain HTTP for jobs, YouTube links and balance.
- Prefer jobs with a webhook (or polling) for recordings longer than a few minutes; the synchronous endpoint is fine for voice messages.
- Handle 402 by telling the user to top up, 429 by backing off, 502/503 by retrying with backoff.
- Keep the key out of client-side code and out of the repository.

Авторизация

Каждый запрос передаёт один из ваших ключей в заголовке Authorization:

Authorization: Bearer ovz_…

Ключ показывается один раз, при создании. Храните его на своём сервере: любой, у кого он есть, может тратить ваши кредиты. Ключей может быть несколько (например, по одному на приложение), и любой из них можно отозвать на странице API. Базовый URL — https://api.ovozai.uz/v1.

Цены

API оплачивается кредитами — это отдельный баланс, не связанный с вашим временем в боте и на сайте OvozAI. Один кредит — это секунда расшифровки:

Кредиты
Расшифровка (файл или ссылка YouTube)1 кредит за секунду аудио
Расшифровка с таймкодами (verbose_json, SRT, VTT)2 кредита за секунду аудио
Озвучка текста400 кредитов за 1 000 символов текста

Кредиты округляются только вниз: запись длиной 10,6 секунды стоит 10 кредитов (21 с таймкодами), 143 символа озвучки — 57. Записи без речи, неудавшиеся запросы и задачи, отменённые до начала, ничего не стоят. С первым ключом вы получаете 1 800 кредитов, чтобы попробовать.

КредитыРасшифровкаУзбекские картыМеждународные карты
36 00010 ч90 000 сум$8.99
180 00050 ч390 000 сум$38.99
720 000200 ч1 400 000 сум$138

Акция в честь запуска: кредиты 2× на первый пакет, если купить его не позднее 9 ноября (по ташкентскому времени).

Кредиты покупаются на сайте и не сгорают. На странице API видно, сколько потрачено по дням, и журнал всех списаний и неудавшихся запросов. Нужны большие объёмы? Напишите на info@ovozai.uz.

Расшифровка записи

POST /audio/transcriptions принимает аудио- или видеофайл (до 500 МБ; всё, что читает ffmpeg: ogg, mp3, m4a, wav, mp4, webm…) как multipart/form-data и отвечает, когда расшифровка готова. Минута аудио занимает несколько секунд, час — несколько минут. Для длинных записей удобнее задача.

Поле
fileобязательноеЗапись.
modelнеобязательноеЛюбое значение: модель выбирает OvozAI. Библиотекам OpenAI это поле нужно.
languageнеобязательноеuz-Cyrl — узбекский кириллицей, иначе латиницей. Другие языки записываются так, как на них говорят, что бы здесь ни стояло.
response_formatнеобязательноеjson (по умолчанию), text или с таймкодами (2 кредита за секунду): verbose_json, srt, vtt.
timestamp_granularities[]необязательноеword добавляет в verbose_json время каждого слова.

В ответе есть заголовки OvozAI-Transcription-Id и OvozAI-Credits (сколько это стоило). Запись без речи возвращается с пустым текстом и ничего не стоит.

Если соединение оборвётся до начала расшифровки, она отменяется и ничего не стоит. Если расшифровка уже началась, она завершится, и результат можно получить по её id в течение 7 дней.

Задачи: длинные записи и ссылки YouTube

POST /transcriptions сразу отвечает (202) задачей; потом вы запрашиваете её или получаете вебхук, когда она готова. Отправьте либо файл как multipart/form-data:

curl https://api.ovozai.uz/v1/transcriptions \
  -H "Authorization: Bearer $OVOZAI_API_KEY" \
  -F file=@lecture.mp4 \
  -F timestamps=true \
  -F webhook_url=https://example.com/ovozai

либо ссылку на видео YouTube как JSON (открытые видео или видео по ссылке длиной до 3 ч; на вашей стороне ничего не скачивается):

curl https://api.ovozai.uz/v1/transcriptions \
  -H "Authorization: Bearer $OVOZAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/watch?v=…"}'
Поле
file / urlобязательноеЗапись или ссылка YouTube.
languageнеобязательноеКак выше: uz-Cyrl — узбекский кириллицей.
timestampsнеобязательноеtrue, чтобы получить таймкоды (только для файлов, 2 кредита за секунду).
webhook_urlнеобязательноеПубличный адрес https://, который вызывается, когда задача выполнена или не удалась.

Задача:

{
  "id": "6f1c…",
  "object": "transcription",
  "status": "completed",          // queued, processing, completed или failed
  "source": "file",               // или "youtube"
  "title": "lecture.mp4",
  "url": null,                    // ссылка YouTube, для ссылок
  "language": "uz",
  "timestamps": true,
  "created_at": "2026-10-31T10:00:00.000Z",
  "completed_at": "2026-10-31T10:02:41.000Z",
  "duration": 1834.2,             // длина записи в секундах
  "credits": 3668,                // стоимость, когда задача выполнена или не удалась
  "text": "…",
  "segments": [{ "id": 0, "start": 0.42, "end": 3.1, "text": "…" }],
  "words": [{ "word": "Assalomu", "start": 0.42, "end": 0.93 }],
  "error": null                   // { "code", "message" }, если не удалась
}
Запрос
GET /transcriptions/{id}Задача. С ?format=text, srt или vtt — результат файлом.
GET /transcriptionsВаши последние задачи, сначала новые, без текста (?limit= до 100).
DELETE /transcriptions/{id}Удаляет задачу и её результат. Ожидающая задача отменяется и ничего не стоит; выполняющуюся можно удалить, когда она завершится.

Результаты удаляются через 7 дней после готовности.

Таймкоды и субтитры

С таймкодами OvozAI находит в записи место каждого слова расшифровки: вы получаете segments (фразы размером с субтитр: до 2 строк по 42 символа) и words либо то же самое в SRT или WebVTT. Они стоят 2 кредита за секунду записи и требуют саму запись, поэтому для ссылок YouTube недоступны. Если расставить таймкоды не удалось, весь запрос завершается ошибкой и ничего не стоит.

curl https://api.ovozai.uz/v1/audio/transcriptions \
  -H "Authorization: Bearer $OVOZAI_API_KEY" \
  -F file=@video.mp4 -F response_format=srt > video.srt

Вебхуки

Если у задачи есть webhook_url, на него приходит POST, когда задача выполнена или не удалась:

{
  "id": "evt_…",
  "type": "transcription.completed",   // или "transcription.failed"
  "created_at": "2026-10-31T10:02:41.000Z",
  "data": { …задача вместе с текстом… }
}

Ответьте любым 2xx в течение 10 секунд. Иначе вебхук придёт снова через 10 с, 1 мин, 10 мин, 1 ч (всего 5 попыток); задачу всегда можно запросить и самому.

Каждый вебхук подписан вашим секретом (он на странице API) в заголовке OvozAI-Signature: t=<unix-время>,v1=<подпись>, где подпись — HMAC-SHA256 от <t>.<тело запроса как есть> в hex. Прежде чем доверять телу, проверьте подпись и что t не устарел:

import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((part) => part.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  return fresh && crypto.timingSafeEqual(Buffer.from(v1, "hex"), Buffer.from(expected, "hex"));
}
import hashlib, hmac, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(part.split("=", 1) for part in header.split(","))
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    fresh = abs(time.time() - int(parts["t"])) < 300
    return fresh and hmac.compare_digest(parts["v1"], expected)

Озвучка текста

POST /audio/speech читает текст вслух естественным голосом (на узбекском, русском, английском и других языках) и отвечает аудио. Работает как метод озвучки OpenAI.

curl https://api.ovozai.uz/v1/audio/speech \
  -H "Authorization: Bearer $OVOZAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": "Assalomu alaykum! Bugun havo juda yaxshi.", "voice": "female"}' \
  --output speech.mp3
Поле
inputобязательноеТекст, от 20 до 20 000 символов.
voiceнеобязательноеfemale (по умолчанию, Zephyr), male (Charon) или любой из этих голосов по имени: Zephyr, Leda, Achernar, Callirrhoe, Charon, Achird, Algieba, Iapetus. Послушать их можно в приложении, на странице «Текст в речь».
response_formatнеобязательноеmp3 (по умолчанию), opus (Ogg Opus, как голосовые сообщения Telegram) или wav.
modelнеобязательноеЛюбое значение; не учитывается.

Звуки ставятся прямо в input, в угловых скобках, там, где их должно быть слышно: <laugh>, <chuckle>, <sigh>, <gasp>, <breath>, <cough>, <cry>, <short pause>, <long pause>. Пишите их по-английски, на каком бы языке ни был текст; вслух они не читаются. <whispers> читает шёпотом до конца предложения, а слово ЗАГЛАВНЫМИ звучит с ударением.

Salom! <laugh> Bugun havo juda yaxshi. <short pause> Keling, sayr qilamiz.

Стоит 400 кредитов за 1 000 символов в input, с округлением вниз. Длинный текст озвучивается не сразу: около минуты на 5 000 символов. Заголовки OvozAI-Audio-Seconds и OvozAI-Credits сообщают длину аудио и стоимость.

Баланс

GET /balance:

{
  "object": "balance",
  "unlimited": false,
  "credits": 34200,
  "available_credits": 30600,     // за вычетом того, что заняли ожидающие и текущие задачи
  "top_up_url": "https://app.ovozai.uz/buy/api"
}

Запрос отклоняется с 402, если ему не хватает available_credits: длина файла или видео известна до начала, поэтому это проверяется заранее.

Ошибки

Ошибки приходят с HTTP-статусом и телом вида {"error": {"code": "insufficient_balance", "message": "…"}}.

СтатусКодЗначение
400invalid_requestПоле отсутствует или заполнено неверно; какое — сказано в сообщении.
400file_missingВ поле file нет файла (или нет url).
400unreadable_fileФайл не является аудио или видео, которое может прочитать ffmpeg.
400unsupported_urlПринимаются только ссылки на видео YouTube.
400video_unavailable, live_video, too_longВидео закрыто или удалено, идёт в прямом эфире или слишком длинное.
400timestamps_unavailableТаймкоды запрошены для ссылки YouTube, или у задачи, созданной без таймкодов, запрошен формат, которому они нужны.
400input_too_short, input_too_longТекст для озвучки слишком короткий или слишком длинный.
401unauthorizedКлюч не передан, неверен или отозван.
402insufficient_balanceНе хватает кредитов; сколько нужно — сказано в сообщении.
404not_foundТакой задачи (или метода) нет.
409not_ready, conflictЗадача ещё не готова или выполняется.
413file_too_largeФайл больше 500 МБ.
429rate_limited, too_many_jobsСлишком много запросов или задач в очереди.
502transcription_failed, timestamps_failed, speech_failedВ этот раз не получилось. Ничего не списано; попробуйте ещё раз.
503links_unavailable, server_busyПопробуйте чуть позже.

Ограничения

  • Файлы до 500 МБ; видео YouTube до 3 ч.
  • До 2 расшифровок одновременно на аккаунт; остальные ждут своей очереди, всего до 20 ожидающих и выполняющихся.
  • До 2 запросов озвучки одновременно на аккаунт.
  • 120 запросов в минуту на ключ.

Ваши данные

Записи, отправленные через API, удаляются сразу после расшифровки, никогда не хранятся и не используются для улучшения наших моделей. Результаты хранятся 7 дней, чтобы вы могли их забрать, затем удаляются; удалить их раньше можно запросом DELETE /transcriptions/{id}. Исключение — расшифровки ссылок YouTube: их копию мы храним вместе со ссылкой, пока вы не удалите задачу. Текст для озвучки не хранится, как и аудио, созданное из него. Если вы отправляете чужие записи, вам нужно согласие этих людей, а своим пользователям стоит сообщить, что записи обрабатывает OvozAI. Подробнее — в политике конфиденциальности и условиях использования.

© 2026 OvozAI · info@ovozai.uz · Конфиденциальность · Условия