SONA Голоси Telegram-бот EN
Довідник SONA

Налаштування

Усе, що потрібно для бота та API: від ключа і вибору голосу до наголосів, субтитрів і завантаження файлу.

Ключ і швидкий старт

Бот і API працюють з одного балансу кредитів.

Отримати API-ключ

  1. Відкрий @sonapro_bot.
  2. Обери 🔌 API → Створити ключ.
  3. Додавай sk_user_… у заголовок кожного запиту.
X-API-Key: sk_user_…

Важливо: не вставляй ключ у frontend-код, публічний GitHub або переписку. Створення нового ключа в боті відразу вимикає попередній.

Перша озвучка

Процес асинхронний: створи job_id, перевіряй статус і після done забери аудіо.

API="https://api.sonapro.ai"
KEY="sk_user_…"

# 1. Створити задачу
curl -X POST "$API/v1/tts" \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Привіт, світе!","voice":"vc_xxxxxxxxxx","language":"uk","model":"sona-3.6"}'

# 2. Перевірити статус
curl "$API/v1/tts/JOB_ID" -H "X-API-Key: $KEY"

# 3. Забрати файл
curl "$API/v1/tts/JOB_ID/audio" -H "X-API-Key: $KEY" -o out.mp3

Ендпоінти

Базова адреса: https://api.sonapro.ai.

МетодШляхОпис
POST/v1/ttsСтворити озвучку або діалог → job_id
GET/v1/tts/{job_id}Статус задачі
GET/v1/tts/{job_id}/audioЗавантажити аудіо
GET/v1/tts/{job_id}/linkКоротке публічне посилання
GET/v1/tts/{job_id}/subtitles?format=srt|vtt|ass|json|zipСубтитри; потрібно subtitles:true
GET/v1/tts/{job_id}/dubДубляж: мови, голоси й ціна (кредити й PAYG) для готового результату
POST/v1/tts/{job_id}/dubДублювати готовий результат → задача на кожну мову; оплата кредитами або PAYG
POST/v1/tts/dub-optionsМови й голоси дубляжу до створення озвучки
GET/v1/tts/{job_id}/fragmentsФрагменти готової озвучки: номер, текст, початок і кінець
POST/v1/tts/{job_id}/fragments/{n}/quoteЦіна переозвучки фрагмента
POST/v1/tts/{job_id}/fragments/{n}Переозвучити фрагмент → новий повний файл
POST/v1/tts/dialogue/parseДіалог: розібрати сценарій або прозу на ролі й репліки
GET/v1/tts/{job_id}/dialogueДіалог: хто, що й коли говорить
GET/v1/tts/{job_id}/stemsДіалог: ZIP з окремою доріжкою кожної ролі
GET/v1/tts/{job_id}/stems/linkПублічне посилання на доріжки ролей
GET/POST/v1/dialogue/templatesШаблони діалогів: список або створення → dlg:N
GET/PATCH/DEL/v1/dialogue/templates/{ref}Шаблон діалогу: прочитати, змінити або видалити
POST/v1/dialogue/templates/from-job/{job_id}Шаблон із героїв готового діалогу
GET/v1/voices?language=uk&collection=sona_v1Каталог; collection: library або sona_v1
POST/v1/voices/cloneКлонувати голос → tmpl:N
GET/POST/v1/voices/templatesСписок або створення шаблону
PATCH/DEL/v1/voices/templates/{num}Змінити або видалити шаблон
GET/v1/emotionsАктуальний список емоцій
GET/POST/v1/pronunciationСписок або збереження правила вимови
DEL/v1/pronunciation/{term}Видалити правило
GET/v1/meАкаунт, тариф і баланс
GET/v1/activity?kind=voice&status=done&limit=50Історія задач акаунта: що вже готово, а що ще ні (озвучки, зображення, відео)
POST/v1/imagesЗгенерувати зображення
POST/v1/images/editЗгенерувати з фото-референсом
GET/v1/images/{image_id}Статус задачі
GET/v1/images/{image_id}/fileЗавантажити PNG/JPEG/WebP
POST/v1/videosСтворити відео Veo 3.1 — з тексту або з 1–3 фото → video_id
GET/v1/videos/{video_id}Статус відео
GET/v1/videos/{video_id}/fileЗавантажити MP4
GET/v1/videos?limit=20Історія відео акаунта

Баланс і термін дії — GET /v1/me

Відповідь стосується лише акаунта, якому належить ключ. «Профіль» у боті показує ті самі числа. Дати — ISO 8601 в UTC.

ПолеКредити на озвучку й тариф
credits_remainingСкільки можна витратити зараз: усі чинні пакети разом зі стартовими кредитами. Поруч — credits_total і credits_used.
credits_expiring
credits_expires_at
Скільки кредитів згорить найближчим терміном і коли. Це лише найближча дата: у кожного пакета свій термін. Коли в пакетах кредитів не лишилось — 0 і null.
tariffПоточний тариф: start, pro, business, ultra або null.
tariff_expires_atКоли цей тариф закінчиться. Витрачений пакет тримає тариф до кінця свого терміну, тому дата буває пізніша за credits_expires_at і є навіть тоді, коли та — null. Після неї tariff знижується до меншого чинного пакета або стає null.
jobs_limitСкільки озвучок акаунт може виконувати одночасно.
sub_active
sub_expires_at
Підписка Ультра і дата її кінця; для інших тарифів — false і null.
unlimitedtrue — безлімітний акаунт: кредити не списуються, тож баланс не рухається, а tariff_expires_at — null.

Пакети Nano і Veo — у product_billing.products.nano.plan і product_billing.products.video.plan; null, якщо пакета немає.

ПолеПакет Nano / Veo
daily_limit
jobs_limit
Генерацій на добу (у Veo — null, без ліміту) і скільки одночасно. Кілька пакетів Nano діють разом, і тут — їхня сума.
used_today
remaining_today
Використано й лишилось у поточній добі.
resets_atКоли почнеться нова доба; з кількома пакетами — найближча. Відлік іде від початку пакета, а не з півночі.
expires_atКінець поточного терміну пакета; з кількома пакетами — найближчий.
active_untilКінець усього вже оплаченого строку без перерв. Без інших пакетів дорівнює expires_at.
plansКожен пакет, що діє зараз, окремо: id, label, ліміти, використання за його власну добу, starts_at, expires_at. Пакет Nano, куплений поверх активного, діє одразу поруч із ним; пакет Veo починається після кінця поточного.

product_billing.legacy_image_credits — раніше придбані кредити, якими можна платити за Nano. Вони вже входять у credits_remaining, тож не додавай їх удруге. payg — гаманець оплати за фактом: balance_usd доступно, reserved_usd зарезервовано під задачі, що виконуються; кошти не згорають. Поля payg немає, якщо PAYG для акаунта вимкнений.

curl https://api.sonapro.ai/v1/me -H "X-API-Key: $SONA_API_KEY"

Відповідь, скорочено:

{
  "credits_remaining": 400000,
  "credits_expiring": 400000,
  "credits_expires_at": "2026-10-27T11:37:49+00:00",
  "tariff": "pro",
  "tariff_expires_at": "2026-10-27T11:37:49+00:00",
  "jobs_limit": 4,
  "product_billing": {"products": {"nano": {"plan": {
    "daily_limit": 600, "used_today": 2, "remaining_today": 598,
    "resets_at": "2026-09-28T11:37:49+00:00",
    "expires_at": "2026-10-27T11:37:49+00:00",
    "active_until": "2026-11-26T11:37:49+00:00"}}}},
  "payg": {"balance_usd": "5.000000", "reserved_usd": "0.000000"}
}

Голоси й шаблони

Параметри зберігаються для кожного шаблону окремо.

Формати ID і тариф

vc_…Бібліотечний голос1 кредит / символ
sona_…SONA Voice v11,5 кредита / символ
tmpl:NОсобистий шаблон/клон1,5 кредита / символ

Щоб побудувати окремий список наших голосів, запитай GET /v1/voices?collection=sona_v1. У загальному каталозі кожен елемент має поле collection: sona_v1 або library. Фільтри поєднуються, наприклад ?collection=sona_v1&language=uk.

Отримати каталог голосів

Один запит повертає весь каталог обраної мови — зручно зібрати свою таблицю id + name + description.

curl "$API/v1/voices?language=uk" \
  -H "X-API-Key: $KEY"

# відповідь (скорочено)
{
  "count": 1,
  "voices": [
    {
      "id": "vc_04d73ccf5c",
      "name": "Weston A.",
      "language": "uk",
      "gender": "masculine",
      "tags": ["Conversational"],
      "description": "Approachable adult male voice with a professional tone for casual conversations and everyday interactions",
      "is_pro": false,
      "has_preview": true,
      "collection": "library"
    }
  ]
}

Один голос — різні шаблони

Шаблон зберігає власні speed, volume і emotion. Тому один голос може мати «Нейтральний», «Злий» і «Спокійний» варіанти. Бот запитує ці поля під час створення; у картці шаблону їх можна змінити.

POST /v1/voices/templates
{
  "engine": "sona",
  "voice": "sona_xxxxxxxxxxxx",
  "name": "Taras · angry",
  "speed": 1.05,
  "volume": 1.0,
  "emotion": "angry"
}

# Змінити пресет пізніше
PATCH /v1/voices/templates/7
{"emotion":"neutral","speed":1.0}

Якщо під час генерації передати параметр явно, він перекриє значення шаблону лише для цієї озвучки.

Клонування

POST /v1/voices/clone — multipart з полями clip, name, language і необов’язковими speed, volume, emotion. Зразок — від 3 до 60 секунд чистої мови без фонової музики, до 16 МБ; на Sona 3.6 довший зразок, 30–60 секунд, краще зберігає акцент.

Параметри озвучення

Поля POST /v1/tts. Зірочкою позначені обов’язкові.

ПолеТип / межіОпис
text *stringТекст для озвучення
voice *vc_…, sona_…, tmpl:NГолос або шаблон
languageauto, uk, en, pl…auto бере мову голосу; явний код дозволяє іншу мову
modelsona-3.5 / sona-3.6Типово sona-3.6. sona-3.5 працює, лише коли її передано в запиті; старі назви sona-pro, sona-fast і sona-hd теж ідуть на sona-3.6. Модель, вибрана в боті, на API не впливає.
normalizationauto / off / localeSona 3.6: читання чисел, дат, часу, валют і скорочень; напр. en-IN
formatmp3Формат файлу
bitrate32000–192000Бітрейт MP3; типово 96000
sample_rate8000–48000Частота дискретизації; типово 44100
speed0.6–1.5Швидкість SONA/клону
volume0.5–2.0Гучність SONA/клону
emotionstringОдна вокальна манера на весь запит
billing_sourcecredits / paygТипово — кредити тарифу. Передай payg явно для оплати з грошового балансу. Автоматичного перемикання немає.
auto_stressbool, типово trueВелика голосна всередині кириличного слова → U+0301
subtitlesboolSRT/VTT/ASS і JSON-таймкоди
namestringНазва файлу без розширення
client_request_idstring, до 128: латиниця, цифри, . _ : -Твій ідентифікатор запиту (або заголовок Idempotency-Key). Повтор із тим самим id і тим самим тілом повертає першу відповідь із replayed: true — без другої задачі й другого списання; той самий id з іншим тілом — 409. Діє 72 год. Так само в POST …/dub і POST …/fragments/{n}.

Переозвучити фрагмент

Готова озвучка складається з фрагментів, приблизно по 700 символів. Один фрагмент можна озвучити ще раз — як був або з виправленим текстом (наприклад, з наголосом). Результат — нова задача з новим повним файлом, де цей фрагмент замінено; оригінал не змінюється. Ціна — ×2 до звичайної озвучки символів фрагмента.

GET /v1/tts/{job_id}/fragments — номер (index, з 1), текст, start і end кожного фрагмента. POST …/fragments/{n}/quote — ціна, ті самі поля, що й у POST /v1/tts/quote. POST …/fragments/{n} з необов’язковими text (до 3000 символів), max_credits / max_microusd, billing_source і client_request_id повертає job_id; далі це звичайна задача, із субтитрами, якщо вони були в оригіналі. Статус готової озвучки показує fragments — скільки їх. Доступно, поки зберігається результат (24 год); фрагмент дубляжу не переозвучується — переозвуч оригінал і задублюй знову.

Емоція шаблону і емоція запиту

Якщо використовуєш tmpl:N без emotion, SONA бере збережену емоцію шаблону. Якщо передати emotion:"angry" в цьому запиті, вона замінить емоцію шаблону лише для нього.

Оплата за фактом (PAYG)

Поповни баланс від $5 та оплачуй озвучку в міру використання. Sona — $8 за мільйон оплачуваних символів; клони та PRO — $12 (×1,5). 10 паралельних задач; кошти не згорають. Наприклад, $16 вистачить на 2 000 000 звичайних символів.

Відкрий /payg у Telegram: баланс, поповнення та вибір оплати озвучки в боті. У веб-кабінеті (api.sonapro.ai/cabinet) оплату обирає власний перемикач «Оплата» в налаштуваннях озвучки — вибір у боті туди не переноситься. В API працює той самий ключ: передавай billing_source:"payg" у кожному запиті. Ні вибір у боті, ні перемикач у кабінеті не змінюють типовий режим API. Зображення й відео мають власні пакети і той самий PAYG-баланс: $0.015 за зображення, $0.02 за відео; деталі у вкладках «Генерація зображень» і «Генерація відео».

GET /v1/billing/payg повертає доступні/зарезервовані USD та історію. Поповнення: POST /v1/billing/checkout з {"product":"payg","amount_usd":"16.25","method":"mono"} (або crypto). Кошти зараховуються після перевірки провайдером. Порожній гаманець повертає 402; помилка чи скасування озвучки повертає кошти на той самий баланс. Квитанція billing задачі показує суму й статус списання.

Дубляж

Готова озвучка — іншими мовами й тієї ж тривалості, що й оригінал.

Як це працює

Текст готової озвучки перекладається й озвучується іншими мовами. Кожна мова — окрема задача й окремий файл. Як саме лягає переклад, обираєш ти: «Під відео» — кожне речення починається там, де звучить в оригіналі, і доріжку можна покласти на те саме відео; «Природно» — як звичайна озвучка цією мовою (нижче, «Режими»). Дубляж доступний кожному акаунту, працює з тим самим заголовком X-API-Key і оплачується кредитами або з PAYG-балансу (оплата за фактом).

ЗапитКоли
GET /v1/tts/{job_id}/dubПропозиція для готового результату: мови, голоси й ціна
POST /v1/tts/{job_id}/dubДублювати готовий результат → задача на кожну мову
POST /v1/tts + dub_languagesЗамовити дубляж разом з озвучкою: задачі створяться самі, коли оригінал буде готовий
POST /v1/tts/dub-optionsМови й голоси до створення озвучки
POST /v1/audio/dub-sourceДублювати власний запис — лише аудіо (вкладка «Дубляж аудіо»)

Режими: під відео чи природно

Переклад рідко має ту саму довжину, що й оригінал: англійська чи іспанська часто на 20–25 % коротші за українську. Тому обери, що важливіше — збіг із картинкою чи природне звучання. Поле mode у POST …/dub (у POST /v1/tts з dub_languages — dub_mode); діє і для звичайної озвучки, і для діалогу. Ціна однакова.

РежимЯк звучитьКоли обирати
video
«Під відео»
типово
Довжина й паузи як в оригіналі: кожна фраза (у діалозі — кожна репліка) на своєму місці (щоб вирівняти паузи, фраза може почати до пів секунди раніше), файл тієї ж тривалості. Коротший переклад сервіс спершу трохи сповільнює дубль, а якщо цього мало — просить сказати повніше (без нових фактів); решту розподіляє по паузах — без довгої тиші посередині; у кінці лишається хіба коротка тиша.Доріжка ляже під те саме відео: ролик, презентація, урок, де звук має збігатися з картинкою.
natural
«Природно»
Як звичайна озвучка цією мовою: кожен фрагмент звучить у звичайному темпі, паузи природні (не довші за ~0,9 с; у діалозі — паузи самого діалогу), без тиші в кінці. Тривалість може відрізнятися від оригіналу — часто коротша.Канал, подкаст, аудіокнига, аудіо без відео — де картинка не мусить збігатися слово в слово.

Без поля — video. Інше значення — 422. GET …/dub і POST /v1/tts/dub-options повертають modes (id, name, description) і default_mode, відповідь POST …/dub — mode, а статус задачі дубляжу — dub_mode. У режимі «Природно» нічого не переозвучується, тож списується лише базова ціна, а решта утримання повертається.

Дубляж готового результату

Спершу запитай пропозицію, потім запусти потрібні мови. max_credits (для PAYG — max_amount_microusd) — найбільше, що ти погоджуєшся заплатити. Менше за базову ціну — запит відхиляється з 409, нічого не списано; між базовою ціною й максимальною — обмежує, скільки можна доплатити за повторну озвучку; без нього утримується повна максимальна сума.

# 1. Що доступно і скільки коштує
curl https://api.sonapro.ai/v1/tts/JOB_ID/dub \
  -H "X-API-Key: $SONA_API_KEY"

# 2. Запустити: по задачі на кожну мову
curl -X POST https://api.sonapro.ai/v1/tts/JOB_ID/dub \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"languages":["en","ja"],"voices":{"ja":"native"},"mode":"video","max_credits":4500}'
# → {"job_id":"JOB_ID","mode":"video","billing_source":"credits","chars":4500,"chars_base":3000,"jobs":[
#     {"job_id":"DUB_ID","language":"en","status":"queued","voice":"same","chars":2250}, …]}

# 3. Кожна мова — звичайна задача озвучки
curl https://api.sonapro.ai/v1/tts/DUB_ID -H "X-API-Key: $SONA_API_KEY"
curl https://api.sonapro.ai/v1/tts/DUB_ID/audio -H "X-API-Key: $SONA_API_KEY" -o dub_en.mp3

У відповіді POST …/dub chars — кредити, утримані зараз, chars_base — базова ціна, а chars кожної задачі в jobs — її утримання. Коли мова готова, списується база плюс повторно озвучені символи, решта одразу повертається; chars у статусі готової задачі дубляжу — фактично списані кредити.

Відповідь GET …/dub для оригіналу на 1 000 символів голосом із каталогу, скорочено:

{
  "job_id": "JOB_ID",
  "source_language": "uk",
  "languages": ["ar", "bg", "cs", "de", "en", "…"],
  "voices": {
    "en": {"auto": "native",
           "native": {"id": "vc_…", "name": "…", "gender": "feminine"},
           "choices": [{"id": "vc_…", "name": "…", "gender": "feminine"}, "…"],
           "pro": [{"id": "sona_…", "name": "…", "pro": true, "gender": "feminine"}]}
  },
  "cost_per_language": 1500,
  "cost_catalog_voice": 1500,
  "cost_clone_voice": 2000,
  "cost_per_language_max": 2250,
  "cost_catalog_voice_max": 2250,
  "cost_clone_voice_max": 3000,
  "multiplier_catalog_voice": 1.5,
  "multiplier_clone_voice": 2.0,
  "billing_source": "credits",
  "charge_per_language": 1500,
  "charge_per_language_max": 2250,
  "max_languages": 10,
  "modes": [{"id": "video", "name": "Під відео", "description": "…"},
            {"id": "natural", "name": "Природно", "description": "…"}],
  "default_mode": "video",
  "free_slots": 4,
  "balance": 400000,
  "payg": {
    "cost_per_language_microusd": 12000,
    "cost_catalog_voice_microusd": 12000,
    "cost_clone_voice_microusd": 16000,
    "cost_per_language_max_microusd": 18000,
    "cost_catalog_voice_max_microusd": 18000,
    "cost_clone_voice_max_microusd": 24000,
    "balance_microusd": 5000000
  }
}

cost_per_language — базова ціна однієї мови голосом оригіналу; cost_catalog_voice і cost_clone_voice — якщо для мови обрати голос із каталогу або клон чи голос Sona PRO. Поля з _max — скільки утримується при запуску: база плюс 50 % на повторну озвучку. multiplier_catalog_voice і multiplier_clone_voice — ціна за символ оригіналу. billing_source — чим заплатить auto; charge_per_language і charge_per_language_max — що утримається з кредитів (0 для безлімітного акаунта). payg є лише в акаунтів із PAYG: ті самі ціни в мікродоларах і balance_microusd. У voices для кожної мови: auto — що вибере auto (same чи native), native — головний голос носія мови, choices — до 6 голосів носіїв, pro — голоси Sona PRO цієї мови. Задача дубляжу має в статусі dub_of — job_id оригіналу. Готовий результат, який можна дублювати, має dub_available: true.

Субтитри: subtitles у POST …/dub (true чи false) вмикає їх для кожної мови запиту; без поля дубляж бере вибір оригіналу — його показує subtitles у пропозиції GET …/dub, а дубляж, замовлений через POST /v1/tts, бере subtitles самої озвучки. Готова мова з субтитрами має в статусі has_subtitles: true і віддає SRT, VTT, ASS чи JSON через GET /v1/tts/{job_id}/subtitles, як звичайна озвучка. Без доплати.

Оплата за фактом (PAYG)

Дубляж можна оплатити з PAYG-балансу: $12 за мільйон символів оригіналу за кожну мову голосом із каталогу й $16 — клоном або голосом Sona PRO (звичайна ставка PAYG $8 × 1,5 і × 2), плюс доплата за повторну озвучку за тією ж ставкою. Чим платити, задає billing_source у POST …/dub: auto (типово) — PAYG, якщо оригінал оплачено з PAYG і PAYG для акаунта увімкнено, інакше кредити; credits чи payg — явно. Ліміт ціни — max_amount_microusd, за тими самими правилами, що й max_credits.

curl -X POST https://api.sonapro.ai/v1/tts/JOB_ID/dub \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"languages":["en","de"],"billing_source":"payg","max_amount_microusd":36000}'
# → {"job_id":"JOB_ID","billing_source":"payg","amount_microusd":36000,"amount_usd":"0.036000",
#    "base_microusd":24000,"base_usd":"0.024000",
#    "jobs":[{"job_id":"DUB_ID","language":"en",…,"amount_microusd":18000}, …]}

amount_microusd і amount_usd — утримано зараз, base_microusd і base_usd — базова ціна, amount_microusd у кожній задачі jobs — її утримання. Підсумкове списання показує квитанція billing у статусі готової задачі дубляжу (charged_usd). Для PAYG free_slots у пропозиції рахує слоти PAYG.

Дубляж одразу при створенні

Додай до POST /v1/tts поле dub_languages і, за потреби, dub_voices та dub_mode (video чи natural, див. «Режими»). Ціна дубляжу додається до ціни озвучки й утримується разом із нею: POST /v1/tts/quote з тим самим тілом показує базову ціну дубляжу в dub_credits, утримання з доплатою за повторну озвучку — в dub_credits_max, а charge_credits уже включає утримання. max_credits діє на весь запит: менше за ціну озвучки разом із базовою ціною дубляжу — 409, більше — обмежує доплату за повторну озвучку.

curl -X POST https://api.sonapro.ai/v1/tts \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Привіт, світе!","voice":"vc_xxxxxxxxxx","language":"uk","dub_languages":["en","de"],"dub_voices":{"de":"same"},"dub_mode":"natural"}'
# → {"job_id":"JOB_ID","status":"queued","chars":14,"language":"uk",
#    "dub_credits":42,"dub_credits_max":64,"dub_languages":["en","de"],"dub_mode":"natural"}

# стан дубляжу — у статусі оригіналу
curl https://api.sonapro.ai/v1/tts/JOB_ID -H "X-API-Key: $SONA_API_KEY"
# → … "dub_jobs":[{"language":"en","state":"started","job_id":"DUB_ID"},
#                 {"language":"de","state":"waiting"}]
waiting→started+job_id

Коли оригінал готовий, сервіс сам створює задачі дубляжу, і кожна отримує свій job_id. Якщо оригінал завершився помилкою або його скасовано, усе утримане за дубляж повертається, а стан стає refunded.

З billing_source:"payg" задача оплачує з PAYG-балансу й свої dub_languages: дубляж утримується з гаманця разом із задачею й повертається, якщо задача не вдалася чи скасована. Ліміт ціни на весь запит тоді — max_microusd. Quote показує dub_amount_microusd і dub_amount_max_microusd (у доларах — dub_amount_usd і dub_amount_max_usd), а amount_microusd включає утримання дубляжу.

Голос для кожної мови

Поле voices (або dub_voices у POST /v1/tts) — словник «мова → голос». Мова без запису отримує auto.

ЗначенняЩо звучить
autoТипово. Голос оригіналу, якщо він говорить цією мовою; інакше — голос носія мови з каталогу тієї ж статі. Клон і голос Sona PRO лишаються собою.
sameГолос оригіналу — з його акцентом
nativeНайпопулярніший голос носія мови з каталогу, тієї ж статі, якщо вона відома
vc_…, sona_…, tmpl:NКонкретний голос, збережений шаблон або власний клон

Щоб показати вибір ще до створення озвучки, надішли голос, мову й модель у POST /v1/tts/dub-options. Відповідь містить languages, voices у тому самому форматі й max_languages. Ціни тут немає, бо вона залежить від тексту: її дає POST /v1/tts/quote.

curl -X POST https://api.sonapro.ai/v1/tts/dub-options \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"voice":"vc_xxxxxxxxxx","language":"uk","model":"sona-3.6"}'

Ціна й ліміти

  • Ціна — за кожен символ оригіналу, за кожну мову: голосом із каталогу — 1,5 кредита (як озвучка клоном чи голосом Sona PRO), клоном або голосом Sona PRO — 2 кредити. З PAYG — $12 і $16 за мільйон символів оригіналу. Переклад входить у ціну.
  • Повторна озвучка — доплата по факту: фрагменти, які довелося озвучити ще раз, щоб вони влізли в час, оплачуються зверху за тією ж ставкою (символи кожного повторного дубля × множник). При запуску утримується базова ціна плюс 50 % від неї (поля *_max); коли дубляж готовий, списується база плюс повторно озвучені символи, а решта одразу повертається. Більше за утримане не списується — повторна озвучка понад нього безкоштовна. Якщо дубляж мови не вдався, повертається все утримане за неї.
  • Приклад — оригінал на 1 000 символів, одна мова: голосом із каталогу 1 500 кредитів (до 2 250 з повторною озвучкою) або $0.012 (до $0.018); клоном чи голосом Sona PRO — 2 000 (до 3 000) або $0.016 (до $0.024).
  • Мови залежать від моделі оригіналу: 42 мови sona-3.5, а sona-3.6 додає одію (or) та урду (ur). Мова оригіналу до списку не входить.
  • До 10 мов за запит. Кожна мова — окрема задача й займає один слот одночасних задач тарифу (jobs_limit), а з PAYG — один із 10 слотів PAYG. Набір приймається цілком або ніяк: якщо вільних слотів не вистачає на всі мови, повертається 429. Скільки вільно зараз, показує free_slots.
  • 24 години — стільки результат зберігається й доступний для дубляжу; потім 410. Дубляж дубляжу не робиться — дублюй оригінал.

Помилки

У разі відмови нічого не списується.

402Недостатньо кредитів (повідомлення пропонує оплатити з PAYG) або коштів PAYG
403Дубляж недоступний для цього акаунта, або PAYG для акаунта вимкнено
404Задачу не знайдено
409Озвучка ще не завершена, це вже дубляж, цю озвучку не можна дублювати, або max_credits / max_amount_microusd нижче за базову ціну
410Результат уже видалено за строком зберігання
422Мова недоступна або збігається з мовою оригіналу, забагато мов, невідомий голос, mode не video і не natural
429Замало вільних слотів на всі мови
503Дубляж тимчасово недоступний або тривають технічні роботи

Дубляж свого запису

Свій аудіозапис чи голосове теж можна задублювати іншими мовами — у боті чи через API. Покрокова інструкція, ціна й ліміти — на вкладці «Дубляж аудіо».

Дубляж аудіо

Свій запис — та сама доріжка іншими мовами: сервіс розпізнає текст, перекладає його й озвучує в такт оригіналу.

Як це працює

  • Що надсилати — аудіофайл (mp3, m4a, ogg, wav, flac…) або голосове повідомлення: один голос у записі, до 2 год. Відео не приймаємо — лише звук.
  • Що робить сервіс — безкоштовно розпізнає мову, текст і час кожного слова й визначає стать мовця. Текст можна виправити до дубляжу: імена, терміни, недочуте.
  • Що виходить — mp3 кожною обраною мовою. «🎬 Під відео» — кожна фраза на своєму місці й та сама тривалість, що в оригіналу: доріжку можна накласти на те саме відео. «🎙 Природно» — як звичайна озвучка цією мовою. Фонова музика й шуми не переносяться: у результаті звучить лише новий голос.

У боті — крок за кроком

  1. Відкрий @sonapro_bot і надішли аудіофайл або голосове — до 20 МБ (більше Telegram ботам не віддає).
  2. Бот покаже картку запису з тривалістю й ціною — натисни «🌐 Дубляж цього аудіо».
  3. Зачекай на розпізнавання — приблизно хвилина на кожні 10 хвилин запису. Бот надішле розпізнаний текст.
  4. Якщо треба — «✏️ Виправити текст»: скопіюй текст, виправ і надішли наступним повідомленням (у боті — до 3 500 символів; довший текст виправляється через API).
  5. «🌐 Обрати мови» — познач потрібні мови й натисни «Далі › голоси». Для кожної мови — «Авто» (носій мови тієї ж статі, що й мовець), інший голос носія мови (🔊 — прослухати), голос Sona PRO 💎 або свій збережений голос ⭐.
  6. Обери режим «🎬 Під відео» чи «🎙 Природно», за потреби — «Субтитри», і натисни «▶️ Запустити» — на кнопці вже видно ціну. Готовий файл кожною мовою прийде в чат.

Через API, ціна й ліміти

  • Через API — надішли файл, дочекайся status: done, за потреби виправ текст і запускай дубляж звичайним POST …/dub.
ЗапитЩо робить
POST /v1/audio/dub-sourceMultipart: file, необов'язково language (uk, en, pt-BR… або auto) і name. Відповідь 202: job_id, status, duration
GET /v1/tts/{job_id}Статус запису: source: "upload", language, gender (стать мовця або null), transcript_chars, dub_available; поки сервіс завантажений — waiting і retry_at
GET /v1/tts/{job_id}/transcriptРозпізнаний текст і його речення з часом (sentences)
PUT /v1/tts/{job_id}/transcriptВиправити текст до дубляжу: незмінені слова зберігають свій час у записі
GET / POST /v1/tts/{job_id}/dubПропозиція й запуск, як для будь-якої озвучки. Голосу Sona в записі немає, тож same не буває; auto — найпопулярніший голос носія мови тієї ж статі, що й мовець
# 1. Надіслати запис (розпізнавання безкоштовне)
curl -X POST https://api.sonapro.ai/v1/audio/dub-source \
  -H "X-API-Key: $SONA_API_KEY" \
  -F file=@talk.mp3 -F language=uk
# → 202 {"job_id":"JOB_ID","status":"queued","duration":512.4}

# 2. Дочекатися "status": "done"
curl https://api.sonapro.ai/v1/tts/JOB_ID -H "X-API-Key: $SONA_API_KEY"

# 3. Текст із часом речень — і виправлення, якщо треба
curl https://api.sonapro.ai/v1/tts/JOB_ID/transcript -H "X-API-Key: $SONA_API_KEY"
curl -X PUT https://api.sonapro.ai/v1/tts/JOB_ID/transcript \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Привіт усім. Сьогодні поговоримо про погоду."}'

# 4. Дубляж — як для будь-якої озвучки
curl -X POST https://api.sonapro.ai/v1/tts/JOB_ID/dub \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"languages":["en","de"],"mode":"video"}'
  • Ціна — розпізнавання й виправлення тексту безкоштовні. Дубляж запису — за кожен символ розпізнаного тексту, за кожну мову, удвічі дорожче за озвучку: голосом із каталогу — 2 кредити, клоном або голосом Sona PRO — 3. З PAYG — $16 і $24 за мільйон символів. Повторна озвучка — доплата по факту за тією ж ставкою, при запуску утримується база плюс 50 %, як у будь-якого дубляжу.
  • Приклад — запис на 1 000 символів тексту, одна мова: голосом із каталогу 2 000 кредитів (до 3 000) або $0.016 (до $0.024); клоном чи голосом Sona PRO — 3 000 (до 4 500) або $0.024 (до $0.036).
  • Ліміти — файл до 95 МБ, запис до 2 год, до 6 год записів на добу на акаунт, один запис розпізнається за раз. «Під відео» дає файл тієї ж тривалості, що й запис. Сам файл видаляється, щойно запис розпізнано; текст і mp3 зберігаються 24 години.
411Запит без заголовка Content-Length — надсилай файл звичайним запитом
413Файл більший за 95 МБ
422Запис задовгий (понад 2 год), це не аудіо або це відео, невідома мова запису, виправлений текст відрізняється від розпізнаного більш ніж на 30 % за довжиною, або same для дубляжу запису
429Попередній запис ще розпізнається, вичерпано 6 год записів на добу або вільні слоти тарифу

Діалоги

Кілька голосів в одній озвучці: кожна роль говорить своїм голосом — з паузами, накладаннями й перебиваннями.

Як це працює

Діалог — це ролі й репліки в порядку звучання. Кожна репліка озвучується голосом своєї ролі, і всі вони складаються в один файл. Тишу на початку й у кінці кожної репліки ми обрізаємо, тож пауза між репліками звучить рівно такою, як задано. Гучність ролей вирівнюється: тиха роль не тоне поруч із гучною, а шепіт лишається шепотом. Репліки можуть накладатися, звучати одночасно або перебивати попередню — обірвана репліка плавно затихає там, де її перебили, а накладання не перевантажує звук. Субтитри називають мовця, а кожну роль можна забрати окремою доріжкою.

ЗапитЩо робить
POST /v1/tts + speakers, segmentsОзвучити діалог → job_id; ціну заздалегідь показує POST /v1/tts/quote з тим самим тілом
POST /v1/tts/dialogue/parseРозібрати сценарій або звичайну прозу на ролі й репліки — безкоштовно
GET /v1/tts/{job_id}/dialogueГотовий діалог: хто, що й коли говорить
GET /v1/tts/{job_id}/stemsZIP з окремою доріжкою кожної ролі
GET /v1/dialogue/templatesШаблони діалогів dlg:N: герої та їхні голоси
POST /v1/tts/{job_id}/dub + role_voicesДубляж діалогу іншими мовами

Діалоги вмикаються для акаунта окремо: GET /v1/me повертає "dialogue": true, коли ними можна користуватися. Поки ні, запити діалогу відповідають 403.

У боті

  1. Надішли сценарій текстом або файлом .txt / .docx — кожна репліка з нового рядка: Ім'я: текст. Бот упізнає діалог і відкриє екран ролей «🎭 Діалог: N ролей · M реплік».
  2. На екрані ролей — кнопка для кожної ролі «Ім'я — Голос». Перша роль отримує поточний голос, інші — запропоновані, щоб ролі не звучали однаково. Натисни роль і обери їй голос: збережені, клони, недавні, пошук за назвою, ID або каталог.
  3. Далі › з'являється, коли голос є в кожної ролі: картка покаже ролі, голоси, символи й ціну, а Озвучити запустить діалог. Озвучити одним голосом повертає до звичайної озвучки того самого тексту, Як писати діалог показує формат і команди.
  • 🎭 Розібрати на ролі — кнопка під звичайним текстом без імен: оповідь розбирається на оповідача й персонажів, а слова реплік беруться з твого тексту дослівно.
  • 🎭 Шаблони діалогів — збережені склади героїв із голосами. Шаблон, герої якого збігаються з іменами сценарію, підставляється сам: роль позначена «з шаблону» або «як минулого разу»; 🎭 Шаблон… обирає інший шаблон або жодного.
  • Якщо в сценарії помилка, бот покаже «Рядок N: …» і не прочитає ні імена, ні команди вголос.

Під готовим діалогом:

🎚 Доріжки ролейZIP з окремою доріжкою кожної ролі; якщо він більший за 50 МБ — посилання на нього
✂️ Переозвучити фрагментРепліки списком «Ім'я: текст»: будь-яку можна озвучити ще раз — як була або з виправленим текстом
🌐 Створити дубляжДіалог іншими мовами: обираєш лише мови, голос кожної ролі для кожної мови добирається сам
💾 Зберегти як шаблонГерої цього діалогу з їхніми голосами, швидкістю й емоцією стають новим шаблоном

Формат сценарію

Так сценарій пишеться і в боті, і в POST /v1/tts/dialogue/parse.

  • Репліка — з нового рядка: Ім'я: текст або [Ім'я]: текст. Рядок без імені продовжує попередню репліку.
  • Ремарка в дужках після імені не озвучується: Андрій (пошепки): … — це роль «Андрій».
  • Текст до першого імені читає роль «Оповідач».
  • Команди — у фігурних дужках будь-де в репліці; вони не озвучуються й не оплачуються. Пауза стосується кінця своєї репліки, решта — її початку й відлічується від попередньої репліки. Числа — секунди (можна з комою), з ms чи мс — мілісекунди.
КомандаРосійською · англійськоюЩо робить
{пауза: 1.5}{пауза: 1.5}
{pause: 1.5}
Пауза після цієї репліки, до 30 с
{накладання: 0.7}{наложение: 0.7}
{overlap: 0.7}
Почати за 0.7 с до кінця попередньої репліки
{перебити: 0.7}{перебить: 0.7}
{interrupt: 0.7}
Те саме — і обірвати попередню
{почати через: 2}{начать через: 2}
{start after: 2}
Почати через 2 с після початку попередньої
{перебити через: 2}{перебить через: 2}
{interrupt after: 2}
Те саме — і обірвати попередню
{почати після: "фраза"}{начать после: "фраза"}
{after words: "phrase"}
Почати, щойно в попередній репліці прозвучить фраза; вона має траплятися там рівно один раз
{перебити після: "фраза"}{перебить после: "фраза"}
{interrupt after words: "phrase"}
Те саме — і обірвати попередню
{одночасно}{одновременно}
{simultaneous}
Разом із попередньою реплікою
Автор: Лісова галявина. Над озером стелиться вечірній туман.
Василь: Андрію, ти чуєш? Хтось співає над водою. {пауза: 1}
Андрій (пошепки): Чую. Кажуть, це Мавка, вона заманює рибалок у саму глибину.
Мавка: {перебити після: "заманює рибалок"} Неправда!
Я просто люблю співати, коли сходить місяць.
Василь: {накладання: 0.4} Ой... Вона нас почула.
Автор: Хлопці переглянулися й мовчки рушили додому.

Чотири ролі, сім рядків — шість реплік: після Василевого питання секунда тиші, Мавка перебиває Андрія на словах «заманює рибалок», рядок без імені продовжує її репліку, а Василь починає ще до того, як вона договорить.

API: озвучити діалог

Той самий POST /v1/tts, але замість text і voice — ролі (speakers) і репліки (segments). Решта полів — model, language, format, subtitles, billing_source, max_credits, name — працюють як у звичайній озвучці; speed, volume і emotion запиту діють на ролі без власних. Далі це звичайна задача: статус, /audio, субтитри.

curl -X POST https://api.sonapro.ai/v1/tts \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"sona-3.6","subtitles":true,"dialogue_pause_seconds":0.35,
  "speakers":[
    {"id":"author","name":"Автор","voice":"vc_xxxxxxxxxx"},
    {"id":"vasyl","name":"Василь","voice":"tmpl:3","speed":1.05},
    {"id":"mavka","name":"Мавка","voice":"sona_xxxxxxxxxxxx","volume":0.9,"emotion":"calm"}],
  "segments":[
    {"speaker_id":"author","text":"Над озером стелиться туман.","pause_after_seconds":1},
    {"speaker_id":"vasyl","text":"Чуєш? Хтось співає над водою. Це, мабуть, Мавка."},
    {"speaker_id":"mavka","text":"Так, це я!","start_mode":"after_words",
     "start_after_words":"над водою","interrupt_previous":true},
    {"speaker_id":"vasyl","text":"Вона нас почула.","start_mode":"overlap","start_offset_seconds":0.3}]}'
# → {"job_id":"JOB_ID","status":"queued","chars":202,"language":"uk",
#    "dialogue":{"speakers":3,"segments":4}}

# із шаблоном dlg:3: голоси героїв беруться з нього за іменами, speakers не потрібні
curl -X POST https://api.sonapro.ai/v1/tts \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template":"dlg:3","segments":[{"speaker_id":"Василь","text":"Ти чуєш?"},{"speaker_id":"Мавка","text":"Чую."}]}'
ПолеОпис
speakers2–20 ролей (таблиця нижче). З template — необов'язкові: вони лише перекривають героїв шаблону або додають нових
segments *До 2000 реплік у порядку звучання (таблиця нижче)
dialogue_pause_secondsПауза між репліками, які не задають власної, 0–30 с; типово 0.35
templatedlg:N — шаблон діалогу: кожна роль отримує голос героя з тим самим іменем
textНе потрібен. Якщо передати — має дорівнювати текстам реплік через порожній рядок
speakers[]Опис
id *Унікальний у запиті, до 80 символів; на нього посилаються репліки
nameІм'я в субтитрах, доріжках і шаблонах; типово — id
voice *vc_…, sona_… або tmpl:N
speed0.6–1.5 (або 60–150 %)
volume0.5–2.0 (або 50–200 %): точне підсилення ролі в міксі після вирівнювання гучності
emotionЕмоція ролі
languageМова ролі — у діалозі ролі можуть говорити різними мовами. Типово — мова запиту; auto бере мову голосу ролі, а якщо вона невідома, визначає її з реплік ролі

Пріоритет: поле ролі → поле запиту → пресет збереженого голосу tmpl:N. Наголоси, правила вимови й теги в тексті працюють у кожній репліці так само, як у звичайній озвучці.

segments[]Опис
speaker_id *id ролі
text *Текст репліки
pause_after_secondsПауза після репліки, 0–30 с; замість dialogue_pause_seconds
start_modeКоли починається репліка — таблиця нижче; типово after
start_offset_secondsДля overlap і after_seconds, 0–60 с
start_after_wordsДля after_words: фраза до 200 символів, що трапляється в попередній репліці рівно один раз
interrupt_previoustrue — обірвати попередню репліку там, де починається ця (з будь-яким start_mode, крім after)
interrupt_overlap_secondsСкільки обидва голоси звучать разом перед обривом, 0–0.5 с; типово 0.05
start_modeКоли починається репліка
afterТипово: коли всі попередні репліки стихли, плюс пауза
simultaneousРазом із попередньою
overlapЗа start_offset_seconds до кінця попередньої
after_secondsЧерез start_offset_seconds після початку попередньої
after_wordsЩойно в попередній репліці прозвучить start_after_words

Правило початку відлічується від попередньої репліки й замінює паузу перед нею. Перша репліка завжди after, а одна роль сама на себе не накладається. Відповідь POST /v1/tts додає dialogue — скільки ролей і реплік; quote — dialogue з ролями (id, name, voice, chars), кількістю реплік і credit_multiplier.

API: результат

Статус діалогу містить dialogue — ролі (id, name) і кількість реплік. У готового додаються dialogue_url, stems_url і fragments — кількість реплік, які можна переозвучити.

# 1. Статус
curl https://api.sonapro.ai/v1/tts/JOB_ID -H "X-API-Key: $SONA_API_KEY"
# → … "dialogue":{"speakers":[{"id":"author","name":"Автор"}, …],"segments":4},
#     "dialogue_url":"/v1/tts/JOB_ID/dialogue","stems_url":"/v1/tts/JOB_ID/stems","fragments":4

# 2. Хто, що й коли
curl https://api.sonapro.ai/v1/tts/JOB_ID/dialogue -H "X-API-Key: $SONA_API_KEY"

# 3. Доріжки ролей: ZIP або публічне посилання на нього
curl https://api.sonapro.ai/v1/tts/JOB_ID/stems -H "X-API-Key: $SONA_API_KEY" -o stems.zip
curl https://api.sonapro.ai/v1/tts/JOB_ID/stems/link -H "X-API-Key: $SONA_API_KEY"
# → {"url":"https://api.sonapro.ai/ds/…","expires":1791460800}

# 4. Озвучити третю репліку ще раз, з виправленим текстом
curl -X POST https://api.sonapro.ai/v1/tts/JOB_ID/fragments/3 \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Так, це я! І я все чую."}'

Відповідь GET …/dialogue, скорочено:

{
  "job_id": "JOB_ID",
  "duration": 7.41,
  "speakers": [{"id": "author", "name": "Автор", "voice": "vc_xxxxxxxxxx"}, "…"],
  "segments": [
    {"index": 2, "speaker_id": "vasyl", "speaker_name": "Василь",
     "text": "Чуєш? Хтось співає над водою. Це, мабуть, Мавка.",
     "start": 3.12, "end": 5.06, "interrupted": true},
    {"index": 3, "speaker_id": "mavka", "speaker_name": "Мавка",
     "text": "Так, це я!", "start": 5.01, "end": 6.2, "interrupted": false},
    "…"
  ]
}
  • Доріжки ролей — GET …/stems віддає ZIP: окрема доріжка кожної ролі тієї ж довжини, що й увесь діалог, плюс timeline.json. GET …/stems/link — публічне посилання без ключа (url і expires), зручне для великих файлів.
  • Субтитри (subtitles:true) називають мовця: SRT — «Ім'я: …», одночасна мова — один блок «- А: … / - Б: …», VTT — <v Ім'я>, ASS — поле Name.
  • Репліки як фрагменти — GET /v1/tts/{job_id}/fragments повертає репліки з speaker_id і speaker_name. POST …/fragments/{n} з необов'язковим виправленим text створює нову задачу — увесь діалог, де цю репліку озвучено ще раз; оригінал не змінюється. Ціну заздалегідь показує POST …/fragments/{n}/quote.

API: розбір сценарію

POST /v1/tts/dialogue/parse перетворює текст на ролі й репліки у форматі POST /v1/tts і пропонує кожній ролі голос. Безкоштовно: до 30 запитів на хвилину. Звичайний текст без імен відповідає {"is_dialogue": false}, а з "auto": true розбирається на оповідача й персонажів — до 20 000 символів, до 6 запитів на хвилину; слова реплік беруться з оригіналу дослівно.

# сценарій; voice — поточний голос, його отримає перша роль
curl -X POST https://api.sonapro.ai/v1/tts/dialogue/parse \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Василь: Ти чуєш? {пауза: 1}\nМавка: Чую!","voice":"vc_xxxxxxxxxx"}'

# звичайна оповідь → оповідач і персонажі, без шаблону
curl -X POST https://api.sonapro.ai/v1/tts/dialogue/parse \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Василь озирнувся й гукнув: «Хто тут?» Із туману тихо відповіла Мавка: «Я».","auto":true,"template":"none"}'

Відповідь на перший запит, скорочено:

{
  "is_dialogue": true,
  "auto": false,
  "speakers": [
    {"id": "Василь", "name": "Василь", "lines": 1, "chars": 8,
     "suggested_voice": {"id": "vc_xxxxxxxxxx", "name": "…", "gender": "masculine"},
     "voice_source": "current", "template_voice": null, "remembered_voice": null},
    {"id": "Мавка", "name": "Мавка", "lines": 1, "chars": 4,
     "suggested_voice": {"id": "vc_…", "name": "…", "gender": "feminine"},
     "voice_source": "suggested", "template_voice": null, "remembered_voice": null}
  ],
  "segments": [
    {"speaker_id": "Василь", "text": "Ти чуєш?", "pause_after": 1.0, "start_mode": "after", "…": "…"},
    {"speaker_id": "Мавка", "text": "Чую!", "pause_after": null, "start_mode": "after", "…": "…"}
  ],
  "characters": 12,
  "credit_multiplier": 2.0,
  "language": "uk",
  "template": null
}
  • Поля запиту: text (обов'язкове), auto, voice — поточний голос (vc_…, sona_…, tmpl:N; невідомий просто ігнорується), template, language, model.
  • suggested_voice — голос, з якого роль починає, у порядку: герой шаблону → голос, яким цей герой звучав у твоєму останньому діалозі → voice запиту (лише перша роль) → голос із каталогу, якого не має жодна інша роль. Звідки він — каже voice_source: template, memory, current, suggested або null. Голос із шаблону чи пам'яті приходить зі своїми speed і emotion; самі вони — у template_voice і remembered_voice.
  • template: "dlg:N" — цей шаблон, "none" — без шаблону; без поля застосовується твій шаблон, герої якого покривають найбільше ролей сценарію (щонайменше дві або всі). Відповідь тоді має template — id, name, matched і missing (ролі, яким шаблон не дав голосу), інакше null.
  • segments можна одразу надіслати в POST /v1/tts, додавши голос кожній ролі. Поля в них звуться коротко — pause_after, start_offset, interrupt, interrupt_overlap; POST /v1/tts приймає обидва написання.
  • Сценарій, який не можна озвучити (помилка в команді, забагато ролей чи реплік, задовгий), отримує 422 з причиною «Рядок N: …» ще тут.

Шаблони діалогів

Шаблон — твій збережений склад: герої так, як їх названо в сценаріях, і голос кожного (vc_…, sona_… або tmpl:N), за бажанням — speed, volume, emotion і language. Посилання — dlg:N: номер у межах акаунта, після видалення не повторюється. До 50 шаблонів, у кожному 1–20 героїв, назва — до 60 символів.

ЗапитЩо робить
GET /v1/dialogue/templatesСписок: templates, змінені останніми — першими, і max
POST /v1/dialogue/templatesСтворити → 201; герої списком roles або рядками text
GET /v1/dialogue/templates/{ref}Один шаблон; ref — dlg:N або N
PATCH /v1/dialogue/templates/{ref}Змінити name, roles або text — герої замінюються повністю
DELETE /v1/dialogue/templates/{ref}Видалити → {"deleted": "dlg:3"}
POST /v1/dialogue/templates/from-job/{job_id}Шаблон із героїв готового діалогу → 201; працює й після того, як аудіо видалено
# створити зі списку героїв: один герой на рядок
curl -X POST https://api.sonapro.ai/v1/dialogue/templates \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Лісова пісня","text":"Автор vc_xxxxxxxxxx\nВасиль tmpl:3 1.1\nАндрій: vc_yyyyyyyyyy calm\nМавка = sona_xxxxxxxxxxxx 0.9 sad"}'
# → 201 {"id":"dlg:3","num":3,"name":"Лісова пісня","roles":[
#     {"name":"Автор","voice":"vc_xxxxxxxxxx","voice_name":"…","speed":null,…}, …],…}

# або з героїв готового діалогу
curl -X POST https://api.sonapro.ai/v1/dialogue/templates/from-job/JOB_ID \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Лісова пісня"}'

# перейменувати
curl -X PATCH https://api.sonapro.ai/v1/dialogue/templates/dlg:3 \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Мавка й рибалки"}'
  • Рядки героїв — Ім'я ID [швидкість] [емоція]: між іменем і голосом пробіл, :, -, — чи =; швидкість — 0.6–1.5 або 60–150 %. Рядок, який не вдалося прочитати, — 422 «Рядок N: …».
  • Збіг за іменами — без урахування регістру й зайвих пробілів, «ё» = «е», усі апострофи однакові. POST /v1/tts з "template": "dlg:3" дає кожній ролі голос героя з тим самим іменем, а в субтитрах лишається написання зі сценарію; speakers з тим самим id перекривають героя або додають нового. Роль, якої немає ні там, ні там, — 422 з її іменем. Розбір сценарію підставляє відповідний шаблон сам.
  • Пам'ять героїв — і без шаблону сервіс пам'ятає останній голос кожного героя за іменем (до 500 на акаунт): його записує кожен прийнятий діалог, і наступний розбір пропонує його знову (voice_source: "memory").
  • Якщо збережений голос tmpl:N видалено, герої з ним лишаються без голосу ("voice": null): розбір показує їх у missing, і їм треба дати новий.

Дубляж діалогу

Готовий діалог дублюється так само, як звичайна озвучка, — GET і POST /v1/tts/{job_id}/dub, — але голос задається для кожної ролі окремо. Кожна репліка перекладається з урахуванням попередніх і того, хто їх говорить, озвучується голосом своєї ролі й стає туди, де звучала в оригіналі; обірвана репліка обривається в ту саму мить. Файл кожної мови — тієї ж довжини, що й оригінал, і теж є діалогом: репліки, доріжки ролей, субтитри, переозвучка репліки. Дублювати дубляж ще раз не можна.

# 1. Мови, голоси ролей і ціна
curl https://api.sonapro.ai/v1/tts/JOB_ID/dub -H "X-API-Key: $SONA_API_KEY"
# → … "dialogue":true,"roles":[{"id":"vasyl","name":"Василь","voice":"tmpl:3"}, …],
#     "role_voices":{"en":{"vasyl":{"auto":{"id":"tmpl:3","name":"…"},"choices":[…]}, …}, …}

# 2. Запустити: голос задано лише Мавці англійською, решта — auto
curl -X POST https://api.sonapro.ai/v1/tts/JOB_ID/dub \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"languages":["en","pl"],"role_voices":{"en":{"mavka":"vc_xxxxxxxxxx","author":"native"}}}'
  • role_voices — «мова → роль → голос»: auto, same, native, vc_…, sona_… або tmpl:N; роль без запису отримує auto. Поле voices для діалогу не діє — 422.
  • auto: клон і голос Sona PRO лишаються собою, голос, що говорить цією мовою, — теж; інакше роль отримує голос носія мови тієї ж статі, і дві ролі не отримують один голос.
  • Пропозиція GET …/dub для діалогу додає dialogue: true, roles і role_voices — для кожної мови й ролі, що вибере auto, і до 6 голосів носіїв у choices.
  • mode — як у вкладці «Дубляж»: video (типово) — кожна репліка починається там, де в оригіналі (щоб вирівняти паузи — до пів секунди раніше), файл тієї ж тривалості, під те саме відео; natural — репліки йдуть одна за одною з природними паузами (накладання й перебивання зберігаються), тривалість може відрізнятися.
  • Ціна не залежить від голосів (нижче, «Ціна й ліміти»); мови, до 10 мов за запит, слоти, утримання й max_credits — як у вкладці «Дубляж». Замовити дубляж разом зі створенням діалогу (dub_languages) не можна — лише з готового результату.

Ціна й ліміти

  • Діалог — 2 кредити за символ реплік, якими б голосами вони не звучали; імена, команди, налаштування й паузи не оплачуються. З PAYG (billing_source:"payg") — $16 за мільйон символів реплік. Наприклад, 1 000 символів реплік — 2 000 кредитів або $0.016.
  • Одна репліка ще раз — ×2 до її символів: 2 кредити за символ, з PAYG — $16 за мільйон.
  • Дубляж діалогу — 2 кредити за символ реплік оригіналу за кожну мову, з PAYG — $16 за мільйон на мову. Репліки, які довелося озвучити ще раз, щоб вони влізли в час, доплачуються за тією ж ставкою: при запуску утримується база плюс до 50 %, а невикористане одразу повертається.
  • Ролі — від 2 до 20, id і ім'я — до 80 символів. Репліки — до 2000, разом до 200 000 символів.
  • Паузи — до 30 с, зсуви (start_offset_seconds і числа в командах) — до 60 с. Увесь діалог разом із паузами — до 5 годин; довший отримує 422 ще до списання.
  • Одна задача — діалог займає один слот одночасних задач, скільки б ролей у ньому не було.
  • 24 години — стільки зберігаються файл, доріжки ролей і репліки для переозвучки й дубляжу; потім 410. Шаблон із готового діалогу можна зберегти й пізніше.

Помилки

У разі відмови нічого не списується.

400Тіло запиту не вдалося прочитати — наприклад, воно не в UTF-8
402Недостатньо кредитів або коштів PAYG
403Діалоги ще не увімкнено для цього акаунта (GET /v1/me → "dialogue": false), або PAYG для акаунта вимкнено
404Задачу чи шаблон не знайдено, задача — не діалог, або немає репліки з таким номером
409Діалог ще не готовий, ціна вища за max_credits / max_microusd, уже збережено 50 шаблонів, або це вже дубляж
410Файли діалогу вже видалено за строком зберігання
422Помилка в ролях, репліках чи сценарії — з місцем: «Роль …», «Репліка N: …», «Рядок N: …»; невідомий голос, недоступна мова ролі, задовгий діалог, героя немає в шаблоні; у запиті діалогу є voice, accent чи dub_languages; автоматичному розбору не можна довіряти
429Забагато запитів (розбір — 30 на хвилину, з auto — 6) або зайняті всі слоти одночасних задач
503Діалоги чи автоматичний розбір тимчасово недоступні або тривають технічні роботи

Наголоси, вимова й емоції

Клон передає тембр, а читає текст модель. Тому наголос і вимова налаштовуються через текст.

Три рівні роботи з наголосом

РівеньПрикладКоли застосовувати
1. Знак U+0301за́мок / замо́кПерша підказка для неоднозначного слова
2. Велика голосназАмок / замОкЛише зручний запис: SONA перетворить його на той самий U+0301
3. Фонетична замінаТарас → та-РАСТільки якщо модель проігнорувала обидві підказки і заміну перевірено на слух

U+0301 і велика літера — не два різні методи. Велика голосна всередині кириличного слова лише конвертується в U+0301. Якщо модель ігнорує знак, вона може ігнорувати обидва варіанти.

Персональний словник SONA: як він працює з кирилицею

Це не готовий орфоепічний словник усієї мови й не автоматичний пошук наголосів. Це список власних винятків акаунта: перед озвученням SONA знаходить term у тексті й буквально підставляє replacement. Ідентифікатор словника в POST /v1/tts передавати не потрібно — збережені правила застосовуються автоматично.

ВластивістьПоведінка SONA
КирилицяПідтримується і в term, і в replacement. Фонетичну підказку можна записати звичайними українськими/російськими літерами.
РегістрТипово case_sensitive: false: Тарас знаходить Тарас, тарас і ТАРАС. З case_sensitive: true правило US не змінює us, а LaTeX не змінює latex. Ключ малими літерами також приймає початкову велику: cat → cat / Cat, але не CAT. Діє в Sona 3.5 і 3.6.
МежіЗбіг лише за цілим словом або цілою фразою. Правило Тарас не змінює Тараса чи Тарасові.
ВідмінкиКожну потрібну словоформу зберігай окремо: Тараса → та-РА-са, Тарасові → та-РА-со-ві. Це приклади формату — кожну заміну перевір на слух.
Область діїПравила належать акаунту, а не одному голосу: вони діють у боті та API для всіх його голосів і шаблонів.
ПорядокДовші фрази застосовуються раніше за коротші слова. Ліміт — 50 правил; term до 60, replacement до 160 символів.

Для слова зі словника пиши в сценарії звичайне написання. Не додавай одночасно U+0301 або велику голосну: словник застосовується після нормалізації наголосу, тому змінене написання вже не дорівнюватиме збереженому term. Після підміни саме фінальний текст іде в озвучення, субтитри та підрахунок символів.

Приклад правила з урахуванням регістру для POST /v1/pronunciation: {"term":"US","replacement":"United States","case_sensitive":true}. Старі правила зберігають попередню поведінку. Правила з перетином написань повертають 422: спочатку зміни або видали попереднє правило. Для оновлення чи видалення конкретного варіанта передавай точний term зі списку правил.

# додати або оновити одне правило
curl -X POST https://api.sonapro.ai/v1/pronunciation \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"term":"Тарас","replacement":"та-РАС"}'

# окремі правила для відмінюваних форм
curl -X POST https://api.sonapro.ai/v1/pronunciation \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"term":"Тараса","replacement":"та-РА-са"}'

# переглянути всі правила акаунта
curl https://api.sonapro.ai/v1/pronunciation \
  -H "X-API-Key: $SONA_API_KEY"

# видалити правило; кирилицю в URL треба percent-encode
curl -X DELETE https://api.sonapro.ai/v1/pronunciation/%D0%A2%D0%B0%D1%80%D0%B0%D1%81 \
  -H "X-API-Key: $SONA_API_KEY"

Коли використовувати: для імен, брендів, абревіатур і термінів, які стабільно читаються неправильно. Якщо проблема лише в наголосі й U+0301 спрацьовує, словник не потрібен. Фонетична підміна — sounds-like підказка, а не гарантія, тому тестуй короткою озвучкою на потрібній мові.

Перевірене правило: Тарас

Для українського голосу Taras модель читала ТАрас і ігнорувала знак наголосу. Прослухана заміна та-РАС дала правильне ТарАс.

curl -X POST https://api.sonapro.ai/v1/pronunciation \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"term":"Тарас","replacement":"та-РАС"}'

Правило діє лише на ціле слово, незалежно від регістру, і автоматично застосовується до всіх озвучок цього API-акаунта. Не розбивай весь текст на склади і не вигадуй IPA: кожну фонетичну заміну спочатку треба прослухати.

Промпт для Claude / ChatGPT

Встав промпт перед сценарієм. AI проаналізує весь текст, а не лише слово «Тарас», і поверне готовий варіант для SONA.

Ти — редактор тексту для озвучення SONA.

Проаналізуй увесь текст у контексті та підготуй його до природної машинної озвучки.

Правила:
1. Не змінюй зміст, стиль, факти та мову.
2. Збережи природну пунктуацію і абзаци — вони керують паузами.
3. Знайди слова, які TTS може прочитати неправильно. Особливо перевір:
   - імена та прізвища;
   - географічні назви;
   - бренди, назви продуктів і компаній;
   - абревіатури;
   - іншомовні вставки й запозичення;
   - рідкісні терміни та омографи.
4. Якщо неоднозначний лише наголос, постав U+0301 після наголошеної голосної:
   за́мок / замо́к, му́ка / мука́.
5. Якщо знака наголосу може бути недостатньо і правильна вимова тобі достовірно
   відома, перепиши ЛИШЕ проблемне слово фонетично:
   - розділи його на зручні для читання частини дефісами;
   - наголошений склад напиши ВЕЛИКИМИ літерами;
   - збережи відмінкове закінчення конкретної форми слова.
6. Не обмежуйся словом «Тарас». Самостійно знаходь інші проблемні слова за
   контекстом, але не вигадуй вимову, якщо не впевнений.
7. Орієнтири формату:
   - Тарас → та-РАС
   - OpenAI → оупен-ей-АЙ
   - ChatGPT → чат-джі-пі-ТІ
   - Renault → ре-НО
8. Не розбивай звичайні слова на склади, не вставляй IPA і не переписуй увесь текст
   фонетично. Уже наявні теги <emotion value="..."/> збережи без змін.
9. Поверни лише готовий текст для озвучення без пояснень, списків і коментарів.

Мій текст:
"""
[ВСТАВ ТЕКСТ]
"""

Теги в тексті

Поля speed, volume і emotion задають одну манеру на всю озвучку. Ті самі три контролі можна поставити прямо в текст — і додати паузу, вимову по літерах та смішок. Теги працюють на sona-3.5 і sona-3.6; [laughter] розрахований на sona-3.6, типову модель; з "model":"sona-3.5" на нього не розраховуй.

<speed ratio="0.8"/>0.6–1.5від цього місця й далі
<volume ratio="0.5"/>0.5–2.0від цього місця й далі
<emotion value="sad"/>список нижчевід цього місця й далі
<break time="700ms"/>ms або s, до 10 содна пауза тут
<spell>Bob</spell>—вимовити по літерах
[laughter]—один смішок тут
<volume ratio="0.6"/><speed ratio="0.8"/>Тут подаю тихіше й повільніше.<break time="1s"/>
<volume ratio="1"/><speed ratio="1"/>А тут уже як завжди.
<emotion value="excited"/> Не повіриш, що я дізнався! [laughter]
<emotion value="sad"/> Але потім усе пішло не так…

Великі літери, кому замість точки й забутий слеш ми виправляємо самі (<SPEED RATIO="0,8"> → <speed ratio="0.8"/>), а поламаний тег повертає 422 з поясненням — щоб він не «не спрацював» тихо. Текст у кутових дужках, що не є тегом, озвучується як цитата: <<Стій!>> стає «Стій!», 5 < 10 > 3 — 5 ‹ 10 › 3 (без цього рушій мовчки пропускав усе в дужках). HTML-теги на кшталт <b> не звучать. Довгий текст ми ріжемо на частини й самі перевідкриваємо активні speed/volume/emotion у кожній наступній, тому їхня дія не обривається посеред озвучки.

emotion поки в стані beta й найкраще звучить англійською — на інших мовах різниця може бути не чутна; speed і volume — підказка, а не точний множник. <break> розриває генерацію в цьому місці, тому кілька пауз поспіль звучать неприродно. Символи тегів входять у chars, а в субтитри не потрапляють: там лишається тільки те, що звучить.

Повний список · 58 емоцій

neutral, happy, excited, enthusiastic, elated, euphoric, triumphant, amazed, surprised, flirtatious, curious, content, peaceful, serene, calm, grateful, affectionate, trust, sympathetic, anticipation, mysterious, angry, mad, outraged, frustrated, agitated, threatened, disgusted, contempt, envious, sarcastic, ironic, sad, dejected, melancholic, disappointed, hurt, guilty, bored, tired, rejected, nostalgic, wistful, apologetic, hesitant, insecure, confused, resigned, anxious, panicked, alarmed, scared, proud, confident, distant, skeptical, contemplative, determined

Генерація зображень

Генерація з тексту та з фото-референсом.

POST /v1/imagesJSON: prompt, model, size → image_id. Prefer: respond-async повертає 202 одразу.
POST /v1/images/editmultipart із повторюваним полем images: Nano Banana 2.1 / Pro і GPT Image 2.5 — до 10 файлів
GET /v1/images/{image_id}Статус задачі. Якщо error: пояснення в detail і error_code — content_refused (модель відхилила сам запит, refusal_reason як у відео, retryable:false — змініть промпт) або generation_failed (retryable:true); оплата повертається сама
GET /v1/images/{image_id}/fileЗавантажити файл
GET /v1/images?limit=20Історія акаунта

Приклад

# пакет Nano або раніше придбані кредити: billing_source можна не вказувати (auto)
curl -X POST https://api.sonapro.ai/v1/images \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: respond-async" \
  -d '{"prompt":"Cinematic portrait in soft blue light","model":"nano-banana-2","size":"1024x1024"}'

# PAYG-баланс ($0.015): billing_source:"payg" обов’язковий, без нього auto поверне 402
curl -X POST https://api.sonapro.ai/v1/images \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: respond-async" \
  -d '{"prompt":"Cinematic portrait in soft blue light","model":"nano-banana-2","size":"1024x1024","billing_source":"payg","max_amount_microusd":15000}'

# edit із кількома референсами (повторюй -F images=@... до ліміту моделі; для PAYG додай -F billing_source=payg)
curl -X POST https://api.sonapro.ai/v1/images/edit \
  -H "X-API-Key: $SONA_API_KEY" -H "Prefer: respond-async" \
  -F 'prompt=Збережи людей і обʼєднай композицію' \
  -F 'model=nano-banana-pro' \
  -F 'images=@reference-1.jpg' -F 'images=@reference-2.png'

# GPT Image 2.5 через PAYG ($0.03); із раніше придбаними кредитами billing_source можна не вказувати
curl -X POST https://api.sonapro.ai/v1/images \
  -H "X-API-Key: $SONA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: respond-async" \
  -d '{"prompt":"Cinematic portrait in soft blue light","model":"gpt-image-2.5","size":"2048x1152","billing_source":"payg","max_amount_microusd":30000}'

# опитуй GET /v1/images/IMAGE_ID до status=done, потім завантаж download_url

Розміри (size)

sizeФорматNano Banana 2.1 / ProGPT Image 2.5
1024x10241:1, квадрат1024×1024≈1254×1254
2048x115216:9, широкий2048×1152≈1672×941
1152x20489:16, вертикальний1152×2048≈941×1672
1536x11524:3, альбомний1536×1152≈1448×1086
1152x15363:4, портретний1152×1536≈1086×1448

За замовчуванням — 1024x1024; інші значення повертають 422. Nano Banana віддає файл рівно запитаного розміру. Для GPT Image 2.5 size обирає лише пропорцію: файл приходить у власній роздільності моделі (~1,5 Мп), без апскейлу. Той самий size приймає POST /v1/images/edit.

Моделі

МодельmodelРеференсиОплата
Nano Banana 2.1nano-banana-2до 10пакет Nano, PAYG або раніше придбані кредити
Nano Banana Pronano-banana-proдо 10те саме, що й Nano Banana 2.1: спільний денний ліміт пакета
GPT Image 2.5gpt-image-2.5до 10PAYG — $0.03 або раніше придбані кредити (за тарифом покупки)

Не хардкодь список: GET /v1/me повертає в image.model_options лише моделі, доступні саме цьому акаунту, разом із ціною (billing_options). Поле model обов’язкове — моделі за замовчуванням немає.

Як оплачується зображення

  • Пакет Nano на 30 днів: Старт $27 — 600 зображень на день, 5 одночасно; Про $45 — 1 200 на день, 7 одночасно; Ультра $90 — 3 500 на день, 14 одночасно. Nano Banana 2.1 і Pro рахуються в один денний ліміт; невикористаний ліміт не переноситься.
  • PAYG — $0.015 за генерацію з грошового балансу. Лише явно: передай billing_source:"payg" (у multipart — поле billing_source=payg). Щоб зафіксувати ціну, додай max_amount_microusd.
  • Раніше придбані кредити — 1 000 за Nano Banana 2.1 або Pro.
  • GPT Image 2.5 — PAYG, $0.03 за зображення (billing_source:"payg"), або кредити, придбані до переходу на пакети, — за тарифом покупки (Start 2 500 · Pro 3 333 · Business 6 000 · Ultra 9 000), auto бере їх першими. Пакети й кредити, куплені після переходу, її не оплачують: без старих кредитів auto повертає 402. size задає тільки пропорцію — файл приходить у власній роздільності моделі (~1,5 Мп, напр. 1672×941 для 16:9). Старі ID gpt-image-2 і sona-image приймаються.

Типове billing_source:"auto" бере пакет, а без пакета — раніше придбані кредити. Гроші з PAYG воно не витрачає ніколи: якщо ні пакета, ні кредитів немає, прийде 402. Якщо генерація не вдалася, оплата повертається автоматично. Зображення віддаються в оригіналі 1080 так, як їх генерує модель, без апскейлу. quality=2k вимкнено, воно повертає 422.

Генерація відео

Veo 3.1 · 720p · з тексту й з референсами — 8 с, від першого кадру — зараз 6 с · один ендпоінт для тексту й фото.

POST /v1/videosСтворити відео → 202 + video_id. JSON — відео з тексту; multipart/form-data — відео з 1–3 фото
GET /v1/videos/{video_id}Статус: queued → processing → done або error
GET /v1/videos/{video_id}/fileЗавантажити MP4 (H.264 + AAC)
GET /v1/videos?limit=20Історія відео акаунта

Параметри

ПолеЗа замовч.Опис
prompt *—Що відбувається в кадрі, до 4000 символів
modelveo-3.1Єдина модель відео
aspect_ratio16:916:9 (горизонтальне) або 9:16 (вертикальне)
images—Лише multipart, повторюване поле, PNG/JPEG/WEBP до 10 МБ. 1 фото — перший кадр; 2 — перший і останній кадри; 3 — референси (персонаж, предмет, стиль). Більше трьох — 422
image_modeза кількістюРоль фото замість правила кількості: frames — 1–2 фото як перший / перший і останній кадр; references — 1–3 фото як референси. frames із трьома фото — 422
resolution720p720p або 1080p. 1080p — лише з billing_source:"payg", $0.03; якщо 1080p зараз недоступне — 503, нічого не списується. Статус повертає resolution готового файла: коли збільшення до 1080p не вдалося, приходить 720p і списується $0.02
billing_sourceautoauto, plan або payg — як і для зображень
max_amount_microusd—Стеля ціни для PAYG; дорожче — 409 без списання

Відповідь завжди асинхронна: відео рендериться від 1 до кількох хвилин, тож POST одразу повертає 202, а готовий файл забираєш за download_url зі статусу. Відео з тексту — 8 с. Тривалість відео з фото задає сервіс рендеру: від першого кадру (1–2 фото) зараз 6 с, з трьома референсами — 8 с. Тому до завершення duration_s для нього дорівнює null. У готовому відео duration_s — справжня тривалість файлу.

Приклад

# 1. Відео з тексту
curl -X POST https://api.sonapro.ai/v1/videos \
  -H "X-API-Key: $SONA_API_KEY" -H "Content-Type: application/json" \
  -d '{"prompt":"Паперовий кораблик пливе ставком на світанку","aspect_ratio":"16:9"}'
# → 202 {"video_id":"...","status":"queued","model":"veo-3.1","status_url":"/v1/videos/..."}

# 2. Відео з фото: перший кадр — твоє зображення
curl -X POST https://api.sonapro.ai/v1/videos \
  -H "X-API-Key: $SONA_API_KEY" \
  -F 'prompt=Камера повільно наближається, листя ворушить вітер' \
  -F 'aspect_ratio=9:16' \
  -F 'images=@first-frame.jpg'

# 3. Опитуй статус до done і забери MP4
curl https://api.sonapro.ai/v1/videos/VIDEO_ID -H "X-API-Key: $SONA_API_KEY"
curl https://api.sonapro.ai/v1/videos/VIDEO_ID/file -H "X-API-Key: $SONA_API_KEY" -o clip.mp4

Доступ і оплата

  • Відео доступне кожному акаунту. Якщо менеджер вимкнув Veo для акаунта, POST /v1/videos повертає 403, а GET /v1/me показує video.allowed:false.
  • Пакет Veo на 30 днів, кількість відео необмежена: Старт $45 — 2 відео одночасно; Про $95 — 6; Ультра $140 — 10. Пакет підключає менеджер.
  • PAYG — $0.02 за відео з грошового балансу, лише явно: передай billing_source:"payg". Щоб зафіксувати ціну, додай max_amount_microusd (20000). Відео 1080p (resolution:"1080p") — $0.03 (30000), лише через PAYG.

GET /v1/me → video: allowed, models, aspect_ratios, duration_s, max_references, resolutions (доступні зараз) і billing_options — ціна для цього акаунта. Якщо рендер не вдався, статус повертає error із поясненням у detail, і оплата повертається сама. Поле error_code: content_refused — модель відхилила сам запит за своїми правилами (refusal_reason: real_person, intellectual_property, minor, audio, sexual, violence, unsafe, prohibited, prompt або policy; retryable:false — змініть промпт або зображення), або generation_failed (retryable:true). Той самий запит (промпт + зображення), відхилений двічі (через звук — тричі), 24 год не приймається: POST одразу відповідає 422, нічого не списується.

Результат і помилки

Статуси задачі, файли, субтитри і HTTP-коди.

Життєвий цикл

queued→processing→done

Також можливі error і canceled. Аудіо, зображення й відео зберігаються обмежений час; після видалення endpoint поверне 410.

Історія задач — GET /v1/activity

Останні задачі акаунта, якому належить ключ: озвучки, зображення й відео разом. Незавершені (queued, processing) ідуть першими, далі — від найновіших. Так видно, які запити вже виконано, а які ні, навіть якщо job_id загубився.

kindvoice, image або video; кілька — через кому. Без параметра — усі.
statusqueued, processing, done, error або canceled; кілька — через кому. Без параметра — усі.
limitСкільки задач повернути: від 1 до 100, за замовчуванням 12.
curl "https://api.sonapro.ai/v1/activity?kind=voice&status=queued,processing,error&limit=50" -H "X-API-Key: $SONA_API_KEY"

Відповідь, скорочено:

{
  "jobs": [
    {"id": "3f9c2a…", "kind": "voice", "name": "chapter_2", "status": "processing",
     "created_at": "2026-10-09T10:27:03+00:00", "finished_at": null},
    {"id": "8a41d0…", "kind": "voice", "name": "chapter_1", "status": "done",
     "created_at": "2026-10-09T10:12:40+00:00", "finished_at": "2026-10-09T10:13:05+00:00"}
  ],
  "payments": []
}

id — це job_id озвучки, image_id зображення або video_id відео: статус і файл забирай звичайними запитами (/v1/tts/{job_id}/audio, /v1/images/{image_id}/file, /v1/videos/{video_id}/file). Файли зберігаються обмежений час, запис в історії лишається. Невідоме значення kind чи status повертає 422. payments — останні платежі акаунта.

Субтитри

Передай subtitles:true під час створення. Потім забери srt, vtt, ass, json або zip; ZIP містить аудіо і всі формати разом.

HTTP-коди

400Некоректний формат запиту
401Відсутній або невірний API-ключ
402Недостатньо кредитів, немає активного пакета або порожній PAYG-баланс
403Модель або продукт не підключені цьому акаунту (напр. відео, поки його не увімкнув менеджер)
404Ресурс не знайдено
409Ціна вища за передану стелю (max_credits / max_amount_microusd) — нічого не списано
410Файл уже видалено за строком зберігання
422Невірне поле, ID голосу або межа параметра
429Забагато запитів, зайняті всі одночасні задачі або вичерпано денний ліміт пакета
503Сервіс/голос тимчасово недоступний; враховуй Retry-After