Полностью контейнеризированное решение для голосового бота заказа такси.
Решение состоит из следующих компонентов:
-
pjsip-proxy (C++) - принимает SIP-звонки и управляет RTP-потоками
-
sip-bot (Java Spring Boot) - логика диалога, распознавание речи (Vosk), интеграция с RunaWFE
-
rhvoice - синтез речи (Text-to-Speech) Выше перечисленное должно стоять вместе так как обмен через socket
-
RunaWFE - система управления бизнес-процессами (может работать отдельно)
- Телефонный провайдер (SIP-транк, например, Ростелеком) ↔ pjsip-proxy:
- SIP (UDP, порт 5060) — для сигнализации (установка и завершение звонка).
- RTP (UDP, порты 4000-4100) — для передачи голосового потока (аудио).
- pjsip-proxy ↔ sip-bot:
- Unix Domain Sockets (
/tmp/sip_prox/) — сверхбыстрая локальная передача событий звонка (INCOMING,DISCONNECTED) и потокового аудио (PCM) без сетевых накладных расходов Docker.
- Unix Domain Sockets (
- sip-bot ↔ rhvoice:
- HTTP (внутри Docker-сети, порт 8080) — бот отправляет текст, сервис возвращает аудиофайл (WAV/PCM) для воспроизведения.
- sip-bot ↔ RunaWFE:
- HTTPS/HTTP REST API — отправка структурированных данных (телефон, адрес) для запуска бизнес-процесса по завершении диалога.
- Входящий вызов: Клиент звонит на SIP-номер. Провайдер отправляет
INVITEнаpjsip-proxy. - Инициализация:
pjsip-proxyпринимает звонок, согласовывает медиа-параметры (RTP) и мгновенно создает медиа-сокет в общей папке/tmp/sip_prox/. - Приветствие:
sip-botчерез управляющий сокет (_control) получает событиеINCOMING, формирует приветственную фразу и запрашивает её озвучку уrhvoiceпо HTTP. - Диалог:
- Клиент говорит →
pjsip-proxyпересылает аудио-пакеты в сокет →sip-botраспознает речь через движок Vosk. sip-botанализирует смысл, формирует ответ и снова запрашивает синтез речи уrhvoice.
- Клиент говорит →
- Завершение и интеграция: По итогам диалога
sip-botотправляет HTTP-запрос в RunaWFE (запуск БП "Такси" с переменными "Телефон" и "Адрес"), прощается с клиентом и отправляет командуHANGUPвpjsip-proxy.
- Тип телефонии: SIP-транк (IP-телефония). Решение совместимо с любыми провайдерами, поддерживающими стандартный стек SIP/RTP (в данной конфигурации успешно протестировано с шлюзами типа Ростелеком).
- Сетевые настройки сервера:
- На сервере (и в облачном фаерволе / Security Groups) должны быть открыты входящие UDP-порты:
5060— для SIP-сигнализации.4000-4100— для RTP-медиапотока (голос).
- На сервере должны быть настроены правила
iptables(SNAT), чтобы исходящие пакеты от прокси уходили с корректного публичного IP-адреса (указывается в.envкакPUBLIC_IP).
- На сервере (и в облачном фаерволе / Security Groups) должны быть открыты входящие UDP-порты:
- Windows 10/11 с WSL2 или Linux
- Docker Desktop (для Windows) или Docker Engine (для Linux)
- Docker Compose v2+
- Модель Vosk
vosk-model-ru-0.42(~3 ГБ) - Работающий сервер RunaWFE на хосте
Скачайте модель Vosk
# Создайте директорию для модели
mkdir -p vosk-model-ru-0.42
# Скачайте модель с https://alphacephei.com/vosk/models
# Прямая ссылка: https://alphacephei.com/vosk/models/vosk-model-ru-0.42.zip
wget https://alphacephei.com/vosk/models/vosk-model-ru-0.42.zip
# Распакуйте в директорию vosk-model-ru-0.42
unzip vosk-model-ru-0.42.zip -d vosk-model-ru-0.42/taxi-bot-docker/
│
├── .env # 🔑 Секреты и настройки (SIP, RunaWFE, пароли)
├── .gitignore # Что НЕ нужно коммитить в Git
├── docker-compose.yml # Главный файл оркестрации всех контейнеров
├── README.md # 📖 Краткая инструкция по запуску
│
├── pjsip_proxy/ # 📂 Исходники C++ SIP-прокси
│ ├── Dockerfile # 🛠 Как собирать и запускать прокси в Docker
│ ├── CMakeLists.txt # (из оригинального репозитория)
│ └── ... # (исходный код C++)
│
├── runawfe-sip-bot/ # 📂 Исходники Java-бота
│ ├── Dockerfile # 🛠 Как собирать и запускать бота в Docker
│ ├── pom.xml # (из оригинального репозитория)
│ ├── app/ # (исходный код Java, application.yaml)
│ ├── stt/ # (модули распознавания речи)
│ └── ... # (исходный код Java)
│
└── vosk-model-ru-0.42/ # 📂 Модель распознавания речи (Vosk)
├── am/
├── conf/
├── graph/
├── ivector/
└── ...
Сервер RunaWfe должен быть запущен отдельно на 8080 порту.
- Убедитесь, что в файле
.envкорректно указаны:- Данные SIP-провайдера (
SIP_DOMAIN,SIP_USER,SIP_PASS,PUBLIC_IP). - Адрес и учетные данные RunaWFE (
WFE_API_URL,WFE_LOGIN,WFE_PASS). - Важно: URL должен содержать путь к API, например:
https://ваш-домен.ru/restapi.
- Данные SIP-провайдера (
- Убедитесь, что в RunaWFE создана группа исполнителей "Водители" и развернут бизнес-процесс "Такси".
Далее в корне проекта выполните
docker-compose up -d --build Windows: Убедитесь, что Брандмауэр Windows не блокирует порты Docker или WSL2.
Linux: Проверьте, что порты открыты: sudo ufw allow 5060/udp и sudo ufw allow 4000:4100/udp (или настройте Security Group в облаке).
Если запускаете локально на линуксе то надо знать что http://host.docker.internal:8080 по умолчанию не работает. В docker-compose есть настройка:
extra_hosts:
- "host.docker.internal:host-gateway"но она может не сработать тогда нужно будет прописывать реальный ip адрес руны
Если не работает после перезапуска, то:
docker-compose downdocker volume rm taxi-bot-docker-dist_sip-socketsили
sudo rm -f /var/lib/docker/volumes/taxi-bot-docker-dist_sip-sockets/_data/* или просто всю папку _data
docker-compose up -d