Преминете към основното съдържание

WebSocket API

ASR сървърът предоставя WebSocket-базирано API за транскрипция на реч. Протоколът е прост 3-стъпков request-response цикъл през краткоживяща WebSocket връзка.

Endpoint​

ws://<host>:8765/ws/transcribe

При production deployment (чрез Cloudflare Tunnel):

wss://asr.dictaro.ai/ws/transcribe

Протокол​

Стъпка 1: Metadata (Client -> Server)​

Клиентът изпраща JSON text frame с параметри на заявката:

{
"type": "transcribe",
"language": "bg",
"task": "transcribe",
"api_key": "your-api-key",
"machine_id": "a1b2c3d4e5f6...",
"postprocess": true
}

Полета​

ПолеТипЗадължителноПо подразбиранеОписание
typestringда--"transcribe" за транскрипция или "ping" за health check
languagestring | nullнеnullISO 639-1 код на езика на речта. Ако е null, по подразбиране е "en"
taskstringне"transcribe""transcribe" -- текст на оригиналния език; "translate" -- превод на английски
api_keystringусловно--Задължителен, ако сървърът има конфигуриран SERVER_API_KEY
machine_idstringне"unknown"SHA256 хардуерен отпечатък за telemetry/billing
postprocessboolнеserver defaultOverride на LLM корекция per-request

Поддържани езици (25)​

bg, hr, cs, da, nl, en, et, fi, fr, de, el, hu, it, lv, lt, mt, pl, pt, ro, sk, sl, es, sv, ru, uk

Task стойности​

TaskОписаниеПример
transcribeТекст на оригиналния езикБългарска реч -> Български текст
translateПревод на английскиБългарска реч -> Английски текст

Machine ID (хардуерен отпечатък)​

machine_id е SHA256 хеш, изчислен от хардуерни компоненти на клиентската машина:

КомпонентИзточник (Windows WMI)
BIOS serialWin32_BIOS.SerialNumber
Motherboard serialWin32_BaseBoard.SerialNumber
Motherboard manufacturerWin32_BaseBoard.Manufacturer
Motherboard productWin32_BaseBoard.Product
CPU IDWin32_Processor.ProcessorId
Disk serialWin32_DiskDrive.SerialNumber (само фиксирани дискове)
machine_id = SHA256(bios_serial + board_serial + board_manufacturer + board_product + cpu_id + disk_serial)

OS серийният номер умишлено не е включен -- преинсталиране на OS не трябва да променя ID-то.

Стъпка 2: Аудио данни (Client -> Server)​

Клиентът изпраща WAV файл като binary WebSocket frame.

Изисквания към аудиото​

СвойствоСтойност
ФорматWAV (RIFF)
Sample rateПроизволен (сървърът resample-ва до 16kHz при нужда; 16kHz е препоръчителен)
КаналиMono
Bit depthFloat32 или Int16

Валидации​

Сървърът извършва следните проверки:

  1. Размер на файла -- максимум 50 MB (преди декодиране)
  2. WAV magic bytes -- проверка за RIFF и WAVE хедъри
  3. Продължителност -- максимум 300 секунди (5 минути) след декодиране

Стъпка 3: Резултат (Server -> Client)​

Сървърът изпраща JSON text frame с резултата:

{
"text": "Здравейте, как сте?",
"segments": [
{
"text": "Здравейте, как сте?",
"start": 0.0,
"end": 2.5
}
],
"language": "bg",
"postprocessed_text": "Здравейте, как сте?",
"postprocess_ms": 150,
"postprocess_error": null
}

Полета на резултата​

ПолеТипОписание
textstringСуров (raw) текст от ASR транскрипцията
segmentsarrayСегменти с text, start (секунди) и end (секунди)
languagestringДетектиран/използван език (ISO 639-1 код)
postprocessed_textstring | nullLLM-коригиран текст (ако post-processing е включен и успешен), иначе null
postprocess_msnumberЛатентност на post-processing в милисекунди (0, ако е изключен)
postprocess_errorstring | nullСъобщение за грешка, ако post-processing е неуспешен

Грешки​

При грешка сървърът изпраща JSON с поле error:

{
"error": "описание на грешката"
}

Често срещани грешки​

ГрешкаОписание
"unauthorized"Невалиден или липсващ API ключ
"File too large: X.XMB (max 50MB)"Файлът надвишава 50 MB лимита
"Invalid audio format: not a valid WAV file"Не е валиден WAV файл
"Audio too long: X.Xs (max 300s)"Аудиото е по-дълго от 5 минути
"GPU busy: server is processing another request..."GPU lock timeout (120s)

Ping / Health Check​

За проверка на свързаността без изпращане на аудио:

Заявка:

{
"type": "ping"
}

Отговор:

{
"type": "pong",
"status": "ok"
}

HTTP Health Endpoint​

GET /health

Отговор:

{
"status": "ok",
"model": "canary-1b-v2",
"postprocess_enabled": false
}

Примери​

Python (websockets)​

import json
import io
import soundfile as sf
from websockets.sync.client import connect

audio, sr = sf.read("recording.wav", dtype="float32")

with connect("ws://localhost:8765/ws/transcribe") as ws:
# 1. Изпращане на metadata
ws.send(json.dumps({
"type": "transcribe",
"language": "bg",
"task": "transcribe",
"api_key": "your-key",
"machine_id": "a1b2c3...",
"postprocess": True,
}))

# 2. Изпращане на аудио
buf = io.BytesIO()
sf.write(buf, audio, sr, format="WAV")
ws.send(buf.getvalue())

# 3. Получаване на резултат
result = json.loads(ws.recv())
if "error" in result:
print(f"Грешка: {result['error']}")
else:
text = result.get("postprocessed_text") or result["text"]
print(text)

JavaScript (browser)​

const ws = new WebSocket("ws://localhost:8765/ws/transcribe");

ws.onopen = () => {
// 1. Изпращане на metadata
ws.send(JSON.stringify({
type: "transcribe",
language: "bg",
task: "transcribe",
api_key: "your-key",
machine_id: "a1b2c3...",
}));

// 2. Изпращане на аудио като ArrayBuffer (WAV формат)
ws.send(wavArrayBuffer);
};

ws.onmessage = (event) => {
const result = JSON.parse(event.data);
if (result.error) {
console.error(result.error);
} else {
// Използване на postprocessed_text ако е наличен
const text = result.postprocessed_text || result.text;
console.log(text);
}
};

Telemetry (Prometheus метрики)​

Сървърът записва per-request метрики с label machine_id за usage tracking:

МетрикаТипLabelsОписание
asr_requests_totalCountermachine_id, task, status, languageОбщ брой заявки
asr_audio_seconds_totalCountermachine_id, task, languageОбработени аудио секунди
asr_processing_secondsHistogrammachine_id, task, languageОбща латентност на обработка
asr_postprocess_secondsHistogrammachine_id, task, languageЛатентност на LLM post-processing

PromQL примери​

# Общо заявки по машина
sum by (machine_id) (asr_requests_total)

# Общо аудио минути по машина
sum by (machine_id) (asr_audio_seconds_total) / 60

# Request rate за последния час
rate(asr_requests_total[1h])

# Средно време за обработка по машина
rate(asr_processing_seconds_sum[5m]) / rate(asr_processing_seconds_count[5m])