444 lines
16 KiB
Markdown
444 lines
16 KiB
Markdown
# Go Speech - TTS микросервис
|
||
|
||
Микросервис на Go для преобразования русского текста в речь через Piper TTS с HTTPS API.
|
||
|
||
## Возможности
|
||
|
||
- HTTP/HTTPS API для синтеза речи
|
||
- Веб-интерфейс для удобного использования через браузер
|
||
- Поддержка русского языка через Piper TTS
|
||
- Выбор из 4 голосов: Ruslan, Irina, Denis, Dmitri
|
||
- Локальная генерация речи (без внешних API)
|
||
- Возврат аудио в формате OGG
|
||
- Встроенный фронтенд в бинарнике (не требует отдельных файлов)
|
||
- Кэширование сгенерированных аудио файлов для ускорения повторных запросов
|
||
- Автоматическая очистка кэша (удаление файлов старше 3 дней)
|
||
- Контейнеризация через Podman/Docker
|
||
|
||
## Требования
|
||
|
||
- Go 1.21+
|
||
- Piper TTS (устанавливается автоматически в Docker образе)
|
||
- ffmpeg (для конвертации в OGG)
|
||
- SSL сертификаты (самоподписанные для разработки)
|
||
|
||
## Установка и запуск
|
||
|
||
### Локальная разработка
|
||
|
||
1 Клонируйте репозиторий:
|
||
|
||
```bash
|
||
git clone <repository-url>
|
||
cd go-speech
|
||
```
|
||
|
||
2 Установите зависимости:
|
||
|
||
```bash
|
||
go mod download
|
||
```
|
||
|
||
3 Скачайте русскую модель Piper TTS:
|
||
|
||
```bash
|
||
mkdir -p models
|
||
curl -L https://huggingface.co/rhasspy/piper-voices/resolve/main/ru/ru_RU/denis/medium/ru_RU-denis-medium.onnx -o models/ru_RU-denis-medium.onnx
|
||
curl -L https://huggingface.co/rhasspy/piper-voices/resolve/main/ru/ru_RU/denis/medium/ru_RU-denis-medium.onnx.json -o models/ru_RU-denis-medium.onnx.json
|
||
```
|
||
|
||
4 Установите Piper TTS локально (если запускаете вне Docker):
|
||
|
||
```bash
|
||
# Скачайте бинарник с https://github.com/rhasspy/piper/releases
|
||
# И поместите в PATH или укажите путь через переменную окружения PIPER_PATH
|
||
```
|
||
|
||
5 Установите ffmpeg:
|
||
|
||
```bash
|
||
# Ubuntu/Debian
|
||
sudo apt-get install ffmpeg
|
||
|
||
# Alpine
|
||
apk add ffmpeg
|
||
```
|
||
|
||
6 Сгенерируйте SSL сертификаты:
|
||
|
||
```bash
|
||
./generate-certs.sh
|
||
```
|
||
|
||
7 Запустите сервис:
|
||
|
||
```bash
|
||
go run main.go
|
||
```
|
||
|
||
Или с переменными окружения:
|
||
|
||
```bash
|
||
GO_SPEECH_PORT=8443 \
|
||
GO_SPEECH_PIPER_PATH=/usr/local/bin/piper \
|
||
GO_SPEECH_MODEL_DIR=./models \
|
||
GO_SPEECH_VOICE=ruslan \
|
||
GO_SPEECH_FFMPEG_PATH=/usr/bin/ffmpeg \
|
||
GO_SPEECH_CERT_FILE=./certs/server.crt \
|
||
GO_SPEECH_KEY_FILE=./certs/server.key \
|
||
go run main.go
|
||
```
|
||
|
||
Для использования другого голоса (например, `denis`, `dmitri`, `irina`):
|
||
|
||
```bash
|
||
GO_SPEECH_VOICE=denis go run main.go
|
||
```
|
||
|
||
### Запуск через Podman/Docker
|
||
|
||
1 Соберите образ:
|
||
|
||
```bash
|
||
podman build -t go-speech:latest .
|
||
```
|
||
|
||
2 Скачайте модель (если не включена в образ):
|
||
|
||
```bash
|
||
mkdir -p models
|
||
curl -L https://huggingface.co/rhasspy/piper-voices/resolve/main/ru/ru_RU/denis/medium/ru_RU-denis-medium.onnx -o models/ru_RU-denis-medium.onnx
|
||
curl -L https://huggingface.co/rhasspy/piper-voices/resolve/main/ru/ru_RU/denis/medium/ru_RU-denis-medium.onnx.json -o models/ru_RU-denis-medium.onnx.json
|
||
```
|
||
|
||
3 Сгенерируйте сертификаты:
|
||
|
||
```bash
|
||
./generate-certs.sh
|
||
```
|
||
|
||
4 Запустите контейнер:
|
||
|
||
```bash
|
||
podman run -d \
|
||
--name go-speech \
|
||
-p 8443:8443 \
|
||
-e GO_SPEECH_VOICE=ruslan \
|
||
-v $(pwd)/models:/app/models:ro \
|
||
-v $(pwd)/certs:/app/certs:ro \
|
||
go-speech:latest
|
||
```
|
||
|
||
Для использования другого голоса:
|
||
|
||
```bash
|
||
podman run -d \
|
||
--name go-speech \
|
||
-p 8443:8443 \
|
||
-e GO_SPEECH_VOICE=denis \
|
||
-v $(pwd)/models:/app/models:ro \
|
||
-v $(pwd)/certs:/app/certs:ro \
|
||
go-speech:latest
|
||
```
|
||
|
||
### Запуск как systemd сервис
|
||
|
||
1. Отредактируйте `go-speech.service` и укажите правильные пути к моделям и сертификатам
|
||
|
||
2. Скопируйте unit файл:
|
||
|
||
```bash
|
||
sudo cp go-speech.service /etc/systemd/system/
|
||
```
|
||
|
||
3 Перезагрузите systemd:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
```
|
||
|
||
4 Запустите сервис:
|
||
|
||
```bash
|
||
sudo systemctl start go-speech
|
||
sudo systemctl enable go-speech
|
||
```
|
||
|
||
5 Проверьте статус:
|
||
|
||
```bash
|
||
sudo systemctl status go-speech
|
||
```
|
||
|
||
## Веб-интерфейс
|
||
|
||
### GET /go-speech/front
|
||
|
||
Встроенный веб-интерфейс для синтеза речи через браузер.
|
||
|
||
**Доступ:**
|
||
|
||
Откройте в браузере:
|
||
|
||
``` text
|
||
https://localhost:8443/go-speech/front
|
||
```
|
||
|
||
### GET /go-speech/help
|
||
|
||
Отображение документации (README.md) в браузере.
|
||
|
||
**Доступ:**
|
||
|
||
``` text
|
||
https://localhost:8443/go-speech/help
|
||
```
|
||
|
||
**Возможности:**
|
||
|
||
- Выбор голоса из доступных моделей (Ruslan, Irina, Denis, Dmitri)
|
||
- Многострочное поле для ввода текста
|
||
- Кнопка "Озвучить" - генерирует и проигрывает аудио в браузере
|
||
- Кнопка "Скачать" - скачивает файл озвучки
|
||
- Минималистичный дизайн
|
||
|
||
Фронтенд полностью встроен в бинарник и не требует дополнительных файлов.
|
||
|
||
## API
|
||
|
||
Все API endpoints доступны по префиксу `/go-speech/api/v1/`
|
||
|
||
### POST /go-speech/api/v1/tts
|
||
|
||
Преобразует текст в речь и возвращает OGG аудио файл.
|
||
|
||
**Запрос (без указания голоса, используется голос по умолчанию):**
|
||
|
||
```bash
|
||
curl -X POST https://localhost:8443/go-speech/api/v1/tts \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "Привет, это тестовый текст"}' \
|
||
--insecure \
|
||
-o output.ogg
|
||
```
|
||
|
||
**Запрос (с указанием голоса):**
|
||
|
||
```bash
|
||
curl -X POST https://localhost:8443/go-speech/api/v1/tts \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "Привет, это тестовый текст", "voice": "irina"}' \
|
||
--insecure \
|
||
-o output-irina.ogg
|
||
```
|
||
|
||
**Параметры запроса:**
|
||
|
||
- `text` (обязательный) - Текст для озвучки (максимум 5000 символов)
|
||
- `voice` (опциональный) - Голос для синтеза: `ruslan` (по умолчанию), `irina`, `denis`, `dmitri`
|
||
|
||
**Ответ:**
|
||
|
||
- Content-Type: `audio/ogg`
|
||
- Body: OGG аудио файл
|
||
- Content-Disposition: `inline; filename=speech-{voice}.ogg`
|
||
|
||
**Коды ответа:**
|
||
|
||
- `200` - Успех
|
||
- `400` - Неверный запрос (пустой текст, слишком длинный текст, неверный голос)
|
||
- `405` - Неверный HTTP метод
|
||
- `500` - Ошибка сервера
|
||
|
||
### GET /go-speech/api/v1/healthz
|
||
|
||
Генерирует аудио файл со словом "Окей" и возвращает его. Используется для проверки работоспособности TTS.
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl -k https://localhost:8443/go-speech/api/v1/healthz -o healthz.ogg
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
- Content-Type: `audio/ogg`
|
||
- Body: OGG аудио файл со словом "Окей"
|
||
|
||
### GET /go-speech/api/v1/health
|
||
|
||
Проверка работоспособности сервиса.
|
||
|
||
**Запрос:**
|
||
|
||
```bash
|
||
curl https://localhost:8443/go-speech/api/v1/health --insecure
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
- `200 OK` - Сервис работает
|
||
|
||
## Переменные окружения
|
||
|
||
- `PORT` - Порт для HTTPS сервера (по умолчанию: 8443)
|
||
- `CERT_FILE` - Путь к SSL сертификату (по умолчанию: certs/server.crt)
|
||
- `KEY_FILE` - Путь к SSL приватному ключу (по умолчанию: certs/server.key)
|
||
- `PIPER_PATH` - Путь к бинарнику Piper TTS (по умолчанию: /usr/local/bin/piper)
|
||
- `MODEL_DIR` - Директория с моделями (по умолчанию: models)
|
||
- `GO_SPEECH_VOICE` - Имя голоса для синтеза речи (по умолчанию: ruslan)
|
||
- Доступные варианты: `ruslan`, `denis`, `dmitri`, `irina`
|
||
- Путь к модели формируется как: `{MODEL_DIR}/ru_RU-{GO_SPEECH_VOICE}-medium.onnx`
|
||
- `MODEL_PATH` - Полный путь к модели Piper TTS (опционально, переопределяет автоматический выбор на основе GO_SPEECH_VOICE)
|
||
- `FFMPEG_PATH` - Путь к бинарнику ffmpeg (по умолчанию: /usr/bin/ffmpeg)
|
||
- `GO_SPEECH_MODE` - Режим работы сервера (по умолчанию: debug)
|
||
- `release` - Режим продакшена (минимальное логирование)
|
||
- Любое другое значение - Режим разработки (подробное логирование всех операций)
|
||
|
||
## Кэширование
|
||
|
||
Сервер автоматически кэширует сгенерированные аудио файлы для ускорения обработки повторных запросов.
|
||
|
||
### Как работает кэш
|
||
|
||
- **Директория кэша**: Создается автоматически в директории рядом с исполняемым файлом (`./cache/`)
|
||
- **Ключ кэша**: SHA256 хеш от комбинации имени модели и текста (`SHA256(model_name:text)`)
|
||
- **Проверка кэша**: При каждом запросе сначала проверяется наличие файла в кэше
|
||
- **Сохранение**: После генерации аудио файл автоматически сохраняется в кэш
|
||
- **Автоочистка**: Фоновая горутина каждые 5 минут удаляет файлы старше 3 дней
|
||
|
||
### Преимущества кэширования
|
||
|
||
- Ускорение повторных запросов с тем же текстом и голосом
|
||
- Снижение нагрузки на систему (не требуется повторная генерация)
|
||
- Автоматическое управление размером кэша
|
||
|
||
### Пример работы
|
||
|
||
```bash
|
||
# Первый запрос - генерация и сохранение в кэш
|
||
curl -X POST https://localhost:8443/tts \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "Привет", "voice": "irina"}' \
|
||
--insecure -o output1.ogg
|
||
|
||
# Второй запрос с тем же текстом - используется кэш (быстрее)
|
||
curl -X POST https://localhost:8443/tts \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "Привет", "voice": "irina"}' \
|
||
--insecure -o output2.ogg
|
||
```
|
||
|
||
**Примечание**: Кэш работает автоматически и не требует дополнительной настройки.
|
||
|
||
## Логирование
|
||
|
||
Сервер поддерживает два режима логирования, управляемые переменной окружения `GO_SPEECH_MODE`:
|
||
|
||
### Режим разработки (по умолчанию)
|
||
|
||
Когда `GO_SPEECH_MODE` не установлена или имеет любое значение кроме `release`, включается подробное логирование:
|
||
|
||
- Детальная информация о конфигурации при запуске
|
||
- Логирование всех входящих HTTP запросов с параметрами
|
||
- Подробная информация о процессе генерации аудио
|
||
- Логирование выполнения команд Piper TTS и ffmpeg
|
||
- Информация о размерах файлов и времени выполнения операций
|
||
- Детальные сообщения об ошибках с контекстом
|
||
|
||
**Пример вывода в режиме разработки:**
|
||
|
||
``` text
|
||
[INFO] === Запуск Go Speech TTS сервера ===
|
||
[DEBUG] Режим отладки: ВКЛЮЧЕН
|
||
[DEBUG] Конфигурация:
|
||
[DEBUG] PORT: 8443
|
||
[DEBUG] PIPER_PATH: /usr/local/bin/piper
|
||
[DEBUG] === Обработка TTS запроса ===
|
||
[DEBUG] Тело запроса: {"text":"Привет","voice":"irina"}
|
||
[DEBUG] === Генерация аудио ===
|
||
[DEBUG] Запуск Piper TTS для генерации WAV...
|
||
```
|
||
|
||
### Режим продакшена
|
||
|
||
Установите `GO_SPEECH_MODE=release` для минимального логирования:
|
||
|
||
- Только критичные ошибки и важные события
|
||
- Базовая информация о запросах (метод, путь, время выполнения)
|
||
- Без детальной отладочной информации
|
||
|
||
**Пример запуска в режиме продакшена:**
|
||
|
||
```bash
|
||
GO_SPEECH_MODE=release ./go-speech
|
||
```
|
||
|
||
## Структура проекта
|
||
|
||
``` text
|
||
go-speech/
|
||
├── main.go # Основной HTTP сервер
|
||
├── handlers/ # HTTP обработчики
|
||
│ └── tts.go # Обработчик TTS запросов
|
||
├── tts/ # TTS модуль
|
||
│ └── piper.go # Интеграция с Piper TTS
|
||
├── internal/ # Внутренние пакеты
|
||
│ ├── logger/ # Модуль логирования
|
||
│ │ └── logger.go # Логирование с поддержкой режимов
|
||
│ └── cache/ # Модуль кэширования
|
||
│ └── cache.go # Кэширование аудио файлов
|
||
├── cache/ # Директория кэша (создается автоматически)
|
||
├── static/ # Статические файлы фронтенда
|
||
│ └── index.html # Веб-интерфейс (встраивается в бинарник)
|
||
├── models/ # Модели Piper TTS
|
||
├── certs/ # SSL сертификаты
|
||
├── Dockerfile # Контейнер для Podman/Docker
|
||
├── go-speech.service # Systemd unit файл
|
||
├── generate-certs.sh # Скрипт генерации сертификатов
|
||
└── README.md # Документация
|
||
```
|
||
|
||
## Разработка
|
||
|
||
### Сборка
|
||
|
||
```bash
|
||
go build -o go-speech .
|
||
```
|
||
|
||
### Тестирование
|
||
|
||
```bash
|
||
# Запустите сервис
|
||
go run main.go
|
||
|
||
# Откройте веб-интерфейс в браузере
|
||
# https://localhost:8443/go-speech/front
|
||
|
||
# Или документацию
|
||
# https://localhost:8443/go-speech/help
|
||
|
||
# Или используйте API напрямую
|
||
curl -X POST https://localhost:8443/go-speech/api/v1/tts \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "Тестовый текст"}' \
|
||
--insecure \
|
||
-o test.ogg
|
||
|
||
# С указанием голоса
|
||
curl -X POST https://localhost:8443/go-speech/api/v1/tts \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "Привет, это тестовый текст", "voice": "irina"}' \
|
||
--insecure \
|
||
-o output-irina.ogg
|
||
|
||
# Проверка работоспособности
|
||
curl -k https://localhost:8443/go-speech/api/v1/healthz -o healthz.ogg
|
||
curl https://localhost:8443/go-speech/api/v1/health --insecure
|
||
```
|
||
|
||
## Лицензия
|
||
|
||
MIT
|