# Soubory a média

> Převod dokumentů, tabulek, obrázků a zvuku na text a převod textu na řeč ve formátu MP3.

Dva pomocné endpointy, které fungují bez konverzace: data loader převede soubor na
prostý text (stejný převod, jaký AYETO používá při nahrávání do znalostní báze),
a převod textu na řeč vytvoří z textu soubor MP3. Oba se platí z
[osobních kreditů](account.md#kredity) uživatele, nebo z kreditu uživatele
v organizaci, když požadavek nese `organization_id`.

## Organizace a kredity

Oba endpointy přijímají volitelné `organization_id`. Požadavek pak běží v této
organizaci stejně jako požadavek [chatu](chat.md#organizace-a-kredity): platí ho kredit
uživatele v organizaci (sdílený zůstatek organizace nebo individuální rozpočet
uživatele, viz [kredity](account.md#kredity)) místo osobních kreditů. Uživatel klíče
musí být administrátor nebo člen organizace; hosté a uživatelé mimo ni dostanou `403`.
Bez `organization_id` se požadavek účtuje z osobních kreditů. Id organizací uživatele
vrací [výpis členství v organizacích](account.md#vypis-clenstvi-v-organizacich).

## Převod souboru na text

| | |
|---|---|
| Endpoint | `POST /api/v3/data-loader/load` |
| Rozsah | `ayeto.data_loader` |
| Limit požadavků | [default](conventions.md#limity-pozadavku) |

Pošlete soubor jako base64; odpověď obsahuje jeho text. Podle typu souboru se text
extrahuje přímo, nebo ho přečte AI model:

| Typ souboru | Typy MIME | Jak se text získá |
|---|---|---|
| Prostý text, CSV, Markdown, HTML, zdrojový kód | jakýkoli `text/*` a dále `application/json`, `application/ld+json`, `application/xml`, `application/xhtml+xml`, `application/javascript`, `application/ics` | Dekóduje se tak, jak je. UTF-8 se rozpozná; jiná kódování se odhadnou. |
| PDF | `application/pdf` | Extrahuje se textová vrstva, každá stránka s prefixem `PDF page: N`. Když má PDF příliš málo textu (naskenovaný dokument), jeho stránky se vykreslí a přečte je model s viděním. |
| Word | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` (`.docx`), `application/msword` (`.doc`) | Text se extrahuje. |
| Excel | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` (`.xlsx`), `application/vnd.ms-excel` (`.xls`) | Jedna sekce na list. U `.xlsx` hodnoty buněk s jejich adresami, vzorce a pojmenované oblasti; u `.xls` jen hodnoty buněk. Velmi velké sešity se oříznou po 100 000 neprázdných buňkách, s poznámkou na konci. |
| Obrázky | jakýkoli `image/*` | Text v obrázku přečte model s viděním. Když obrázek neobsahuje (téměř) žádný text, model místo toho obrázek popíše. |
| Zvuk | `audio/mpeg` (`.mp3`), `audio/wav`, `audio/wave`, `audio/x-wav` (`.wav`) | Přepíše ho model pro převod řeči na text. Dlouhé nahrávky se rozdělí a přepisují po částech. |

Jiné typy souborů (archivy, video, jiné zvukové formáty, prezentace) se nepřevádějí:
požadavek se odmítne s `422` `unsupported file type '<mime type>'` s uvedením typu,
jako který byl soubor zpracován, a nic se neúčtuje.

Typ MIME se bere v tomto pořadí: z pole `mime_type`, z hlavičky data URL v `data`
a nakonec rozpoznáním z obsahu souboru. Pokud typ znáte, pošlete ho explicitně;
rozpoznání není spolehlivé pro každý formát.

Endpoint nestanovuje vlastní limit velikosti, ale celý soubor putuje zakódovaný
v base64 v jednom těle JSON a převádí se, dokud je požadavek otevřený. Velká
naskenovaná PDF, obrázky a dlouhé nahrávky zaberou čas; udržujte soubory rozumně malé
a počítejte s dlouhou dobou odezvy.

### Účtování

Přímá extrakce textu (text, PDF s textovou vrstvou, Word, Excel) nepoužívá žádný AI
model. Vidění (obrázky, naskenovaná PDF) a převod řeči na text (zvuk) se účtují podle
ceny použitých modelů. Server může mít také nastavenou minimální cenu za volání; když
volání stojí méně než minimum, rozdíl se účtuje jako poplatek. Kredity, které volání
spotřebovalo, se vracejí v `credits`.

Výsledky čtení pomocí vidění se ukládají do cache na 24 hodin: opětovný převod
stejného obrázku nebo naskenovaného PDF během této doby model znovu nevolá a stojí jen
minimální poplatek, pokud je nastaven.

Kontrola, zda má uživatel (nebo, s `organization_id`, organizace) kredity, proběhne
před převodem; viz [kredity](account.md#kredity). Volání se účtuje organizaci, když je
nastaveno `organization_id`, viz [organizace](#organizace-a-kredity).

### Požadavek

| Pole | Typ | Povinné | Popis |
|---|---|---|---|
| `data` | řetězec | Ano | Soubor zakódovaný v base64. Přijímá se i data URL (`data:application/pdf;base64,JVBERi0x...`). |
| `mime_type` | řetězec | Ne | Typ MIME souboru. Má přednost před typem v data URL i před rozpoznáním. |
| `organization_id` | UUID | Ne | Provést převod v této organizaci a účtovat ho z kreditu uživatele v ní, viz [organizace](#organizace-a-kredity). Uživatel musí být administrátor nebo člen (ne host). Výchozí: žádná (osobní kredity). |

### Odpověď

`200 OK` s:

| Pole | Typ | Popis |
|---|---|---|
| `content` | řetězec | Extrahovaný text. |
| `size` | celé číslo | U textového vstupu velikost vstupu v bajtech; u převáděných souborů délka `content` ve znacích. |
| `mime_type` | řetězec | Typ MIME, jako který byl soubor zpracován. U obrázku, jehož text byl přečten, je to `text/plain`; u obrázku, který byl popsán, zůstává typ obrázku. |
| `credits` | číslo | Kredity, které volání spotřebovalo, včetně minimálního poplatku. |

Odpověď obsahuje také pole `filename`, `url`, `name`, `meta`, `path`, `extension`,
`is_chunk`, `binary` a `binary_data`. U tohoto endpointu jsou vždy prázdná nebo
`false`; ignorujte je.

### Chyby

| Stav | `detail` | Příčina |
|---|---|---|
| `401` | `API key is invalid` | Klíči chybí rozsah `ayeto.data_loader`, viz [autentizace](authentication.md#chyby-autentizace). |
| `403` | `User is not a member of the organization` | `organization_id` není mezi organizacemi uživatele. |
| `403` | `User does not have write permissions in the organization` | Uživatel je v organizaci host. |
| `422` | `invalid base64 data` | `data` nejsou platný base64 ani platná data URL. |
| `422` | `invalid encoding` | Textový soubor se nepodařilo dekódovat. |
| `422` | `unsupported file type '<mime type>'` | Soubor je typu, který se nepřevádí (viz tabulka výše), například `unsupported file type 'application/zip'`. |
| `422` | `not enough user credit` | Osobní kredity uživatele jsou vyčerpané. |
| `422` | `not enough organization credit` | S `organization_id`: kredit uživatele v organizaci je vyčerpaný. |
| `422` | chyba validace | Chybí `data`. |
| `500` | `error reading document` | Naskenované PDF se nepodařilo vykreslit. |
| `500` | `Error while processing Word document` | Soubor Word se nepodařilo přečíst. |
| `500` | `Error while processing Excel file` | Soubor Excel se nepodařilo přečíst. |
| `500` | `Error while processing audio file`, `Error while processing WAV audio file` | Zvuk se nepodařilo převést nebo přepsat. |

Chyby autentizace, limitů požadavků a serveru jsou popsány v
[konvencích](conventions.md#chyby).

### Příklad

```bash
curl -X POST "https://ayeto.ai/api/v3/data-loader/load" \
  -H "uni-api-key: $AYETO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"data\": \"$(base64 -w0 invoice.pdf)\", \"mime_type\": \"application/pdf\"}"
```

```json
{
  "content": "PDF page: 1\nInvoice 2026-0412\nNorthwind Trading s.r.o.\nTotal due: 12 400 CZK\n\n",
  "size": 76,
  "filename": "",
  "url": "",
  "name": "",
  "meta": "",
  "path": "",
  "extension": "",
  "is_chunk": false,
  "mime_type": "application/pdf",
  "binary": false,
  "binary_data": "",
  "credits": 0.0
}
```

## Převod textu na řeč

| | |
|---|---|
| Endpoint | `POST /api/v3/tts/mp3` |
| Rozsah | `ayeto.tts` |
| Limit požadavků | [default](conventions.md#limity-pozadavku) |

Převede text na řeč a vrátí soubor MP3.

Text se rozdělí na věty (na zalomeních řádků a na `. `) a každá věta se namluví
zvlášť; zvuk všech vět se spojí do jednoho souboru. Jedna věta nesmí být delší než
4 096 znaků.

### Účtování

Každá věta se účtuje podle počtu znaků za cenu modelu pro převod textu na řeč (viz
typ `tts` u [modelů](models-and-tools.md#typy-modelu)). Věta namluvená stejným hlasem
během poslední hodiny se použije znovu a znovu se neúčtuje. Řeč se platí z
[osobních kreditů](account.md#kredity) uživatele, nebo z kreditu uživatele
v organizaci, když je nastaveno `organization_id` (viz
[organizace](#organizace-a-kredity)). Zůstatek se kontroluje před vygenerováním každé
věty.

### Požadavek

| Pole | Typ | Povinné | Popis |
|---|---|---|---|
| `text` | řetězec | Ano | Text k namluvení. |
| `voice` | řetězec | Ne | Jeden z `alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer`. Výchozí: výchozí hlas serveru (`onyx`, pokud ho administrátoři nezměnili). |
| `filename` | řetězec | Ne | Název souboru pro hlavičku `Content-Disposition`. Výchozí `audio.mp3`. |
| `organization_id` | UUID | Ne | Vygenerovat řeč v této organizaci a účtovat ji z kreditu uživatele v ní, viz [organizace](#organizace-a-kredity). Uživatel musí být administrátor nebo člen (ne host). Výchozí: žádná (osobní kredity). |

### Odpověď

`200 OK` se souborem MP3 jako tělem (`Content-Type: audio/mpeg`) a hlavičkou
`Content-Disposition: attachment` s názvem souboru.

### Chyby

| Stav | `detail` | Příčina |
|---|---|---|
| `401` | `API key is invalid` | Klíči chybí rozsah `ayeto.tts`, viz [autentizace](authentication.md#chyby-autentizace). |
| `403` | `permission denied` | Účet uživatele nemá povoleno používat převod textu na řeč. |
| `403` | `User is not a member of the organization` | `organization_id` není mezi organizacemi uživatele. |
| `403` | `User does not have write permissions in the organization` | Uživatel je v organizaci host. |
| `422` | chyba validace | Chybí `text`, nebo `voice` není jeden z uvedených hlasů. |
| `422` | `not enough user credit` | Osobní kredity uživatele jsou vyčerpané. |
| `422` | `not enough organization credit` | S `organization_id`: kredit uživatele v organizaci je vyčerpaný. |
| `500` | `No audio generated` | `text` je prázdný. |
| `500` | `Failed to generate audio` | Generování řeči selhalo, například proto, že je věta příliš dlouhá. |

Chyby autentizace, limitů požadavků a serveru jsou popsány v
[konvencích](conventions.md#chyby).

### Příklad

```bash
curl -X POST "https://ayeto.ai/api/v3/tts/mp3" \
  -H "uni-api-key: $AYETO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Your order has shipped. It will arrive on Friday.", "voice": "nova", "filename": "order-update.mp3"}' \
  --output order-update.mp3
```
