Asset-uri
Conținutul media Kodwen Studio stocat — listezi, obții un URL semnat proaspăt, descarci sau ștergi imaginile, muzica și video-urile generate.
Un asset este un fișier generat pe care gateway-ul îl păstrează pentru tine: fiecare imagine, clip muzical sau video produs cu response_format: "url" și fiecare job video terminat (MP4-ul e stocat mereu). Asset-urile aparțin utilizatorului care deține cheia API — id-ul asset-ului altui utilizator întoarce 404 — și se păstrează 90 de zile.
În loc de octeți base64 primești un obiect asset cu un URL semnat valabil o oră. URL-ul nu cere cheia API, așa că îl poți da unui browser, unui element <audio>/<video> sau unui utilitar de descărcare. Când expiră, ceri unul nou.
Agenții răsfoiesc biblioteca prin uneltele serverului MCP studio_assets_list (kind, before, limit) și studio_renders_list (before, limit, root_render_id). Ambele sunt doar citire și nu întorc niciodată URL-uri semnate; generarea media costă bani și nu e disponibilă prin ele.
Obiectul asset
{
"asset_id": "7d0f2c1e-4b8a-4c1e-9a51-0f3c2e8d9b10",
"kind": "video",
"status": "ready",
"model": "veo-3.1-fast-generate-001",
"url": "https://storage.googleapis.com/…&X-Goog-Signature=…",
"mime_type": "video/mp4",
"bytes": 1834221,
"duration_seconds": 4,
"width": null,
"height": null,
"created_at": "2026-10-10T08:00:00.000Z",
"expires_at": "2026-10-10T09:00:00.000Z"
}| Câmp | Semnificație |
|---|---|
asset_id | UUID stabil. Îl folosești ca să obții un URL proaspăt sau ca să ștergi asset-ul. |
kind | music, video, image, speech, render, upload sau sfx. |
status | pending, ready, failed sau deleted. Doar asset-urile ready au url. |
model | Modelul upstream care l-a produs. |
url | URL semnat al octeților, valabil o oră; null dacă nu e ready. Nu-l păstra în cache după expires_at. |
mime_type, bytes | Tipul de conținut și mărimea obiectului stocat. |
duration_seconds | Durata audio sau video; null pentru imagini. |
width, height | Pixeli, când sunt cunoscuți; altfel null. |
created_at | Momentul creării. Asset-ul e șters după 90 de zile. |
expires_at | Momentul în care url nu mai funcționează; null când nu există URL. |
Endpoint-uri
| Metodă | Cale | Rezultat |
|---|---|---|
GET | /v1/assets?kind=&before=&limit= | { object: "list", data: [asset…], next_before }, cele mai noi primele |
GET | /v1/assets/{id} | Un asset cu un url semnat proaspăt |
GET | /v1/assets/{id}/content | Redirecționare 302 către URL-ul semnat |
DELETE | /v1/assets/{id} | { id, object: "asset", deleted: true } |
POST | /v1/assets/uploads | 201 sesiune de upload { id, upload_url, chunk_granularity, max_bytes, expires_at } |
POST | /v1/assets/uploads/{id}/complete | { asset, ingest: { status, quote_micro_usd? } } |
GET | /v1/assets/quota | { used_bytes, limit_bytes, max_file_bytes } |
GET | /v1/assets/{id}/ingest | { status, error?, summary?, result?, sprite_url? } |
POST | /v1/assets/{id}/ingest | 202 { status, quote_micro_usd? } |
GET | /v1/assets/search?q=&limit= | { object: "list", data: [{ asset_id, t_ms, kind, score, text? }] } |
Listare
kind filtrează după tip, limit e între 1 și 100 (implicit 30). Pentru paginare, trimite next_before din răspunsul anterior ca before, până când next_before devine null.
curl "https://ai.codai.ro/v1/assets?kind=video&limit=20" \
-H "Authorization: Bearer $CODAI_API_KEY"Obținerea octeților
GET /v1/assets/{id} întoarce asset-ul cu un URL semnat nou. GET /v1/assets/{id}/content face același lucru și redirecționează către el, util cu curl -L. Redirecționarea are cache-control: private, no-store. Un asset fără conținut încă (pending) întoarce 404 pe /content.
curl -L -o plane.mp4 "https://ai.codai.ro/v1/assets/$ASSET_ID/content" \
-H "Authorization: Bearer $CODAI_API_KEY"Ștergere
DELETE /v1/assets/{id} șterge fișierul stocat și marchează asset-ul deleted; URL-urile deja emise nu mai funcționează. Ștergerea nu rambursează generarea.
Urcarea propriilor fișiere media
Poți urca video, audio și imagini de cel mult 4 GiB pe fișier și 50 GiB per utilizator (GET /v1/assets/quota). Octeții merg direct în Google Cloud Storage printr-o sesiune reluabilă, niciodată prin gateway:
POST /v1/assets/uploadscu{ filename, mime, bytes, ingest?, origin? }întoarce unupload_url. E un secret bearer pentru acel obiect — nu-l scrie în loguri. Trimiteorigincând urci din browser.- Trimite octeții cu
PUTlaupload_url, în bucăți multiple de 262144 octeți (8 MiB merge bine), fiecare cuContent-Range: bytes <primul>-<ultimul>/<total>și fără antetAuthorization.308înseamnă „continuă”: antetulRange: bytes=0-<n>arată cât a primit stocarea. Ultima bucată răspunde200/201. După o eroare de rețea, trimitePUTcu corp gol șiContent-Range: bytes */<total>și continuă de laRangeprimit. POST /v1/assets/uploads/{id}/completeverifică mărimea, marchează asset-ulready(kind: "upload") și pornește ingestia dacăingesta fosttrue(implicit).409 upload_incompleteînseamnă că nu au ajuns încă toți octeții.
Tipuri acceptate: video/mp4, video/quicktime, video/webm, video/x-matroska, audio/mpeg, audio/wav, audio/x-wav, audio/mp4, audio/aac, audio/flac, audio/ogg, audio/webm, image/png, image/jpeg, image/webp, image/gif, image/heic.
Ingestie și căutare
Ingestia analizează o singură dată un fișier video sau audio urcat, ca Studio și agenții să-l poată edita după conținut: transcriere cu timpi pe cuvânt și vorbitori, planuri cu un sprite sheet de cadre-cheie, beat-uri, urmărirea fețelor și a subiecților, semnale de loudness/claritate și embedding-uri pentru căutare. Prețul e pe minut de media și trece prin poarta de plată: suma e cotată și blocată în portofel înainte de pornirea jobului și decontată la final. Cu sold insuficient, complete raportează ingest.status: "insufficient_funds" (asset-ul rămâne ready), iar POST /v1/assets/{id}/ingest răspunde 402 insufficient_funds.
GET /v1/assets/{id}/ingest întoarce status (none, queued, running, succeeded, failed, insufficient_funds, unsupported); după succeeded include și summary, result complet (ingest.json, versiunea 1) și sprite_url (1 h). GET /v1/assets/search?q=mașină%20roșie găsește momente (t_ms) în toate fișierele tale analizate, potrivind cadre-cheie și segmente de transcriere.
Crearea asset-urilor
Cere response_format: "url" pe oricare endpoint media (vezi Embeddings, audio și realtime):
POST /v1/images/generationsșiPOST /v1/images/edits— câmp în body;POST /v1/audio/music— câmp în body;GET /v1/videos/{id}— parametrul de query?response_format=url.
Valoarea implicită rămâne b64_json, deci clienții existenți nu văd nicio schimbare. Video-urile se taxează exact o dată, iar MP4-ul lor e stocat indiferent de formatul cu care interoghezi.
Fiecare randare Studio terminată e stocată tot ca asset și apare la kind=render (GET /v1/assets?kind=render).
Efectele sonore importate din biblioteca gratuită de efecte sonore CC0 sunt asset-uri de tip kind=sfx.
Erori
| HTTP | code | Când |
|---|---|---|
| 400 | bad_request | kind, before (trebuie să fie dată-oră ISO) sau limit invalid. |
| 404 | not_found | Id necunoscut, asset-ul altui utilizator sau /content pe un asset fără conținut. |
| 400 | invalid_origin | origin din upload nu e o origine de browser permisă. |
| 402 | insufficient_funds | Portofelul nu acoperă cotația ingestiei. |
| 409 | upload_incomplete / asset_not_ready | complete înainte să ajungă toți octeții; ingestie pe un asset care nu e ready. |
| 413 | file_too_large / storage_quota_exceeded | Peste 4 GiB pe fișier sau 50 GiB per utilizator. |
| 415 | unsupported_media_type | Un tip în afara listei de mai sus sau ingestie pe o imagine. |
| 503 | ingest_unavailable / search_unavailable | Ingestia sau căutarea nu e configurată pe acest gateway. |
| 503 | assets_unavailable | Stocarea asset-urilor nu e configurată pe acest gateway. |
SDK-uri
import { Kodwen } from 'codai-sdk';
const client = new Kodwen({ apiKey: process.env.CODAI_API_KEY! });
const { assets } = await client.music.generate({ prompt: 'calm lo-fi piano', response_format: 'url' });
const url = await client.assets.contentUrl(assets[0]!.asset_id); // URL proaspăt, valabil o oră
for await (const a of client.assets.iterate({ kind: 'video' })) console.log(a.asset_id, a.bytes);
await client.assets.delete(assets[0]!.asset_id);from Kodwen import Kodwen
client = Kodwen(api_key=os.environ["CODAI_API_KEY"])
r = client.music.generate({"prompt": "calm lo-fi piano", "response_format": "url"})
url = client.assets.content_url(r.assets[0]["asset_id"])
for a in client.assets.iterate(kind="video"):
print(a["asset_id"], a["bytes"])
client.assets.delete(r.assets[0]["asset_id"])Ambele SDK-uri au și list(...), retrieve(id), content(id) (descarcă octeții de la URL-ul semnat) și contentPath(id) / content_path(id) (URL-ul de redirecționare autentificat).
Urcarea unui fișier, apoi citirea analizei și căutarea în el:
const file = new Blob([await readFile('interviu.mp4')]);
const { asset, ingest } = await client.assets.upload(file, {
filename: 'interviu.mp4',
mime: 'video/mp4',
onProgress: (sent, total) => console.log(`${Math.round((100 * sent) / total)}%`),
});
const state = await client.assets.ingest(asset.asset_id); // interoghează până când status e 'succeeded'
const hits = await client.assets.search('mașină roșie', { limit: 5 });done = client.assets.upload("interviu.mp4", on_progress=lambda sent, total: print(sent, total))
state = client.assets.ingest(done["asset"]["asset_id"])
hits = client.assets.search("mașină roșie", limit=5)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.
Randări
Randări Kodwen Studio — transformi o compoziție HyperFrames HTML (cu asset-urile tale Studio) într-un MP4, apoi interoghezi până când e gata.