Embeddings, audio și realtime
Vectori, speech-to-text, text-to-speech, voce realtime peste WebSocket și tokenii efemeri care fac clienții din browser siguri.
Dincolo de chat, gateway-ul servește patru suprafețe media OpenAI-compatibile. Acceptă aceeași cheie, aceleași rate limits și scriu aceleași înregistrări de usage — dar niciuna nu pornește o sarcină facturabilă, așa că nu contează niciodată la plafonul de sarcini.
Embeddings
POST /v1/embeddings. Modelul implicit codai-embed se rezolvă la voyage-code-3, ales pentru retrieval de cod. Input-ul este un string sau un array nevid de string-uri; opțional dimensions și user. Se acceptă doar encoding_format: "float".
curl https://ai.codai.ro/v1/embeddings \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "codai-embed", "input": ["salut lume", "vectorizează-mă"] }'{
"object": "list",
"model": "voyage-code-3",
"data": [
{ "object": "embedding", "index": 0, "embedding": [0.0123, -0.0456, …] },
{ "object": "embedding", "index": 1, "embedding": [0.0789, 0.0012, …] }
],
"usage": { "prompt_tokens": 7, "total_tokens": 7 }
}Dacă modelul de embedding cerut nu e disponibil, gateway-ul poate servi o alternativă compatibilă și o dezvăluie în x-codai-embed-fallback: <cerut>-><servit>. Verifici header-ul când spațiile vectoriale trebuie să rămână identice între scrieri și citiri.
Generare de imagini
POST /v1/images/generations, compatibil OpenAI, servit de modelele de imagine Google Gemini pe Vertex AI. Body: prompt (obligatoriu, ≤ 8 000 de caractere), model, n (1–4, implicit 1), size, aspect_ratio, image_size, reference_images, negative_prompt. Implicit, imaginile vin inline, în base64, împreună cu mime_type (response_format: "b64_json"). Cu response_format: "url" fiecare imagine e stocată ca asset, iar data conține obiecte asset cu un URL semnat valabil o oră (vezi Un URL în loc de octeți). Ai nevoie de o cheie API reală; token-urile efemere sunt respinse.
model | Backend | Regiune | image_size | Max. imagini de intrare | ≈ Preț per imagine 1K |
|---|---|---|---|---|---|
codai-image (implicit) | gemini-3.1-flash-image | eu | 512, 1K, 2K, 4K | 14 | 0,074 USD |
codai-image-fast | gemini-3.1-flash-lite-image | global | 1K | 4 | 0,034 USD |
codai-image-pro | gemini-3-pro-image | global | 1K, 2K, 4K | 14 | 0,134 USD |
Id-urile brute ale backend-ului sunt acceptate și ele ca model. gemini-2.5-flash-image (oprit de Google pe 2026-10-02), imagen-4 și imagen-4-fast sunt retrase upstream și sunt servite ca codai-image, deci clienții vechi funcționează în continuare. Regiunea care a procesat cererea apare în header-ul x-codai-data-region — codai-image rulează pe multi-regiunea Vertex eu, deci prompturile și imaginile rămân în UE.
aspect_ratio—1:1,2:3,3:2,3:4,4:3,4:5,5:4,9:16,16:9,21:9,9:21,1:4,4:1,1:8,8:1. Are prioritate față desize.size(stil OpenAI) se traduce într-un raport de aspect:1024x1024→ 1:1,1536x1024→ 3:2,1024x1536→ 2:3,1792x1024→ 16:9,1024x1792→ 9:16.image_size— rezoluția, implicit1K. O rezoluție pe care modelul nu o suportă dă 400.reference_images—[{ "b64_json": "…", "mime_type": "image/png" }](PNG, JPEG, WebP, HEIC, HEIF; ≤ 7 MB fiecare). Sunt trimise modelului înaintea promptului; așa păstrezi consecvente un logo, o paletă, un produs sau un personaj de la o generare la alta.
curl https://ai.codai.ro/v1/images/generations \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "codai-image", "prompt": "flat minimalist logo of a paper plane", "n": 1, "aspect_ratio": "1:1", "image_size": "1K" }' \
| jq -r '.data[0].b64_json' | base64 -d > plane.png{ "created": 1790000000, "data": [{ "b64_json": "iVBORw0KGgo…", "mime_type": "image/png" }] }Editare de imagini
POST /v1/images/edits modifică una sau mai multe imagini existente pe baza unei instrucțiuni — aceleași modele, limite și taxare. Trimiți JSON cu image (un {b64_json, mime_type} sau o listă de până la 14) ori un formular multipart/form-data în stil OpenAI, cu fișierul în image (sau image[] repetat). mask nu e suportat (400): descrie în prompt zona de modificat.
curl https://ai.codai.ro/v1/images/edits \
-H "Authorization: Bearer $CODAI_API_KEY" \
-F model=codai-image \
-F prompt="replace the background with a soft sunset gradient, keep the logo unchanged" \
-F image=@plane.png \
| jq -r '.data[0].b64_json' | base64 -d > plane-sunset.pngSDK-uri: client.images.generate(...) și client.images.edit(...) (TypeScript și Python, body JSON).
Proveniență
Imaginile de pe endpoint-ul UE poartă credențiale de conținut C2PA (un chunk caBX în PNG) și un watermark SynthID. Stochează și servește octeții exact cum îi primești — re-encodarea, redimensionarea sau ștergerea metadatelor elimină manifestul C2PA.
Taxare
Costul se calculează din tokenii raportați de model, la tarifele Vertex ale modelului rezolvat: tokenii imaginii generate cântăresc cel mai mult (o imagine 1K pe codai-image ≈ 0,074 USD; 2K ≈ 0,11 USD; 4K ≈ 0,17 USD), iar fiecare imagine de intrare sau de referință adaugă o fracțiune de cent. Costul apare în x-codai-cost-micro-usd, intră în plafoanele de cheltuieli și e debitat din portofelul preplătit în EUR (vezi Limite și prețuri). Plătești doar imaginile returnate efectiv: când filtrul de siguranță blochează toate imaginile, răspunsul e 400 cu codul content_filtered și nu se taxează nimic. Lasă până la 120 s per cerere.
Muzică și video (codai Studio)
Două lane-uri de media generativă pe Vertex AI. Ambele cer o cheie API reală, merg cel mai bine cu prompturi în engleză (Veo și Lyria 2 resping alte limbi, iar Lyria refuză prompturile care numesc artiști) și sunt procesate în SUA — conturile cu rezidență de date în UE primesc 400. Prețurile de mai jos sunt prețurile de listă upstream, în USD; costul upstream apare în x-codai-cost-micro-usd, iar portofelul preplătit în EUR e debitat la tariful codai pentru media (convertit în EUR cu adaosul pentru media), exact ca la imagini.
| Endpoint | Backend | Rezultat | Preț |
|---|---|---|---|
POST /v1/audio/music, codai-music (implicit) | Lyria 3 Clip | MP3 de 30 s cu voce și versuri (sau instrumental) | 0,04 USD per apel |
POST /v1/audio/music, codai-music-pro | Lyria 3 Pro | piesă întreagă de până la 184 s, MP3, voce, versuri, bpm, duration_seconds | 0,08 USD per apel |
POST /v1/audio/music, codai-music-legacy | Lyria 2 | WAV instrumental de 30 s, 48 kHz | 0,06 USD per clip |
POST /v1/videos + GET /v1/videos/{id} | Veo 3.1 Fast | MP4, 4/6/8 s, 720p sau 1080p, audio opțional | 0,10 USD pe secundă |
Muzică
POST /v1/audio/music e sincron: un clip codai-music durează circa 12 s, o piesă codai-music-pro 30–60 s (până la 4 minute pentru piese lungi) — setează un timeout de client de cel puțin 300 s. Body:
prompt(obligatoriu) — gen, stare, instrumente, structură; fără nume de artiști.model—codai-music(implicit),codai-music-prosaucodai-music-legacy.lyrics(≤ 3 000 caractere) — versurile de cântat exact;instrumental: true— fără voce;bpm(40–220);duration_seconds(10–184, doarcodai-music-pro;codai-musicare mereu circa 30 s);language— indiciu pentru limba versurilor, de exempluro.negative_prompt,seed,n(1–4) — doarcodai-music-legacy; trimise unui model Lyria 3, întorc400.response_format—b64_json(implicit) sauurl.
Fiecare element din data conține mime_type (audio/mpeg pentru Lyria 3, audio/wav pentru legacy), duration_seconds și, pentru Lyria 3, lyrics (așa cum au fost cântate, câte un rând [start:end]), caption (descrierea piesei făcută de model), lyrics_match și warnings. Când filtrul de siguranță blochează promptul, răspunsul e 400 content_filtered și nu se taxează nimic.
Versurile în română (și în alte limbi decât engleza) sunt best effort. Lyria 3 cântă cel mai sigur în engleză. Când trimiți lyrics, gateway-ul transcrie rezultatul și întoarce lyrics_match (0–1, 1 = cuvintele cântate se potrivesc cu ale tale); sub 0,6 adaugă avertismentul lyrics_mismatch — generează din nou sau simplifică versurile. Dacă verificarea nu poate rula, primești lyrics_match: null și lyrics_check_unavailable. Apelul se taxează în ambele cazuri.
curl --max-time 300 https://ai.codai.ro/v1/audio/music \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "codai-music-pro",
"prompt": "upbeat Romanian pop, female vocals, acoustic guitar and light synths",
"lyrics": "Vara asta e a noastră\nSoarele ne cheamă afară",
"language": "ro",
"bpm": 118,
"duration_seconds": 60
}' | tee song.json | jq -r '.data[0].b64_json' | base64 -d > song.mp3
jq '.data[0] | {duration_seconds, lyrics_match, warnings}' song.json{
"created": 1790000000,
"model": "codai-music-pro",
"data": [{
"b64_json": "SUQzB…",
"mime_type": "audio/mpeg",
"duration_seconds": 61.4,
"lyrics": "[0:6] Vara asta e a noastră\n[6:12] Soarele ne cheamă afară",
"caption": "Upbeat pop with acoustic guitar… bpm: 118, duration_secs: 61",
"lyrics_match": 0.82,
"warnings": []
}]
}Modelul instrumental anterior rămâne disponibil ca codai-music-legacy:
curl --max-time 180 https://ai.codai.ro/v1/audio/music \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "codai-music-legacy", "prompt": "calm lo-fi piano with soft vinyl crackle, 80 bpm", "negative_prompt": "vocals", "n": 1 }' \
| jq -r '.data[0].b64_json' | base64 -d > track.wavVideo
POST /v1/videos pornește un job și răspunde 202 cu { id, object: "video.job", status: "running", model, seconds, estimated_cost_micro_usd }. Body: prompt (obligatoriu), negative_prompt, seconds (4, 6 sau 8, implicit 8), aspect_ratio (16:9 implicit, sau 9:16), resolution (720p implicit, sau 1080p), audio (implicit true), image ({ b64_json, mime_type } — primul cadru, pentru image-to-video; forțează 8 s), seed.
Interogează GET /v1/videos/{id} la câteva secunde (un job durează de obicei 1–3 minute). status e running, succeeded (cu data[0].b64_json, video/mp4), failed sau filtered (filtrul de siguranță — nu se taxează nimic). Video-ul se taxează exact o dată, când jobul reușește — chiar dacă interogările ajung pe instanțe diferite ale gateway-ului; interogările ulterioare ale aceluiași job returnează din nou video-ul fără taxare. MP4-ul terminat e mereu stocat ca asset, deci apare și în GET /v1/assets?kind=video. Adaugă ?response_format=url la interogare ca să primești asset-ul (URL semnat) în locul base64 — recomandat pentru video-urile 1080p, care sunt mari. Id-ul jobului e semnat și legat de contul tău: alți utilizatori primesc 404.
ID=$(curl -s https://ai.codai.ro/v1/videos \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "prompt": "a paper plane gliding over a sunny city, cinematic", "seconds": 4 }' | jq -r .id)
until [ "$(curl -s https://ai.codai.ro/v1/videos/$ID -H "Authorization: Bearer $CODAI_API_KEY" | tee job.json | jq -r .status)" != "running" ]; do sleep 5; done
jq -r '.data[0].b64_json' job.json | base64 -d > plane.mp4SDK-uri: client.music.generate({ prompt }), client.videos.create(...) / .retrieve(id) și client.videos.generate({ prompt }), care creează jobul și interoghează până reușește (aruncă eroare la failed, filtered sau timeout). Python: client.music.generate({...}), client.videos.generate({...}, poll_interval=5.0, timeout=300.0).
Un URL în loc de octeți
response_format: "url" funcționează pe POST /v1/images/generations, POST /v1/images/edits, POST /v1/audio/music (câmp în body) și GET /v1/videos/{id} (parametru de query). Rezultatul e stocat ca asset timp de 90 de zile, iar fiecare element din data e un obiect asset în loc de { b64_json, … }:
{
"created": 1790000000,
"model": "codai-music-legacy",
"data": [{
"asset_id": "7d0f2c1e-…",
"kind": "music",
"status": "ready",
"model": "codai-music-legacy",
"url": "https://storage.googleapis.com/…&X-Goog-Signature=…",
"mime_type": "audio/wav",
"bytes": 5760044,
"duration_seconds": 30,
"width": null,
"height": null,
"created_at": "2026-10-10T08:00:00.000Z",
"expires_at": "2026-10-10T09:00:00.000Z"
}]
}url e un URL semnat valabil o oră, care nu cere cheia API, așa că îl poți pune direct într-un element <img>, <audio> sau <video>. Când expiră, apelează GET /v1/assets/{asset_id} pentru unul nou. Prețul și taxarea sunt identice cu b64_json. Un gateway fără stocare de asset-uri răspunde 503 cu codul assets_unavailable; acolo, b64_json implicit funcționează în continuare.
SDK-uri: trimite response_format: 'url' în body-ul pentru images.generate / images.edit / music.generate și citește result.assets; pentru video, trimite { responseFormat: 'url' } (în Python response_format="url") la videos.retrieve / videos.generate și citește result.asset.
Speech-to-text
POST /v1/audio/transcriptions, formular multipart, maximum 25 MB. Câmpuri: file (obligatoriu), model (implicit codai-transcribe) și opționalele language, prompt, response_format, temperature — trimise mai departe ca atare.
model | Backend |
|---|---|
codai-transcribe, codai-stt, whisper-1, whisper | Whisper |
gpt-4o-mini-transcribe | gpt-4o-mini-transcribe |
curl https://ai.codai.ro/v1/audio/transcriptions \
-H "Authorization: Bearer $CODAI_API_KEY" \
-F file=@sedinta.webm \
-F model=codai-transcribe \
-F language=ro{ "text": "Să începem cu checklist-ul de deploy." }Facturarea este fixă per minut de audio, estimată din dimensiunea încărcării (aproximativ 1 MB per minut de voce comprimată, minimum un minut) și înregistrată ca cost_micro_usd pe rândul de usage.
Text-to-speech
POST /v1/audio/speech. Body JSON: input (obligatoriu, ≤ 4 096 caractere), model (implicit codai-tts), voice, response_format (implicit mp3; merg și wav, opus, pcm), speed, instructions (≤ 1 000 caractere, doar modelele expresive), language (BCP-47, implicit ro-RO, folosit de modelele codai-speech), timestamps și store. Implicit, body-ul răspunsului sunt byte-ii audio.
model | Backend | Voce implicită | Preț (listă upstream) | Note |
|---|---|---|---|---|
codai-speech | Google Chirp 3 HD | Aoede | 30 USD / 1M caractere | Română nativă, 30 de voci, rapid (circa 1 s pentru o replică de 16 s). |
codai-speech-expressive | Gemini 2.5 Flash TTS | Kore | 0,50 USD / 1M tokeni de intrare + 10 USD / 1M tokeni audio | Română nativă, aceleași voci, ghidate prin instructions („vorbește cald și rar, ca un prezentator radio”). Circa 6 s pentru o replică de 16 s. |
codai-tts, tts-1, tts | TTS standard | alloy | fix per 1 000 caractere | Ieftin, neutru. |
codai-tts-expressive, gpt-4o-mini-tts | gpt-4o-mini-tts | marin | fix per 1 000 caractere | Acceptă instructions precum „calm, cald, română scurtă, ușor amuzat”. Voci: alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, verse, marin, cedar. |
Voci în română pentru codai-speech / codai-speech-expressive — trimite numele scurt în voice (devine <language>-Chirp3-HD-<Nume>) sau un nume complet de voce Google: Achernar, Achird, Algenib, Algieba, Alnilam, Aoede, Autonoe, Callirrhoe, Charon, Despina, Enceladus, Erinome, Fenrir, Gacrux, Iapetus, Kore, Laomedeia, Leda, Orus, Puck, Pulcherrima, Rasalgethi, Sadachbia, Sadaltager, Schedar, Sulafat, Umbriel, Vindemiatrix, Zephyr, Zubenelgenubi. Aceleași voci vorbesc și alte limbi când setezi language (de exemplu en-US).
curl https://ai.codai.ro/v1/audio/speech \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "codai-speech", "input": "Bună ziua! Bine ai venit la codai.", "voice": "Charon" }' \
--output salut.mp3Marcaje de timp per cuvânt și vorbire stocată
Setează timestamps: true și/sau store: true (orice model de vorbire) și răspunsul devine JSON în loc de byte-i audio:
words—[{ word, start, end }]în secunde, calculate printr-o transcriere făcută după sinteză (doar cutimestamps: true). Dacă transcrierea eșuează, cererea reușește totuși cuwords: nullși antetulx-codai-timestamps: unavailable.b64_json— audio-ul, cândstorenu e setat; sauasset— custore: trueaudio-ul e salvat ca asset studio de tipspeech(cuwordsîn metadate), pe care îl poți referi caasset:<asset_id>într-o randare, de exemplu pentru subtitrări.object: "audio.speech",model,voice,language,mime_type,duration_seconds,cost_micro_usd.
curl https://ai.codai.ro/v1/audio/speech \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "codai-speech", "input": "Bună ziua!", "language": "ro-RO", "timestamps": true, "store": true }'{
"object": "audio.speech",
"model": "codai-speech",
"voice": "Aoede",
"language": "ro-RO",
"mime_type": "audio/mpeg",
"duration_seconds": 1.1,
"asset": { "asset_id": "3f2b8c1e-…", "kind": "speech", "status": "ready", "url": "https://storage.googleapis.com/…", "…": "…" },
"words": [
{ "word": "Bună", "start": 0.12, "end": 0.48 },
{ "word": "ziua!", "start": 0.52, "end": 1.02 }
],
"cost_micro_usd": "300"
}Facturare: codai-tts* e fix per 1 000 caractere de input; codai-speech* urmează prețurile de listă upstream de mai sus. Prețurile sunt convertite în EUR cu adaosul codai pentru media și debitate din portofel; timestamps: true adaugă transcrierea la tariful speech-to-text. Costul upstream apare în cost_micro_usd / x-codai-cost-micro-usd. Ca și celelalte lane-uri din afara UE, modelele codai-speech nu sunt disponibile conturilor cu rezidență a datelor în UE.
Vorbire în streaming cu viseme (română)
POST /v1/audio/speech/stream transmite voci neurale Azure AI Speech ca Server-Sent Events: bucăți audio intercalate cu momentele visemelor și ale cuvintelor, pe același ceas audio, ca un avatar să sincronizeze buzele cât rulează sunetul. Model codai-tts-ro. Body: input (≤ 4 096 caractere, escapat XML în SSML, deci marcajele se citesc literal), voice (alina → ro-RO-AlinaNeural, implicit; emil → ro-RO-EmilNeural; sau orice nume de voce neurală Azure, de exemplu en-US-AvaNeural), response_format (pcm = PCM16 mono 24 kHz, implicit; sau mp3), speed (0.5–2.0).
| Eveniment SSE | data |
|---|---|
start | { "type": "start", "model", "voice", "format", "content_type", "sample_rate" } |
audio | { "type": "audio", "delta": "<bucată base64>" } |
viseme | { "type": "viseme", "id": 0-21, "offsetMs": 125 } — id de visemă Azure |
word | { "type": "word", "text": "Salut", "offsetMs": 50, "durationMs": 300 } |
done | { "type": "done", "audio_ms", "audioBytes", "visemes", "words" } |
error | { "type": "error", "error": { "code", "message" } } |
offsetMs se măsoară de la primul eșantion audio, deci programezi fiecare visemă la începutRedare + offsetMs.
curl -N https://ai.codai.ro/v1/audio/speech/stream \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "input": "Bună seara! Mulțumesc pentru trandafir!", "voice": "alina" }'Azure Speech rulează în westeurope, deci conturile cu rezidență de date în UE pot folosi acest lane. Facturare: 16 $ per 1M caractere de input, taxat doar după ce s-a produs audio; nu pornește niciodată o sarcină. Când gateway-ul nu are o cheie Azure Speech, ruta răspunde 503 cu codul tts_unavailable.
Tokeni efemeri
Browserele și webview-urile nu trebuie să dețină niciodată cheia ta de lungă durată. În schimb, generezi server-side un token de scurtă durată cu scop limitat cu POST /v1/tokens și îl dai clientului. Scopuri: realtime, audio, embeddings și live — un singur token care ajunge atât la /v1/realtime, cât și la /v1/audio/*, pentru un co-host live care ascultă și vorbește. Chat-ul nu poate fi generat intenționat. TTL 60–3 600 s, implicit 600.
curl https://ai.codai.ro/v1/tokens \
-H "Authorization: Bearer $CODAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "scope": "realtime", "ttl_seconds": 600 }'{ "token": "codai_eph_v1.…", "expires_at": "2026-09-23T12:10:00.000Z", "scope": "realtime" }Token-ul se folosește exact ca o cheie API — Authorization: Bearer codai_eph_v1.… — dar doar pe suprafața scopului său. Nu poate genera alți tokeni (403 forbidden). Revocarea cheii generatoare sau retrogradarea tier-ului ei invalidează tokenii în circulație în fereastra de cache a principalului.
Voce realtime
WSS /v1/realtime?model=<alias> — audio bidirecțional pe un singur WebSocket, retransmis ca atare către protocolul upstream.
model | Protocol | Backend |
|---|---|---|
codai-realtime (implicit pentru clienți în stil OpenAI) | OpenAI Realtime | gpt-realtime-2.1 |
codai-transcribe-live | OpenAI Realtime, intent=transcription | Doar STT în streaming — parțiale și evenimente de tură, fără răspuns de model |
codai-voice | Gemini Live BidiGenerateContent | gemini-live-2.5-flash-native-audio |
Dacă model lipsește, gateway-ul presupune codai-speech.
Parametrii transcrierii live
codai-transcribe-live acceptă doi parametri opționali în query:
language—ro,en,ro-RO, … Indiciul e scris în sesiunea de transcriere (session.audio.input.transcription.language), dacă propriul tăusession.updatenu setează deja unul.session_id— id-ul conversației tale, înregistrat pe rândul de usage (același câmp pe care îl completeazăx-codai-session-idpe rutele HTTP).
Cu language=ro și Deepgram configurat pe gateway, sesiunea rulează pe Deepgram Nova-3 (rezultate intermediare, punctuație, formatare inteligentă). Protocolul nu se schimbă: trimiți în continuare input_audio_buffer.append (PCM16 mono 24 kHz în base64), input_audio_buffer.commit și input_audio_buffer.clear și primești conversation.item.input_audio_transcription.delta și .completed. Delta-urile doar adaugă text; când Deepgram revizuiește cuvinte anterioare, delta-urile se opresc, iar .completed.transcript poartă textul final — consideră-l sursa de adevăr. Fiecare commit primește exact un .completed. Dacă Deepgram nu e configurat sau eșuează înainte să se deschidă socket-ul, sesiunea trece pe lane-ul Azure cu audio-ul deja trimis. upstream_model de pe rândul de usage îți spune ce lane a servit (deepgram:nova-3 sau gpt-live-transcribe), iar ttfb_ms e timpul până la primul delta de transcriere.
import { Codai } from 'codai-sdk';
// token generat server-side cu scope 'live'
const codai = new Codai({ apiKey: token });
const live = codai.realtime.connect({ model: 'codai-transcribe-live', language: 'ro', sessionId: 'stream-42' });
mic.onFrame((pcm24k: Int16Array) => live.appendAudio(pcm24k));
for await (const ev of live) {
if (ev.type === 'conversation.item.input_audio_transcription.delta') subtitrari.adauga(ev.delta);
if (ev.type === 'conversation.item.input_audio_transcription.completed') subtitrari.fixeaza(ev.transcript);
}Autentificarea upgrade-ului
Cheile brute codai_… sunt respinse în query string (cod de închidere 4401). Ar ajunge în log-uri de cereri, proxy-uri și istoricul browserului. Browserele trebuie să folosească un token efemer realtime sau live.
- Browser:
wss://ai.codai.ro/v1/realtime?model=codai-realtime&key=codai_eph_v1.… - Server: trimiți
Authorization: Bearer <cheie sau token>pe cererea de upgrade —?key=nu mai e necesar.
// token obținut de la backend-ul tău, care a apelat POST /v1/tokens
const ws = new WebSocket(
`wss://ai.codai.ro/v1/realtime?model=codai-realtime&key=${encodeURIComponent(token)}`,
);
ws.onopen = () => {
ws.send(JSON.stringify({ type: 'session.update', session: { instructions: 'Răspunde scurt.' } }));
};
ws.onmessage = (ev) => {
const event = JSON.parse(ev.data);
if (event.type === 'response.audio.delta') {
/* adaugi PCM-ul base64 la player */
}
};Coduri de închidere pe care le poți vedea: 4401 credențial invalid sau nepermis, 4503 lane-ul cerut nu e configurat pe acest gateway, 1011 eroare internă. Usage-ul se înregistrează la închiderea sesiunii, cu durata ei.
Ultima actualizare: