06

Компоненты стека

Детальное описание каждого компонента: что делает, какие функции покрывает, ключевые модули и примеры конфигурации.

K

Kamailio — SIP-прокси

C SIP Proxy Signaling Only

Kamailio — высокопроизводительный SIP-прокси-сервер, написанный на C. Способен обрабатывать тысячи вызовов в секунду на одном ядре. Работает исключительно с сигнализацией (SIP) — голосовые потоки (RTP) через него не проходят.

Модуль Назначение
usrloc Хранение регистраций (кто где онлайн)
auth_db Аутентификация SIP из PostgreSQL
dispatcher Балансировка между FreeSWITCH нодами
pike Защита от brute-force (rate limiting)
permissions ACL — белые/чёрные списки IP
tls Шифрование SIP-сигнализации
nathelper Исправление NAT в SIP-заголовках
websocket SIP поверх WebSocket для WebRTC
rtpengine Управление RTPEngine для медиа-проксирования
dmq Синхронизация данных между нодами кластера
dialog Отслеживание активных диалогов
htable In-memory хеш-таблицы для кеширования
kamailio.cfg — маршрутизация входящего запроса
request_route { # Проверяем максимальное количество пересылок if (!maxfwd_process(10)) { sl_send_reply("483", "Too Many Hops"); exit; } # Защита от flood-атак if (!pike_check_req()) { xlog("L_WARN", "PIKE: блокировка $si\n"); exit; } # Аутентификация REGISTER-запросов if (is_method("REGISTER")) { if (!auth_check("$fd", "subscriber", 1)) { auth_challenge("$fd", 0); exit; } save("location"); exit; } # INVITE — отправляем на FreeSWITCH через dispatcher if (is_method("INVITE")) { ds_select_dst(1, 4); # группа 1, round-robin t_relay(); exit; } }
Ключевой инсайт:

Kamailio не работает с голосом. Его задача — быстро решить КУДА отправить вызов и сделать это надёжно. Думайте о нём как о «маршрутизаторе для SIP-пакетов».

F

FreeSWITCH — Медиа-сервер

C Media Server PBX

FreeSWITCH — медиа-сервер и «мозг» обработки вызовов. Написан на C, обрабатывает голос, IVR-меню, очереди, конференции и запись разговоров. Именно здесь вызов «оживает» — FreeSWITCH отвечает, проигрывает приветствие, соединяет абонентов и записывает разговор.

Модуль Назначение
mod_sofia SIP-стек (регистрация, вызовы)
mod_callcenter Очереди вызовов (ACD)
mod_conference Конференц-связь
mod_voicemail Голосовая почта
mod_dptools Инструменты диалплана (bridge, transfer, record)
mod_ivr Интерактивное голосовое меню
mod_lua Lua-скрипты для логики вызовов
mod_event_socket ESL — внешнее управление (Go, Python)
mod_verto WebRTC-протокол (альтернатива SIP.js)
mod_local_stream Музыка ожидания (MOH)
mod_spandsp Факс T.38, DTMF detection
mod_unimrcp ASR/TTS через MRCP-протокол
Lua — IVR-скрипт: приветствие и выбор очереди
-- IVR: отвечаем, проигрываем меню, ждём выбор session:answer() session:sleep(1000) session:streamFile("ivr/welcome.wav") session:streamFile("ivr/press_1_sales_2_support.wav") local digit = session:getDigits(1, "#", 5000) if digit == "1" then -- Перевод в очередь продаж session:transfer("sales@queue") elseif digit == "2" then -- Перевод в очередь поддержки session:transfer("support@queue") else -- Нет ввода — повторяем или переводим на оператора session:transfer("default@queue") end
Ключевой инсайт:

FreeSWITCH управляется извне через ESL (Event Socket). Ваш Go-сервис подключается к ESL и командует: «ответь», «переведи», «запиши». Это позволяет вынести всю бизнес-логику из конфигов FreeSWITCH в нормальный код.

R

RTPEngine — Медиа-прокси

C Media Proxy Sipwise

RTPEngine — медиа-прокси, разработанный компанией Sipwise. Проксирует RTP/SRTP-потоки между клиентами, обеспечивая NAT traversal, конвертацию шифрования и транскодирование кодеков. Не обрабатывает логику вызовов — только пропускает и трансформирует медиа-потоки.

Функция Назначение
NAT traversal Проксирование медиа для клиентов за NAT
SRTP ↔ RTP Конвертация шифрованного в нешифрованный поток
WebRTC bridge DTLS-SRTP (браузер) ↔ plain RTP (IP-телефон)
Codec transcode Перекодирование (Opus ↔ G.711) при необходимости
Media recording Запись RTP-потока в файл
ICE handling Обработка ICE candidates для WebRTC
kamailio.cfg — вызов RTPEngine для медиа-проксирования
# Обработка INVITE — подключаем RTPEngine route[RELAY] { # Для WebRTC-клиентов: конвертируем DTLS-SRTP → plain RTP if ($proto == "ws" || $proto == "wss") { rtpengine_offer("ICE=remove RTP/AVP"); } else { rtpengine_offer("replace-origin replace-session-connection"); } t_on_reply("MANAGE_REPLY"); t_relay(); } onreply_route[MANAGE_REPLY] { if (has_body("application/sdp")) { rtpengine_answer("replace-origin replace-session-connection"); } }
Ключевой инсайт:

Без RTPEngine WebRTC-клиенты не смогут разговаривать с обычными SIP-телефонами — разные протоколы шифрования и кодеки. RTPEngine выступает «переводчиком» между мирами.

Go

Go Backend — API и бизнес-логика

Go REST API ESL Client

Go Backend — ваш кастомный сервис, «клей» между всеми компонентами системы. Предоставляет REST API для фронтенда, управляет вызовами через ESL, обрабатывает CDR-события, управляет кампаниями автообзвона и рассылает вебхуки во внешние системы.

Функция Назначение
REST API CRUD пользователей, очередей, IVR, маршрутов
ESL Client Управление вызовами через FreeSWITCH
WebSocket Hub Реалтайм-события для React-дашборда
CDR Processor Приём событий → запись в PostgreSQL
Dialer Engine Управление кампаниями автообзвона
Webhook Dispatcher Отправка событий во внешние системы (CRM)
Provisioning Server Автонастройка IP-телефонов по MAC
Auth & RBAC JWT-аутентификация, роли и права
Go — подключение к FreeSWITCH ESL и originate
package main import ( "fmt" "github.com/cgrates/fsock" ) func main() { // Подключаемся к FreeSWITCH Event Socket conn, err := fsock.NewFSock( "127.0.0.1:8021", "ClueCon", // пароль ESL 10, // reconnects eventHandlers, eventFilters, logger, ) if err != nil { panic(err) } // Инициируем исходящий вызов cmd := "originate {origination_caller_id_number=1001}" + "sofia/gateway/trunk1/+74951234567 &bridge(user/1001)" reply, err := conn.SendApiCmd(cmd) fmt.Println("Originate:", reply) }

Ключевые Go-библиотеки:

gin fsock pgx go-redis nats.go jwt gorilla/websocket
Ключевой инсайт:

Go идеален для телефонии: горутины для тысяч одновременных ESL-событий, низкая задержка, простой деплой одним бинарником. Вся бизнес-логика живёт здесь, а не в конфигах Kamailio или FreeSWITCH.

P

PostgreSQL — Основная БД

SQL RDBMS Persistent Storage

PostgreSQL — основное постоянное хранилище всех данных системы. Содержит информацию о пользователях, маршрутизации, CDR-записях, конфигурации IVR, очередей и кампаний. Используется как Go-сервисом (бизнес-данные), так и Kamailio (аутентификация SIP).

Группа Таблицы / Назначение
Мультитенантность tenants — компании, домены, лимиты
Пользователи users, extensions, sip_credentials, devices
Маршрутизация dialplans, did_numbers, trunks, outbound_routes
IVR ivr_menus — дерево меню в JSON
Очереди queues, queue_members — настройки и агенты
CDR cdr — журнал всех вызовов
Записи recordings — метаданные файлов записей
Voicemail voicemail_boxes, voicemail_msgs
Конференции conference_rooms
Автообзвон campaigns, campaign_numbers
Аудит audit_log — история изменений
SQL — таблица CDR (журнал вызовов)
CREATE TABLE cdr ( id BIGSERIAL PRIMARY KEY, uuid UUID NOT NULL UNIQUE, tenant_id INT NOT NULL REFERENCES tenants(id), caller_number VARCHAR(32) NOT NULL, callee_number VARCHAR(32) NOT NULL, direction VARCHAR(10) NOT NULL, -- inbound / outbound / internal start_time TIMESTAMPTZ NOT NULL, answer_time TIMESTAMPTZ, end_time TIMESTAMPTZ, duration INT DEFAULT 0, -- секунды bill_sec INT DEFAULT 0, -- оплачиваемые секунды disposition VARCHAR(20), -- ANSWERED, NO_ANSWER, BUSY, FAILED queue_id INT, agent_id INT, recording_url TEXT, hangup_cause VARCHAR(64), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_cdr_tenant_time ON cdr(tenant_id, start_time DESC); CREATE INDEX idx_cdr_caller ON cdr(caller_number); CREATE INDEX idx_cdr_callee ON cdr(callee_number);
Ключевой инсайт:

PostgreSQL используется и Kamailio (для аутентификации), и Go (для бизнес-данных). Это единый источник правды (single source of truth) для всей системы.

R

Redis — Кеш и реалтайм

In-Memory Cache Pub/Sub

Redis — in-memory хранилище для эфемерного состояния реального времени. Здесь живут данные, которые нужны «прямо сейчас»: активные вызовы, статусы операторов, метрики очередей, API-сессии и счётчики rate limiting.

Ключ (key pattern) Хранимые данные
call:{uuid} Активный вызов: caller, callee, state, start_time
agent:{id}:status Статус оператора: ready/busy/break/offline
presence:{ext} Presence: available/dnd/away
queue:{id}:stats Очередь: waiting, talking, avg_wait, sla%
session:{token} API-сессия: user_id, tenant_id, role, expires
rate:{ip} Rate limiting: counter + TTL
location:{aor} Кеш регистраций из Kamailio
Go — работа со статусом оператора через go-redis
import ( "context" "fmt" "time" "github.com/redis/go-redis/v9" ) var rdb = redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) func SetAgentStatus(ctx context.Context, agentID int, status string) error { key := fmt.Sprintf("agent:%d:status", agentID) return rdb.Set(ctx, key, status, 24*time.Hour).Err() } func GetAgentStatus(ctx context.Context, agentID int) (string, error) { key := fmt.Sprintf("agent:%d:status", agentID) return rdb.Get(ctx, key).Result() } // Использование: // SetAgentStatus(ctx, 42, "ready") -- оператор свободен // SetAgentStatus(ctx, 42, "busy") -- в разговоре // SetAgentStatus(ctx, 42, "break") -- на перерыве
Ключевой инсайт:

Redis — это «оперативная память» системы. Всё что нужно знать ПРЯМО СЕЙЧАС (кто онлайн, кто свободен, сколько в очереди) — здесь. Данные эфемерны: перезапуск Redis не сломает систему, только временно обнулит метрики.

N

NATS — Шина событий

Go Message Broker Pub/Sub

NATS — легковесный брокер сообщений, написанный на Go. Быстрее RabbitMQ, проще Kafka. Обеспечивает асинхронную связь между компонентами: FreeSWITCH генерирует события, Go обрабатывает их и рассылает подписчикам — дашборду, CDR-процессору, вебхук-диспетчеру.

Subject (тема) Данные события
call.started uuid, caller, callee, direction, queue
call.answered uuid, agent_id, wait_time
call.ended uuid, duration, disposition, recording_path
agent.status.changed agent_id, old_status, new_status
queue.stats.updated queue_id, waiting, talking, sla
voicemail.new box_id, caller, duration, file_path
cdr.ready cdr_id, complete record
webhook.dispatch url, payload, event_type
Go — публикация и подписка на NATS-события
import ( "encoding/json" "log" "github.com/nats-io/nats.go" ) // Подключение к NATS nc, _ := nats.Connect("nats://localhost:4222") // Публикация события "вызов начат" event := map[string]interface{}{ "uuid": "a1b2c3d4", "caller": "+74951234567", "callee": "1001", "direction": "inbound", } data, _ := json.Marshal(event) nc.Publish("call.started", data) // Подписка — получаем все события вызовов nc.Subscribe("call.>", func(msg *nats.Msg) { log.Printf("[%s] %s", msg.Subject, string(msg.Data)) })
Ключевой инсайт:

NATS развязывает компоненты. FreeSWITCH не знает о React-дашборде, Go не знает о CRM — они просто публикуют события. Каждый подписчик получает то, что ему нужно, не создавая связности.

UI

React Frontend — Панель управления

TypeScript SPA React 18

React Frontend — одностраничное приложение (SPA) для администрирования системы, панели оператора и реалтайм-дашбордов. Включает встроенный WebRTC-телефон на базе SIP.js и визуальный конструктор IVR на React Flow.

Страница Назначение
Dashboard Реалтайм: активные вызовы, очереди, агенты
Users CRUD пользователей и расширений
Queues Настройка очередей, стратегий, агентов
IVR Builder Визуальный drag-n-drop конструктор меню
CDR Журнал вызовов с фильтрами и экспортом
Recordings Прослушивание записей, скачивание
Reports Графики, SLA, heatmap нагрузки
WebPhone Встроенный SIP.js-телефон
Campaigns Управление автообзвоном
Settings Транки, маршруты, безопасность
TypeScript — подключение WebSocket для реалтайм-событий
import { useEffect } from "react"; import { useQueueStore } from "./stores/queue"; export function useRealtimeEvents() { const updateQueue = useQueueStore(s => s.update); useEffect(() => { const ws = new WebSocket("wss://api.example.com/ws"); ws.onmessage = (e) => { const event = JSON.parse(e.data); switch (event.type) { case "call.started": // Добавляем вызов на дашборд addActiveCall(event.data); break; case "queue.stats.updated": // Обновляем метрики очереди updateQueue(event.data); break; } }; return () => ws.close(); }, []); }

Ключевые библиотеки:

React 18 TypeScript SIP.js React Flow Recharts TanStack Query Tailwind Zustand
Ключевой инсайт:

React Flow позволяет строить IVR визуально — перетаскивая блоки. Это намного удобнее чем XML/Lua конфиги. Пользователь рисует меню мышкой, а система генерирует конфигурацию автоматически.

H

Homer — SIP-мониторинг

HEP SIP Capture Troubleshooting

Homer — специализированный инструмент захвата и анализа SIP-трафика. Перехватывает все SIP-пакеты через HEP-протокол, строит визуальные диаграммы вызовов и помогает диагностировать проблемы с сигнализацией. Незаменим при отладке «звонок не проходит».

Функция Назначение
SIP Capture Захват всех SIP-пакетов через HEP-протокол
Call Flow Визуальная диаграмма: INVITE → 180 → 200 → BYE
Search Поиск по номеру, Call-ID, времени, статусу
Alerts Уведомления при SIP-ошибках, высоком % отказов
Statistics Графики: calls/sec, response codes, latency
kamailio.cfg — отправка SIP-пакетов в Homer через HEP
# Загружаем модуль siptrace для отправки в Homer loadmodule "siptrace.so" modparam("siptrace", "duplicate_uri", "sip:homer.local:9060") modparam("siptrace", "hep_mode_on", 1) modparam("siptrace", "hep_version", 3) modparam("siptrace", "trace_flag", 22) # В request_route — включаем трассировку request_route { setflag(22); # trace_flag — все запросы отправляются в Homer sip_trace(); ... }
Ключевой инсайт:

Homer — ваш «Wireshark для SIP». Когда звонок не проходит, Homer покажет ТОЧНО где он застрял: на Kamailio? На FreeSWITCH? Получил 403? Таймаут? Визуальная диаграмма call flow экономит часы отладки.

AI

AI/ML-сервисы — Распознавание и аналитика

Python ASR / TTS NLP

AI/ML-сервисы — набор внешних сервисов для обработки речи и интеллектуальной аналитики. Распознавание речи (ASR), синтез речи (TTS), анализ транскрипций через LLM и определение тональности. Могут быть как self-hosted, так и облачными.

Сервис Назначение
Vosk Self-hosted ASR (Speech-to-Text), поддержка русского
Whisper OpenAI ASR, высокое качество, можно self-host
Piper Self-hosted TTS (Text-to-Speech), нейросетевой
LLM (Claude/GPT) Анализ транскрипций, суммаризация, классификация
Sentiment Определение тональности: позитивная/негативная

Поток обработки (integration flow):

Вызов → FreeSWITCH записывает → WAV-файл → Whisper STT → текст транскрипции → LLM-анализ (суммаризация, классификация, тональность) → результаты в БД

Python — распознавание записи через Whisper
import whisper # Загружаем модель (можно: tiny, base, small, medium, large) model = whisper.load_model("medium") # Распознаём запись разговора result = model.transcribe( "/recordings/2026-02-18/call_a1b2c3d4.wav", language="ru", task="transcribe" ) print(result["text"]) # "Здравствуйте, я хотел бы узнать о статусе моего заказа..." # Сегменты с временными метками for seg in result["segments"]: print(f"[{seg['start']:.1f}s] {seg['text']}")
Ключевой инсайт:

Vosk работает оффлайн и бесплатно. Для реалтайм-распознавания в IVR — идеальный выбор. Whisper лучше для post-call анализа, где важно качество, а не скорость.

Инфраструктура — DevOps-компоненты

Docker Monitoring CI/CD

Инфраструктура — набор DevOps-инструментов, обеспечивающих контейнеризацию, мониторинг, логирование, хранение файлов и автоматизацию развёртывания. Без этого слоя невозможно надёжно эксплуатировать систему в продакшене.

Инструмент Назначение
Docker / Compose Контейнеризация всех компонентов
Nginx Reverse proxy, TLS, балансировка HTTP
Prometheus Сбор метрик (CPU, RAM, calls, queue depth)
Grafana Визуализация метрик, алерты
Loki Агрегация логов из всех контейнеров
MinIO S3-совместимое хранилище для записей разговоров
Certbot Автоматическое обновление SSL-сертификатов
Ansible Автоматизация развёртывания и конфигурации
docker-compose.yml — основные сервисы (фрагмент)
version: "3.8" services: kamailio: image: kamailio/kamailio:latest ports: - "5060:5060/udp" - "5061:5061/tcp" depends_on: [postgres, redis] freeswitch: image: freeswitch/freeswitch:latest ports: - "8021:8021" # ESL volumes: - recordings:/var/lib/freeswitch/recordings rtpengine: image: drachtio/rtpengine:latest network_mode: host # нужен прямой доступ к UDP-портам go-backend: build: ./backend ports: - "8080:8080" depends_on: [postgres, redis, nats, freeswitch] postgres: image: postgres:16 volumes: - pgdata:/var/lib/postgresql/data redis: image: redis:7-alpine nats: image: nats:latest ports: - "4222:4222"
Ключевой инсайт:

Docker Compose — ваш лучший друг на старте. Один файл docker-compose.yml поднимает ВСЮ систему. Для продакшена — переходите на Docker Swarm или Kubernetes, но начинайте с Compose.