# 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 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