При озвученні діалогової сцени в аудіокнизі стандартний 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.







