Files
Blind/modules/tts/README.md
T
2026-09-11 19:47:15 +03:00

104 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Модуль 3: TTS (текст → звук)
Два провайдера за общим интерфейсом `TtsProvider`: переключение = выбор в конфиге.
| Провайдер | Сеть | Латентность (110 симв.) | Голоса | Роль |
|---|---|---|---|---|
| **edge** (`provider_edge.py`) | онлайн, бесплатный сервис MS, без ключа | 3.0 c (4 предл.), 1.7 c (короткая) | Svetlana/Dmitry, отличное качество | основной |
| **piper** (`provider_piper.py`) | офлайн, локально на CPU | 0.47 c | dmitri/irina/ruslan, проще | фолбэк без сети |
## Режимы edge-провайдера
- **Один запрос** (по умолчанию): весь текст → один round-trip (~1.7–3 c). Паузы между
предложениями удлиняются многоточиями («точка» → «…» — edge-tts читает как длинную паузу).
- **per_sentence=True**: каждое предложение отдельным запросом + точная тишина
`sentence_pause_sec` между ними. Медленнее (N запросов), нужен для тонкой подгонки пауз.
Замер 2026-09-11 (свежие соединения в каждом процессе): один запрос 110 симв = 3.0 c,
короткая фраза 36 симв = 1.7 c, Piper 110 симв = 0.47 c. В живой программе соединение
переиспользуется — будет быстрее. Цепочка целиком: STT ~1.2 c + LLM ~1–2 c + TTS ~1.7 c ≈ 4–5 c
от отпускания клавиши до голоса (маскируется earcon «думаю»).
## Использование из кода
```python
from modules.tts import get_provider
tts = get_provider("edge") # voice="ru-RU-DmitryNeural" — мужской
result = tts.synthesize("Привет! Как дела?")
# result.audio (float32), result.samplerate, result.generation_sec, result.duration_sec
```
Фолбэк при обрыве сети (switch = одна строка):
```python
tts = get_provider("piper", model_path="models/piper/ru_RU-dmitri-medium.onnx")
```
## Потоковая озвучка (стриминг, 2026-09-11)
`tts.stream(text)` — генератор: отдаёт чанки-предложения **по мере готовности**
(параллельные запросы, отдача в порядке следования). `Assistant` играёт чанк
сразу, не дожидаясь синтеза всего текста:
- первое предложение звучит через ~0.5 c после готовности LLM (один round-trip);
- длинные ответы больше не пропорционально тормозят (2-е/3-е предложение
синтезируются, пока играет 1-е);
- между чанками вставляется пауза sentence_pause_sec;
- перебивание отцом гасит поток и синтез (счётчик поколений).
Плюс в `Player.play()` добавлен префикс тишины 0.1 c (`lead_silence_sec`) —
защита от «съедания» первого слова при открытии аудио-потока (недозаполненный
буфер ALSA/Pulse).
## Настройка из .env (2026-09-11)
```
TTS_PROVIDER=edge # edge | piper
TTS_VOICE=ru-RU-SvetlanaNeural # мужской: ru-RU-DmitryNeural
TTS_RATE=+15 # темп речи, % (+ = быстрее; ≈+30% к исходному −15)
PIPER_MODEL=models/piper/ru_RU-dmitri-medium.onnx
```
Выбранный конфиг юзером: **edge + Svetlana, rate +15** («женский голос лучше и темп
нормальный»). Piper остаётся офлайн-фолбэком (0.22 c синтез против 0.49 c у edge),
при желании ускориться — одна строка в .env.
Фабрика: `make_tts()` из `modules/tts` — тесты ассистента читают эти параметры
автоматически, смену голоса/скорости/провайдера можно делать без правки кода.
## Файлы
| Файл | Назначение |
|---|---|
| `base.py` | Интерфейс `TtsProvider`, результат `SynthResult` |
| `provider_edge.py` | edge-tts: один запрос / сшивание предложений |
| `provider_piper.py` | Piper офлайн (`length_scale` из rate автоматом в config) |
| `config.py` | `make_tts()` — фабрика из .env (провайдер, голос, скорость) |
| `text_split.py` | Разбивка на предложения; защита сокращений («т.д.», «т.к.») |
| `test_tts.py` | Тест-скрипт (синтез / воспроизведение / интерактив / провайдеры) |
## Тест-скрипт
```bash
.venv/bin/python modules/tts/test_tts.py --play # фраза по умолчанию + звук
.venv/bin/python modules/tts/test_tts.py --text "Своё предложение"
.venv/bin/python modules/tts/test_tts.py --voice ru-RU-DmitryNeural --play # мужской
.venv/bin/python modules/tts/test_tts.py --listen # вводишь текст — слышишь
.venv/bin/python modules/tts/test_tts.py --per-sentence # медленный режим (сравнение)
.venv/bin/python modules/tts/test_tts.py --provider piper --model models/piper/ru_RU-dmitri-medium.onnx --play
```
## Критерии приёмки Модуля 3
1. ✅ Русский голос звучит естественно, скорость −15% — принято юзером на слух (Svetlana).
2. ✅ Паузы между предложениями слышны (многоточия / точная тишина).
3. ✅ Синтез короткой фразы ≤ 3 c: 1.7 c (edge), 0.47 c (piper).
## Известные ограничения
- edge-tts — неофициальный API Microsoft: исторически ломался (403). План Б — Piper, он уже в проекте.
- Piper: голос скачивается один раз в `models/piper/` (команда в docstring провайдера);
качество проще edge, зато 0.5 c и полностью офлайн.
- В `provider_edge._run_async` учтён будущий asyncio-контекст (aiogram в Модуле 6):
синтез не сломает чужой event loop.