---
title: "Текст озвучки"
url: https://lumean.app/developers/docs/guide/text
locale: ru
description: "Паузы и указания диктору, нормализация текста, абзацный режим и что из этого оплачивается. Как проверить текст до заказа бесплатно."
updated: 2026-10-18
sources: [post-orders, post-orders-chunks-preview, get-orders-order-items-item-text]
errors: ["422", text-empty, content-blocked]
spec_version: 1.0.0
---

# Текст озвучки

Сервер не отправляет текст заказа на озвучку как есть. Он приводит текст к единому виду и режет
на фрагменты. Разметка внутри текста влияет и на звук, и на цену. В ответе
[`POST /orders`](/developers/docs/api/post-orders) этих шагов не видно, их показывает
бесплатное превью.

## Где передаётся текст

Текст принимают три поля: `input_text` в корне запроса, файл `.txt` в `input_files[]` (до 20 МБ)
и `task_data.text`. Проверки у всех трёх одинаковые. Для заказа по шаблону передавайте текст в
`input_text`.

## Разметка

| Разметка | Примеры | Что делает | Оплачивается |
| --- | --- | --- | --- |
| Пауза | `{{pause=2.5}}`, `{{pause:500ms}}`, `{{pause}}` | Тишина. Без значения — 1 секунда | Нет |
| SSML-пауза | `<break time="2s"/>` | Тишина в нотации SSML | Да, как символы |
| Указание диктору | `[шёпот]`, `[confident]`, `[pause]` | Подсказка о манере чтения | Да, как символы |

`{{pause}}` — разметка Lumean. Тишину по ней вставляет воркер, поставщику синтеза эта строка не
уходит. Поэтому такие паузы бесплатны и не занимают места во фрагменте.

`<break/>` и `[…]` — синтаксис поставщика синтеза. Он получает их целиком, берёт за них плату и
учитывает в своём лимите длины. Поэтому они **оплачиваются как символы и занимают место во
фрагменте**. Фрагмент из 999 символов с `[confident]` внутри вмещает 988 произносимых символов,
а оплачиваются все 999.

Точную цифру для конкретного текста даёт ответ API. Бесплатное превью считает
`total_price_units` так же, как заказ. Оплачиваемую длину готового фрагмента возвращает
`billable_length` в `GET /orders/{order}/items/{item}/text`.

### Квадратные скобки

Указанием диктору считается любой фрагмент `[…]` без вложенных скобок и без переноса строки
внутри. Сноска `[1]`, пометка `[sic]` и тайм-код `[00:12]` вслух не прозвучат. Модель прочтёт их
как указание к манере чтения. Если скобки должны прозвучать, замените их.

Круглые скобки, звёздочки и угловые ремарки вроде `<Fade out>` озвучиваются и оплачиваются.
Диктор прочитает `(пауза)` и `*шёпотом*` вслух.

## Ограничения

| Ограничение | Значение |
| --- | --- |
| Пауз в тексте | не больше 500 |
| Одна пауза | не длиннее 10 секунд |
| Суммарная тишина | не больше 3600 секунд |
| Фрагментов в заказе | не больше 1500 |

Ограничения проверяются до создания заказа. При превышении API отвечает `422`, деньги не
резервируются. В лимиты пауз входят `{{pause}}` и `<break/>`. Устаревшая форма `[pause=2s]`
считается указанием диктору и в них не входит.

## Текст без произносимого

| Что в тексте | Отказ | Где в ответе |
| --- | --- | --- |
| Только теги: `{{pause}}`, `<break/>`, `[…]` | `text_empty` | `errors` |
| Только знаки препинания или ремарки в скобках | `text_not_voiceable` | `errors` |
| Произносимое есть, но один из фрагментов без него | `paragraph_not_voiceable` | `reason` |

Если озвучивать нечего, заказ не создаётся и API отвечает `422`. Отказ по тексту целиком приходит
в `errors` под именем поля: `input_text` или `task_data.text`. Фрагмент без произносимого
чаще всего появляется в абзацном режиме, потому что абзацы между собой не склеиваются. Повтор и
перегенерация чанка с таким текстом отвечают `422` с `reason: text_not_voiceable`.

### 422 · `text_empty` — text_empty — в тексте нечего озвучивать

| Что произошло | Что делать |
| --- | --- |
| Заказ не создан, средства не заблокированы. Чаще всего это ошибка проверки полей: 422 с сообщением в `errors.input_text` (или `errors.task_data.text`) и без `reason`. Ответ с `reason: "text_empty"` приходит, когда текст прошёл проверку, но при разбиении не дал ни одного фрагмента. | Проверьте, есть ли в теле `errors`. Если есть, исправьте текст в указанном поле. Если нет, текст не разбился на фрагменты: посмотрите его превью. Круглые и угловые скобки, звёздочки и другая типографика озвучиваются и тарифицируются, поэтому их удаление не поможет. |

`Retry-After`: нет. Разбор: https://lumean.app/developers/docs/errors/text-empty

## Нормализация

| Что | Как |
| --- | --- |
| `\r\n`, `\r` | → `\n` |
| Табуляция | → пробел |
| Больше 3 переносов строки подряд | → ровно 3 |
| Больше 5 пробелов подряд | → ровно 5 |
| `Привет.Мир` | → `Привет. Мир` (только озвучка) |

Сервер меняет текст до нарезки. Смещения фрагментов `start` и `end` считаются от изменённого
текста, а не от присланного.

Пробел после `.`, `!` или `?` перед буквой или цифрой добавляется только в тексте озвучки. Он не
ставится в десятичных числах, сокращениях, акронимах, URL со схемой, email и внутри тегов. Голый
домен без схемы, например `example.com` в середине фразы, не отличить от `Привет.Мир`, и он
получит пробел. Пишите такие адреса со схемой.

## Абзацный режим

```json
{ "template_id": "<UUID>", "input_text": "Первый абзац.\n\nВторой абзац.",
  "config_override": { "generation_mode": "paragraph" } }
```

По умолчанию текст режется подряд, по техническому размеру фрагмента, и границы абзацев не
учитываются. В абзацном режиме текст сначала делится по пустой строке, а затем каждый абзац
режется отдельно.

Ключ `generation_mode` лежит в корне `config_override`, а не внутри `tts_settings`. В корне
`config` шаблона он включает режим для всех заказов по этому шаблону. Значения — `paragraph` и
`default`.

Режим поддерживают `elevenlabs` и `heygen`. Другие сервисы ключ игнорируют без ошибки, режим
просто не включается. В `GET /templates/config-options` ключа нет: справочник описывает
настройки сервиса, а режим задаётся на заказ. В одном заказе одновременно выполняются до 10
абзацев из одного фрагмента и до 5 абзацев из нескольких.

В ответе появляются `paragraphs[]`, а у фрагментов — `paragraph_index`. По каждому абзацу
приходят `paragraph_index`, `chunks_count`, `completed_chunks`, `status` и `progress_percent`.

- У `paragraphs[].status` четыре значения: `pending`, `in_progress`, `failed`, `completed`.
  Чанк, заблокированный политикой, считается как `failed`.
- Статус абзаца считается только по исходным чанкам (`item_type = chunk`). Успешный повтор
  упавшего фрагмента статус абзаца не меняет.
- У записей `retry` и `regeneration` поле `paragraph_index` равно `null`. Абзац берите у
  родителя через `parent_item_id`.

> [!WARNING]
> Текст короче минимального оплачиваемого объёма оплачивается по этому минимуму. В абзацном режиме
> минимум применяется к каждому абзацу. Пять коротких абзацев стоят пять минимумов, а тот же текст
> в обычном режиме — один. Порог виден в превью, в `summary.min_billable_chars`.

## Превью нарезки и стоимости

```bash
curl -s -X POST "$BASE/orders/chunks/preview" -H "X-API-KEY: $KEY" \
  -H "Content-Type: application/json" \
  -d '{ "template_id": "<UUID>", "input_text": "…" }'
```

`POST /orders/chunks/preview` прогоняет текст через ту же нормализацию, нарезку и расчёт, что и
заказ, но заказа не создаёт. Превью бесплатно и не расходует токен-квоту ключа.

| Поле `summary` | Что показывает |
| --- | --- |
| `voiced_length` | сколько символов будет озвучено, без учёта минимального объёма |
| `total_effective_length` | оплачиваемая длина всех фрагментов в символах |
| `total_price_units` | сколько токенов спишет заказ |
| `min_billable_chars` | минимальный оплачиваемый объём, `0` — минимума нет |
| `voiced_empty` | `true` — озвучивать нечего, заказ получит `422` |
| `caps_ok`, `caps_exceeded` | превышено ли ограничение: `count`, `single`, `total` или `chunks` |
| `has_blocked_content`, `blocked_chunks[]` | фрагменты, которые уже отклоняла контентная политика, см. [Ретраи и идемпотентность](/developers/docs/guide/retries) |

В отличие от `POST /orders`, превью не отказывает при превышении ограничений, а только сообщает о
нём.

### POST /orders/chunks/preview

Предпросмотр разбиения на чанки

Справочник: https://lumean.app/developers/docs/api/post-orders-chunks-preview

**Правильно**

Прогнать текст через превью и сверить `voiced_length` и `total_price_units` с ожиданием.

**Неправильно**

Оценивать стоимость по длине строки. Разметка, минимальный объём и абзацный режим меняют цифру в
обе стороны.

---

- Эта же страница в браузере: https://lumean.app/developers/docs/guide/text
- Машинный справочник целиком: https://api.lumean.app/docs/llm.md
