OvozAI API
تحويل الكلام إلى نص والنص إلى كلام لتطبيقاتك · https://api.ovozai.uz/v1
بداية سريعة
تحوّل واجهة OvozAI البرمجية الكلامَ إلى نص والنصَّ إلى كلام. صُمّمت للأوزبكية (بالحروف اللاتينية أو الكيريلية)، وتعمل بالجودة نفسها مع الروسية والإنجليزية وغيرها من اللغات التي يتحدث بها الناس في التسجيل الواحد: يُكتب كل جزء باللغة التي قيل بها.
- سجّل الدخول في app.ovozai.uz وافتح قسم API لإنشاء مفتاح.
- أرسل تسجيلًا:
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 Arabic.
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 000 | 10 ساعات | 90 000 UZS | $8.99 |
| 180 000 | 50 ساعة | 390 000 UZS | $38.99 |
| 720 000 | 200 ساعة | 1 400 000 UZS | $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 (التكلفة). يعود التسجيل الخالي من الكلام بنص فارغ ولا يكلّف شيئًا.
إذا انقطع الاتصال قبل بدء التفريغ، يُلغى ولا يكلّف شيئًا. وإذا كان قد بدأ، فإنه يكتمل ويمكن جلبه بمعرّفه خلال 7 أيام.
المهام: التسجيلات الطويلة وروابط YouTube
تجيب POST /transcriptions فورًا (202) بمهمة؛ ثم تجلبها أنت، أو يصلك Webhook عند اكتمالها. أرسل إما ملفًا بصيغة 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 (أسطر بحجم الترجمة المصاحبة، سطران كحد أقصى في كل منهما 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.srtWebhooks
إذا كان للمهمة 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 محاولات في المجموع)، ويمكنك دائمًا جلب المهمة بنفسك.
يُوقَّع كل واحد بسر Webhooks الخاص بك (في صفحة API) في ترويسة OvozAI-Signature: t=<unix time>,v1=<signature>، حيث التوقيع هو HMAC-SHA256 بصيغة hex لـ <t>.<raw body> (الجسم كما وصل، دون تعديل). تحقّق منه، ومن أن 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، مع التقريب إلى الأسفل. تستغرق النصوص الطويلة بعض الوقت: نحو دقيقة لكل 5000 حرف. تذكر الترويستان 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": "…"}}.
| الحالة | الرمز | المعنى |
|---|---|---|
| 400 | invalid_request | حقل مفقود أو خاطئ؛ تذكر الرسالة أيّ حقل. |
| 400 | file_missing | لا يوجد ملف في الحقل file (أو لا يوجد url). |
| 400 | unreadable_file | الملف ليس صوتًا أو فيديو يستطيع ffmpeg قراءته. |
| 400 | unsupported_url | تُقبل روابط فيديو YouTube فقط. |
| 400 | video_unavailable, live_video, too_long | الفيديو خاص أو محذوف، أو بث مباشر، أو طويل جدًا. |
| 400 | timestamps_unavailable | طُلبت طوابع زمنية لرابط YouTube، أو طُلبت صيغة تحتاجها من مهمة أُنشئت بدونها. |
| 400 | input_too_short, input_too_long | نص الكلام قصير جدًا أو طويل جدًا. |
| 401 | unauthorized | المفتاح مفقود أو خاطئ أو ملغى. |
| 402 | insufficient_balance | الأرصدة لا تكفي؛ تذكر الرسالة كم يلزم. |
| 404 | not_found | لا توجد مهمة كهذه (أو نقطة كهذه). |
| 409 | not_ready, conflict | المهمة لم تكتمل بعد، أو قيد التنفيذ. |
| 413 | file_too_large | حجم الملف أكبر من 500 ميغابايت. |
| 429 | rate_limited, too_many_jobs | طلبات كثيرة جدًا، أو مهام كثيرة جدًا في الانتظار. |
| 502 | transcription_failed, timestamps_failed, speech_failed | لم ينجح هذه المرة. لم يُخصم شيء؛ حاول مجددًا. |
| 503 | links_unavailable, server_busy | حاول مجددًا بعد قليل. |
الحدود
- ملفات حتى 500 ميغابايت، وفيديوهات YouTube حتى 3 ساعات.
- حتى 2 من عمليات التفريغ في وقت واحد لكل حساب؛ والبقية تنتظر دورها، حتى 20 بين منتظرة وجارية.
- حتى 2 من طلبات الكلام في وقت واحد لكل حساب.
- 120 طلبًا في الدقيقة لكل مفتاح.
بياناتك
تُحذف التسجيلات المرسلة عبر API فور تفريغها، ولا تُحفظ أبدًا ولا تُستخدم لتحسين نماذجنا. تُحفظ النتائج 7 أيام لتتمكن من جلبها، ثم تُحذف، ويمكنك حذفها قبل ذلك بـ DELETE /transcriptions/{id}. ويُستثنى من ذلك نصوص روابط YouTube: نحتفظ بنسخة منها مع الرابط إلى أن تحذف النتيجة. لا يُحفظ النص المرسل لتحويله إلى كلام، ولا الصوت الناتج عنه. إذا أرسلت تسجيلات أشخاص آخرين، فأنت بحاجة إلى إذنهم، وعليك إخبار مستخدميك بأن OvozAI يعالجها. راجع سياسة الخصوصية والشروط.