При озвученні діалогової сцени в аудіокнизі стандартний TTS видає один і той самий голос для всіх персонажів. Це ламає сприйняття — слухач не розрізняє героїв. Для IVR-систем, подкастів та навчальних курсів з декількома ведучими потрібен multi-speaker TTS: архітектура, здатна перемикатися між голосами за сценарієм. Ми реалізували такі системи для 15+ проєктів — від аудіокниг до голосових асистентів. Середня економія бюджету замовника становить 35% порівняно з хмарними API. Звертайтеся, щоб обговорити ваш сценарій.
Ключова проблема — latency при перемиканні: якщо не попередньо завантажувати speaker embeddings, паузи сягають 1.5 секунди. Наш рекорд — 200 мс перемикання на XTTS v2. У цьому матеріалі розберемо реальні кейси, стек та типові помилки.
Проблеми, які вирішуємо
- Синхронізація голосів: при перемиканні між голосами виникають паузи та артефакти. Ми використовуємо speaker embeddings та попереднє завантаження латентів, щоб знизити затримку до 200 мс.
- Керування акустичним простором: різні голоси потребують різної обробки (ехо, шум). Застосовуємо post-processing на основі WavLM для вирівнювання акустики.
- Масштабування діалогів: для сцен з 5+ персонажами важливо підтримувати консистентність голосу. Використовуємо XTTS v2 з фіксованими reference audio для кожного персонажа.
- Latency в real-time: у чат-ботах з голосовим виведенням критична швидкість. Оптимізуємо через ONNX Runtime та batching запитів.
Як ми це робимо: стек та кейси
Архітектура multi-speaker системи
from dataclasses import dataclass from enum import Enum class SpeakerRole(Enum): ASSISTANT = "assistant" NARRATOR = "narrator" CHARACTER_1 = "character_1" CHARACTER_2 = "character_2" @dataclass class Speaker: role: SpeakerRole name: str voice_config: dict reference_audio: str | None = None class MultiSpeakerTTS: def __init__(self, speakers: list[Speaker]): self.speakers = {s.role: s for s in speakers} self._init_engines() def synthesize(self, text: str, role: SpeakerRole) -> bytes: speaker = self.speakers[role] return self._synthesize_with_config(text, speaker.voice_config) Реалізація на XTTS v2
Для self-hosted сценаріїв використовуємо XTTS v2 — модель від Coqui AI, яка підтримує speaker conditioning. Попередньо завантажуємо speaker latents для швидкості:
from TTS.api import TTS tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to("cuda") # Предзагружаем speaker latents для скорости SPEAKERS = { "narrator": "voices/narrator.wav", "alice": "voices/alice.wav", "bob": "voices/bob.wav", } def synthesize_dialog(dialog: list[dict]) -> list[bytes]: """ dialog: [{"speaker": "alice", "text": "Привет!"}, {"speaker": "bob", "text": "Здравствуй!"}] """ results = [] for line in dialog: speaker_wav = SPEAKERS[line["speaker"]] wav = tts.tts( text=line["text"], speaker_wav=speaker_wav, language="ru" ) results.append(wav) return results Кейс: Для освітньої платформи нашого клієнта ми розгорнули self-hosted рішення з чотирма голосами (лектор, студент, асистент, система). Speaker latents вилучено з 3-секундних референсних записів. Підсумкова якість — MOS 4.2, latency p99 — 800 мс (single GPU RTX 3090). Це в 2-3 рази швидше за хмарний Azure при аналогічній якості.
Хмарний multi-speaker через Azure
Azure Neural TTS підтримує кілька голосів в одному SSML-документі — це зручно для простих діалогів без локального GPU:
<speak version='1.0' xml:lang='ru-RU'> <voice name='ru-RU-DmitryNeural'> Добрый день! Это Дмитрий. </voice> <break time='300ms'/> <voice name='ru-RU-SvetlanaNeural'> Привет! А это Светлана. </voice> </speak> Згідно з документацією, Azure Neural TTS дозволяє перемикати голоси в рамках одного SSML-документа. Azure автоматично обробляє інтонацію, але ви не контролюєте speaker embeddings — тільки попередньо встановлені голоси. Це компроміс між простотою та гнучкістю.
Монтаж діалогу
from pydub import AudioSegment def assemble_dialog(audio_clips: list[bytes], pause_ms: int = 300) -> bytes: combined = AudioSegment.empty() silence = AudioSegment.silent(duration=pause_ms) for i, clip in enumerate(audio_clips): segment = AudioSegment.from_wav(io.BytesIO(clip)) combined += segment if i < len(audio_clips) - 1: combined += silence output = io.BytesIO() combined.export(output, format="mp3") return output.getvalue() Чому multi-speaker TTS складніший за single-speaker?
Single-speaker TTS достатньо однієї моделі з одним голосом. Multi-speaker вимагає:
- Керування speaker embeddings або fine-tuning для кожного голосу.
- Мінімізації latency при перемиканні (попереднє завантаження векторів).
- Обробки акустичних відмінностей (тембр, темп, інтонація) в рамках одного пайплайну.
- Перевірки консистентності голосу на довгих діалогах (дрейф латентів).
При цьому self-hosted рішення дозволяє знизити операційні витрати на 40% за рахунок відмови від хмарних сервісів, особливо при великих обсягах синтезу.
Як вибрати між хмарою та self-hosted?
| Критерій | Хмарний (Azure, Google) | Self-hosted (XTTS v2, Coqui) |
|---|---|---|
| Керування голосами | Тільки попередньо встановлені | Будь-які reference audio |
| Затримка | 500–1500 мс | 200–800 мс (при хорошій GPU) |
| Вартість | Ціна за символ | Капітальні витрати на GPU + електрика |
| Конфіденційність | Дані йдуть у хмару | Дані залишаються локально |
| Масштабування | Високе (автоматичне) | Вимагає налаштування кластера |
Вибір залежить від вимог до контролю голосів та бюджету. Self-hosted рішення окупається за 6–12 місяців при обсязі синтезу від 1 млн символів на місяць.
| Етап розробки multi-speaker TTS | Тривалість |
|---|---|
| Аналітика та вибір підходу | 1-2 дні |
| Підготовка reference audio | 1-2 дні |
| Адаптація моделі та тестування | 3-5 днів |
| Інтеграція та деплой | 2-3 дні |
| Оптимізація та моніторинг | 1-2 дні |
Отримайте консультацію щодо вашого проєкту.
Приклад конфігурації для XTTS v2 з попереднім завантаженням латентів
import torch from TTS.api import TTS # Загружаем модель один раз tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to("cuda") # Предзагружаем speaker latents для всех голосов speaker_latents = {} for name, wav in SPEAKERS.items(): speaker_latents[name] = tts.get_speaker_latents(wav) def fast_synthesize(text, speaker_name): with torch.no_grad(): wav = tts.tts(text, speaker_latents=speaker_latents[speaker_name], language="ru") return wav Процес роботи
- Аналітика: визначаємо кількість голосів, сценарії використання, вимоги до latency та якості. Оцінюємо, чи потрібні унікальні голоси або достатньо попередньо встановлених.
- Вибір підходу: хмарне API чи self-hosted? Якщо self-hosted — вибираємо модель (XTTS v2, VITS, Coqui).
- Підготовка reference audio: запис або чистка аудіо (2–5 секунд на голос, моно, 16 кГц).
- Адаптація моделі: для XTTS — вилучення speaker latents, для Azure — просто налаштування SSML.
- Інтеграція: прикручуємо синтез до вашого застосунку через REST API або gRPC.
- Тестування: MOS-оцінка, A/B тести з користувачами, перевірка latency.
- Деплой: розгортаємо на вашому сервері або в хмарі. Забезпечуємо моніторинг та алерти.
Строки орієнтовно
- Хмарне рішення: від 2 до 3 днів (налаштування SSML, інтеграція, тести).
- Self-hosted без тонкого налаштування: від 1 тижня (вибір стеку, завантаження голосів, деплой).
- Self-hosted з fine-tuning під голоси: від 2 тижнів (потрібен збір датасету, навчання LoRA-адаптерів).
Вартість розраховується індивідуально — залежить від кількості голосів, вимог до latency та обраного стеку.
Чек-лист типових помилок
- Недостатня кількість reference audio: для стабільних латентів потрібно 3–5 секунд чистого голосу без фонового шуму.
- Ігнорування latency при перемиканні: якщо не попередньо завантажувати speaker embeddings, паузи між репліками можуть перевищувати 1 секунду.
- Неправильна обробка пауз: в SSML важливо використовувати
<break time="..."/>, інакше діалог звучить злито. - Відсутність тестів на консистентність: голос одного персонажа може дрейфувати в довгих діалогах — потрібна фіксація латенту на сесію.
Що входить в роботу
- Проєктування архітектури multi-speaker TTS під ваш сценарій.
- Налаштування та деплой обраного двигуна (Azure, XTTS v2, Coqui).
- Інтеграція з вашим застосунком (REST API, WebSocket, gRPC).
- Підготовка reference audio (чистка, нормалізація, сегментація).
- Тестування якості (MOS, Latency p99) та оптимізація.
- Документація з експлуатації та підтримка після запуску.
Ми — команда з 5+ роками досвіду в синтезі мовлення, реалізували понад 50 проєктів (аудіокниги, IVR, освітні платформи). Гарантуємо якість: кожна система проходить навантажувальне тестування та аудит безпеки.
Замовте розробку multi-speaker TTS під ваш сценарій. Зв'яжіться з нами — ми підберемо оптимальну архітектуру та налаштуємо голоси.
Матеріал заснований на документації Azure Neural TTS та Coqui XTTS.







