# Архитектура системы

## Компоненты

### 1. WebSocket API (`src/voice_tts/api/`)

- `server.py` — FastAPI-приложение, endpoint `/ws`, управление сессией.
- `protocol.py` — Pydantic-модели всех входящих и исходящих сообщений.

Отвечает за:
- Приём подключений от Python-агента.
- Парсинг сообщений.
- Жизненный цикл сессии и её graceful shutdown.

### 2. Сессия (`src/voice_tts/session/`)

- `state.py` — `SessionState` и `VoiceProfile`.

Хранит:
- Текстовый буфер.
- Текущий язык, скорость, эмоцию.
- Референсные аудио для спикера и эмоций.
- Очередь аудио-выхода.
- Флаг остановки (`stop_event`).

### 3. Сегментатор (`src/voice_tts/tts/segmenter.py`)

`Segmenter` превращает накопленный текст в сегменты для синтеза.

Правила:
- Разбиение по концам предложений (`.`, `。`, `!`, `?`, `;`, `:` и newline).
- Если сегмент превышает `max_length`, разрез по запятой/тире/скобкам.
- Минимальная длина сегмента (`min_length`) не применяется при принудительном `flush`.

### 4. TTS Engine (`src/voice_tts/tts/`)

- `engine.py` — абстрактный базовый класс `TTSEngine` и `DummyTTSEngine` для тестов.
- `f5_backend.py` — реализация на F5-TTS, включая кэширование транскрибированных референсов.

Интерфейс:

```python
async def synthesize(
    self,
    text: str,
    ref_audio_path: Path | None,
    language: str,
    speed: float,
    emotion: str,
) -> np.ndarray:
    ...
```

### 5. Аудио (`src/voice_tts/audio/`)

- `formats.py` — преобразование float32 -> PCM16 -> base64, генерация WAV-заголовка.

### 6. Конфигурация (`src/voice_tts/config.py`)

`pydantic-settings`, загружает переменные из `.env`.

## Потоки выполнения

```
WebSocket receiver (async)
    |
    v
SessionManager
    |
    +---> Text buffer / Segmenter
    |          |
    |          v
    |     _synthesize_segment (async task per segment)
    |          |
    |          v
    |     TTS Engine (GPU-bound, выполняется в отдельной задаче)
    |          |
    |          v
    |     audio_queue.put((segment_seq, pcm))
    |
    +---> _audio_sender (async worker)
              |
              +---> WebSocket send(audio base64)
              |
              +---> WebSocket send(status: segment_finished)
```

Важно: все обращения к CUDA-инференсу сериализованы через один TTS worker, чтобы избежать contention и OOM.

## Управление прерыванием

Каждая сессия содержит `asyncio.Event stop_event`.

При получении сообщения `stop`:
1. Устанавливается `stop_event`.
2. Очищается текстовый буфер.
3. Опустошается аудио-очередь.
4. Любая текущая/последующая генерация отменяется.
5. Клиенту отправляется `status: stopped`.

Новый текст после `stop` автоматически сбрасывает `stop_event` и начинает новую фразу.
