Files
go-speech/README.md
2025-11-28 17:43:00 +06:00

652 lines
23 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.

# 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
```
**Примечание:** Если вы используете HTTPS (`GO_SPEECH_TLS=true`), сертификаты будут автоматически сгенерированы при первом запуске, если они отсутствуют.
7 Запустите сервис:
**Запуск в режиме HTTP (по умолчанию):**
```bash
# Использует порт 8080 по умолчанию
go run main.go
```
**Запуск в режиме HTTP с указанием порта:**
```bash
GO_SPEECH_PORT=3000 go run main.go
```
**Запуск в режиме HTTPS с автогенерацией сертификатов:**
```bash
GO_SPEECH_TLS=true \
GO_SPEECH_PORT=8443 \
GO_SPEECH_VOICE=ruslan \
go run main.go
```
**Запуск в режиме HTTPS с указанием доменов для сертификата:**
```bash
GO_SPEECH_TLS=true \
GO_SPEECH_PORT=8443 \
GO_SPEECH_TLS_DOMAINS="example.com,api.example.com" \
GO_SPEECH_VOICE=ruslan \
go run main.go
```
**Запуск в режиме HTTPS с использованием CA сертификата:**
```bash
GO_SPEECH_TLS=true \
GO_SPEECH_PORT=8443 \
GO_SPEECH_CA_CERT=./ca/ca.crt \
GO_SPEECH_TLS_DOMAINS="example.com" \
GO_SPEECH_VOICE=ruslan \
go run main.go
```
**Запуск с разными голосами:**
```bash
# Голос Irina (женский)
GO_SPEECH_VOICE=irina go run main.go
# Голос Denis (мужской)
GO_SPEECH_VOICE=denis go run main.go
# Голос Dmitri (мужской)
GO_SPEECH_VOICE=dmitri go run main.go
```
**Запуск с указанием конкретной модели через MODEL_PATH:**
```bash
GO_SPEECH_VOICE=ruslan \
MODEL_PATH=/path/to/custom/ru_RU-ruslan-medium.onnx \
go run main.go
```
**Запуск в режиме продакшена (минимальное логирование):**
```bash
GO_SPEECH_MODE=release go run main.go
```
**Запуск с кастомными путями к утилитам:**
```bash
GO_SPEECH_PIPER_PATH=/opt/piper/bin/piper \
GO_SPEECH_FFMPEG_PATH=/opt/ffmpeg/bin/ffmpeg \
GO_SPEECH_MODEL_DIR=/data/models \
go run main.go
```
**Полный пример с переменными окружения:**
```bash
GO_SPEECH_PORT=8443 \
GO_SPEECH_TLS=true \
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_SPEECH_MODE=debug \
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
```
**Примечание:** При использовании `GO_SPEECH_TLS=true` сертификаты будут автоматически сгенерированы при первом запуске контейнера.
4 Запустите контейнер:
**Запуск в режиме HTTP:**
```bash
podman run -d \
--name go-speech \
-p 8080:8080 \
-e GO_SPEECH_PORT=8080 \
-e GO_SPEECH_VOICE=ruslan \
-v $(pwd)/models:/app/models:ro \
go-speech:latest
```
**Запуск в режиме HTTPS с автогенерацией сертификатов:**
```bash
podman run -d \
--name go-speech \
-p 8443:8443 \
-e GO_SPEECH_TLS=true \
-e GO_SPEECH_PORT=8443 \
-e GO_SPEECH_VOICE=ruslan \
-e GO_SPEECH_TLS_DOMAINS="example.com,api.example.com" \
-v $(pwd)/models:/app/models:ro \
-v $(pwd)/certs:/app/certs \
go-speech:latest
```
**Запуск с предварительно созданными сертификатами:**
```bash
podman run -d \
--name go-speech \
-p 8443:8443 \
-e GO_SPEECH_TLS=true \
-e GO_SPEECH_PORT=8443 \
-e GO_SPEECH_VOICE=ruslan \
-v $(pwd)/models:/app/models:ro \
-v $(pwd)/certs:/app/certs:ro \
go-speech:latest
```
**Запуск с разными голосами:**
```bash
# Голос Irina
podman run -d \
--name go-speech-irina \
-p 8443:8443 \
-e GO_SPEECH_TLS=true \
-e GO_SPEECH_VOICE=irina \
-v $(pwd)/models:/app/models:ro \
-v $(pwd)/certs:/app/certs:ro \
go-speech:latest
# Голос Denis
podman run -d \
--name go-speech-denis \
-p 8444:8443 \
-e GO_SPEECH_TLS=true \
-e GO_SPEECH_VOICE=denis \
-v $(pwd)/models:/app/models:ro \
-v $(pwd)/certs:/app/certs:ro \
go-speech:latest
# Голос Dmitri
podman run -d \
--name go-speech-dmitri \
-p 8445:8443 \
-e GO_SPEECH_TLS=true \
-e GO_SPEECH_VOICE=dmitri \
-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_TLS=true \
-e GO_SPEECH_MODE=release \
-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 9000:9000 \
-e GO_SPEECH_PORT=9000 \
-e GO_SPEECH_TLS=true \
-e GO_SPEECH_PIPER_PATH=/usr/local/bin/piper \
-e GO_SPEECH_FFMPEG_PATH=/usr/bin/ffmpeg \
-e GO_SPEECH_MODEL_DIR=/app/models \
-e GO_SPEECH_VOICE=ruslan \
-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
Встроенный веб-интерфейс для синтеза речи через браузер.
**Доступ:**
Откройте в браузере:
**Для HTTPS режима:**
``` text
https://localhost:8443/go-speech/front
```
**Для HTTP режима:**
``` text
http://localhost:8080/go-speech/front
```
### GET /go-speech/help
Отображение документации (README.md) в браузере.
**Доступ:**
**Для HTTPS режима:**
``` text
https://localhost:8443/go-speech/help
```
**Для HTTP режима:**
``` text
http://localhost:8080/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` - Сервис работает
## Переменные окружения
### Основные настройки
- `GO_SPEECH_PORT` - Порт для запуска сервера
- По умолчанию: `8443` (если `GO_SPEECH_TLS=true`) или `8080` (если TLS отключен)
- Можно указать любой доступный порт
- `GO_SPEECH_VOICE` - Имя голоса для синтеза речи (по умолчанию: `ruslan`)
- Доступные варианты: `ruslan`, `denis`, `dmitri`, `irina`
- Путь к модели формируется как: `{MODEL_DIR}/ru_RU-{GO_SPEECH_VOICE}-medium.onnx`
- `MODEL_PATH` - Полный путь к модели Piper TTS (опционально)
- Переопределяет автоматический выбор на основе `GO_SPEECH_VOICE`
- Используется, если нужно указать конкретную модель напрямую
- `GO_SPEECH_MODE` - Режим работы сервера (по умолчанию: `debug`)
- `release` - Режим продакшена (минимальное логирование)
- Любое другое значение - Режим разработки (подробное логирование всех операций)
### Настройки TLS/HTTPS
- `GO_SPEECH_TLS` - Включение HTTPS режима (по умолчанию: не задано, используется HTTP)
- Если установлено в `true` - сервер запускается по HTTPS
- Если не задано или `false` - сервер запускается по HTTP
- При включенном HTTPS и отсутствии сертификатов - они будут автоматически сгенерированы
- `GO_SPEECH_CERT_FILE` - Путь к файлу TLS сертификата (по умолчанию: `certs/server.crt`)
- Используется только при `GO_SPEECH_TLS=true`
- Если файл отсутствует и TLS включен - будет автоматически сгенерирован
- `GO_SPEECH_KEY_FILE` - Путь к файлу приватного ключа (по умолчанию: `certs/server.key`)
- Используется только при `GO_SPEECH_TLS=true`
- Если файл отсутствует и TLS включен - будет автоматически сгенерирован
- `GO_SPEECH_TLS_DOMAINS` - Список доменов для добавления в сертификат (опционально)
- Формат: домены через запятую, например: `example.com,api.example.com`
- В сертификат всегда автоматически добавляются: `localhost`, `127.0.0.1`
- Используется только при автогенерации сертификатов
- `GO_SPEECH_CA_CERT` - Путь к CA сертификату для подписи сертификата (опционально)
- Если задан и файл существует - сертификат будет подписан этим CA
- CA ключ должен находиться в том же каталоге с расширением `.key`
- Если CA не найден - генерируется самоподписанный сертификат
- Используется только при автогенерации сертификатов
### Пути к утилитам
- `GO_SPEECH_PIPER_PATH` - Путь к исполняемому файлу Piper TTS (по умолчанию: `/usr/local/bin/piper`)
- `GO_SPEECH_FFMPEG_PATH` - Путь к исполняемому файлу ffmpeg (по умолчанию: `/usr/bin/ffmpeg`)
- `GO_SPEECH_MODEL_DIR` - Директория с моделями Piper TTS (по умолчанию: `models`)
## Кэширование
Сервер автоматически кэширует сгенерированные аудио файлы для ускорения обработки повторных запросов.
### Как работает кэш
- **Директория кэша**: Создается автоматически в директории рядом с исполняемым файлом (`./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