# Clarion: API hujjatlari

Clarion API o'zbek nutqini tinish belgilari, so'z vaqt belgilari va tovush hodisalari bilan matnga aylantiradi: fayllar REST orqali, jonli ovoz WebSocket orqali. API OpenAI bilan mos, shuning uchun OpenAI SDK'da faqat `base_url` o'zgaradi.

Asosiy URL: `https://api.uzasr.uz/v1`

## Autentifikatsiya

Kalit har bir so'rov sarlavhasida uzatiladi.

`uzasr_live_…` ko'rinishidagi kalit bir marta ko'rsatiladi. Uni brauzer yoki ilovada emas, serverda saqlang.

```http
Authorization: Bearer uzasr_live_…
```

## Tezkor boshlash

Faylni bitta so'rov bilan matnga aylantirish.

```python
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://api.uzasr.uz/v1",
    api_key=os.environ["UZASR_API_KEY"],
)

result = client.audio.transcriptions.create(
    model="uzasr-large",
    file=open("call.mp3", "rb"),
    response_format="verbose_json",
    timestamp_granularities=["word"],
)
print(result.text)
```

```javascript
import fs from "node:fs"
import OpenAI from "openai"

const client = new OpenAI({
  baseURL: "https://api.uzasr.uz/v1",
  apiKey: process.env.UZASR_API_KEY,
})

const result = await client.audio.transcriptions.create({
  model: "uzasr-large",
  file: fs.createReadStream("call.mp3"),
  response_format: "verbose_json",
  timestamp_granularities: ["word"],
})
console.log(result.text)
```

## Sinxron transkripsiya

10 daqiqagacha fayllar. Javob o'sha so'rovning o'zida keladi.

`POST /v1/audio/transcriptions`

| Parametr | Turi | Tavsif |
| --- | --- | --- |
| `file` | file | Audio yoki video: wav, mp3, m4a, ogg, flac, mp4, webm. |
| `model` | string | `uzasr-large` yoki `uzasr-base`, yoki aniq versiya. |
| `response_format` | string | `json`, `text` yoki `verbose_json`. Standart: `json`. |
| `timestamp_granularities[]` | string | `word`: so'z vaqt belgilari, faqat `verbose_json` bilan. |
| `language` | string | Ixtiyoriy. Faqat `uz` qo'llab-quvvatlanadi. |

## Javob formati

So'z vaqt belgilari va tovush hodisalari bilan `verbose_json`.

| Parametr | Turi | Tavsif |
| --- | --- | --- |
| `text` | string | Tinish belgilari bilan matn, lotin yozuvida. |
| `words[]` | object | `word`, `start`, `end`: so'z va uning soniyalardagi chegaralari. |
| `segments[]` | object | Chegaralari va matni bilan yozuv parchalari. |
| `events[]` | object | `label`, `start`, `end`, `score`. Belgilar: `laughter`, `applause`, `music`. Noma'lum belgilarni e'tiborsiz qoldiring. |

```json
{
  "task": "transcribe",
  "language": "uz",
  "duration": 28.0,
  "text": "Oyoqdagi yechish bilan shunaqa ovoz chiqaradiki, …",
  "segments": [
    { "id": 0, "start": 0.0, "end": 9.8, "text": "Oyoqdagi yechish bilan …" }
  ],
  "words": [
    { "word": "Oyoqdagi", "start": 0.12, "end": 0.64 }
  ],
  "events": [
    { "label": "laughter", "start": 2.28, "end": 2.52, "score": 0.557 },
    { "label": "applause", "start": 19.28, "end": 21.04, "score": 0.659 }
  ]
}
```

`X-Uzasr-Processing-Seconds` sarlavhasida navbat va ishga tushishsiz, GPU'dagi sof qayta ishlash vaqti bor.

## Asinxron vazifalar

3 soatgacha fayllar. Vazifa yarating va holatini so'rab turing.

`POST /v1/jobs` · `GET /v1/jobs/{id}`

O'sha `Idempotency-Key` bilan takroriy so'rov dastlabki vazifani qaytaradi. Holatlar: `queued`, `succeeded`, `failed`.

```python
import os
import time

import requests

API = "https://api.uzasr.uz/v1"
headers = {"Authorization": f"Bearer {os.environ['UZASR_API_KEY']}"}

job = requests.post(
    f"{API}/jobs",
    headers={**headers, "Idempotency-Key": "call-2026-10-21-0042"},
    files={"file": open("meeting.mp3", "rb")},
    data={"model": "uzasr-large"},
).json()

while job["status"] == "queued":
    time.sleep(5)
    job = requests.get(f"{API}/jobs/{job['id']}", headers=headers).json()

print(job["result"]["text"])
```

```javascript
import { openAsBlob } from "node:fs"

const API = "https://api.uzasr.uz/v1"
const headers = { Authorization: `Bearer ${process.env.UZASR_API_KEY}` }

const form = new FormData()
form.append("file", await openAsBlob("meeting.mp3"), "meeting.mp3")
form.append("model", "uzasr-large")

let job = await fetch(`${API}/jobs`, {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": "call-2026-10-21-0042" },
  body: form,
}).then((res) => res.json())

while (job.status === "queued") {
  await new Promise((resolve) => setTimeout(resolve, 5000))
  const poll = await fetch(`${API}/jobs/${job.id}`, { headers })
  job = await poll.json()
}

console.log(job.result.text)
```

## Real vaqt rejimi

WebSocket: kirishda PCM oqimi, chiqishda matn hodisalari.

`WS /v1/realtime?model=uzasr-large`

| Hodisa | Yo'nalish | Tavsif |
| --- | --- | --- |
| `ready` | ← server | Sessiya ochildi, modelning aniq versiyasi ko'rsatilgan. |
| `partial` | ← server | Joriy ibora. `stable` maydoni o'zgarmaydi, qolgani aniqlashtirilishi mumkin. |
| `final` | ← server | Ibora 0,8 s pauzadan keyin tinish belgilari bilan qayd etildi. |
| `event` | ← server | Tovush hodisasi, u tugaganidan 1–1,5 s keyin. |
| `done` | ← server | Sessiya yopildi, hisob uchun `audio_seconds`. |
| `binary` | → mijoz | PCM s16le, 16 kHz, mono. Tavsiya etilgan kadr hajmi 100 ms. |
| `stop` | → mijoz | `{"type":"stop"}`: oxirgi iborani qayd etish va sessiyani yopish. |

```text
wss://api.uzasr.uz/v1/realtime?model=uzasr-large

← { "type": "ready" }
→ <binary PCM s16le 16 kHz, 100 ms>
← { "type": "partial", "utterance": 0, "start": 0.0,
    "text": "Assalomu alaykum qanday", "stable": "Assalomu alaykum" }
← { "type": "final", "utterance": 0, "start": 0.0, "end": 2.4,
    "text": "Assalomu alaykum, qanday yordam bera olaman?" }
→ { "type": "stop" }
← { "type": "done", "audio_seconds": 2.9 }
```

Brauzer WebSocket'da sarlavhalarni uzatmaydi: o'z serveringizdan ulaning va oqimni proksi qiling.

## Modellar

Taxallus doim joriy versiyaga ishora qiladi.

`GET /v1/models`

| Model | Parametrlar | WER | Qachon tanlash kerak |
| --- | --- | --- | --- |
| `uzasr-large` | 600M | 8,1% | Standart tanlov, maksimal aniqlik |
| `uzasr-base` | 220M | 9,4% | Katta hajmlar, arzonroq narx |

- [600M model Hugging Face'da](https://huggingface.co/rustam1221/UzASR-CTC-600M)
- [220M model Hugging Face'da](https://huggingface.co/rustam1221/UzASR-CTC-220M)

## Xatolar

OpenAI bilan mos yagona format.

| HTTP | code | Nima bo'ldi |
| --- | --- | --- |
| 400 | `unsupported_parameter` | Noma'lum forma parametri. |
| 400 | `unsupported_language` | `language` parametri `uz` emas. |
| 400 | `audio_unreadable` | Audioni dekodlab bo'lmadi. |
| 400 | `audio_too_long` | Yozuv endpoint limitidan uzun. `/v1/jobs` endpointidan foydalaning. |
| 401 | `invalid_api_key` | Kalit uzatilmagan, noto'g'ri yoki bekor qilingan. |
| 404 | `model_not_found` | Bunday model yo'q. Ro'yxat: `GET /v1/models`. |
| 413 | `file_too_large` | Fayl limitdan katta. |
| 429 | `concurrency_limit_exceeded` | Parallel so'rovlar soni oshib ketdi. `Retry-After` sarlavhasiga qarang. |
| 503 | `model_unavailable` | Model ishga tushmoqda yoki texnik xizmatda. Bir daqiqadan keyin qayta urinib ko'ring. |
| 504 | `timeout` | Tanib olish belgilangan vaqtga sig'madi. Uzun fayllar uchun `/v1/jobs` endpointidan foydalaning. |

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_language",
    "message": "Only 'uz' is supported"
  }
}
```

## Limitlar

Standart qiymatlar. Korporativ mijozlar uchun sozlanadi.

| Cheklov | Qiymat |
| --- | --- |
| Sinxron so'rov | 10 daqiqagacha audio |
| Asinxron vazifa | 3 soatgacha audio |
| Bitta kalitga parallel so'rovlar | 8 |
| Real vaqt sessiyasi | 5 daqiqagacha |
| Vazifa natijasini saqlash | 7 kun |
