Шлюзы WHIP и WHEP, голосовой конвейер ИИ, каскад нод и мониторинг

Обновлено:

Помимо классического WebSocket сигналинга (описанного в статье Протокол сигналинга и управление качеством), Slyber SFU Server включает четыре специализированных шлюза для прямой интеграции со студийными видеоэнкодерами, голосовыми моделями искусственного интеллекта, сетями доставки контента MoQ и соседними узлами кластера, а также встроенный экспортер телеметрии.

Вещание и просмотр в один запрос через WHIP и WHEP

Стандарты WHIP (WebRTC HTTP Ingestion Protocol) и WHEP (WebRTC HTTP Egress Protocol) позволяют публиковать и принимать потоки за один HTTP запрос без подключения к WebSocket сигналингу. Это идеальный вариант для прямых эфиров из программы OBS Studio, аппаратных камер и быстрых веб плееров.

  • Публикация потока (POST /whip/{room_id}/{track_id}). Клиент отправляет SDP Offer в теле запроса с заголовком Content-Type равным application/sdp и токеном авторизации в заголовке Authorization: Bearer <TOKEN>. Сервер создает сессию с основным видеотреком {track_id} и сопутствующим аудиотреком {track_id}-audio, возвращает статус 201 Created, готовый SDP Answer, заголовок Location, уникальный идентификатор ресурса ETag и заголовки Link с настройками внешних TURN серверов.
  • Подписка зрителя (POST /whep/{room_id}/{track_id}). Зритель отправляет recvonly SDP Offer и сразу получает 201 Created с SDP Answer, в который уже привязаны видео и аудиопоток трансляции без необходимости дополнительной ренегоциации. В заголовке Location возвращается персональный адрес подписки /whep/{room_id}/{track_id}/{sub_id}.
  • Досылка кандидатов и защита владельца (PATCH и DELETE). Для досылки Trickle ICE кандидатов клиент отправляет запрос PATCH с типом application/trickle-ice-sdpfrag. Для завершения эфира отправляется запрос DELETE. Сервер строго проверяет владельца ресурса ownerID и заголовок If-Match (ETag). Попытка стороннего участника перезаписать или удалить чужую трансляцию блокируется со статусом 403 Forbidden или 409 Conflict.

Полнодуплексный аудиошлюз для голосового ИИ (/ai/ws)

Шлюз AI Media Pipe позволяет подключить к любой комнате голосовых ИИ ассистентов (например на базе Gemini Live или OpenAI Realtime API) по обычному WebSocket соединению без реализации WebRTC, ICE и SRTP на стороне ИИ сервиса. Доступ к маршрутам /ai/ws и /ai/ защищен административным заголовком X-Slyber-Node-Secret.

YAML
GET /ai/ws?room=room-dialog&mode=mux&pacing=true&auto_flush=true HTTP/1.1
Host: 127.0.0.1:8090
Upgrade: websocket
Connection: Upgrade
X-Slyber-Node-Secret: your-24-char-production-node-secret

Режимы работы и управление несколькими ботами в одной комнате

  • Одиночный режим (по умолчанию). При подключении к /ai/ws?room=room-dialog сервер автоматически создает в комнате аудиотрек ai-voice-bot и отправляет текстовый фрейм ai_ws_ready. Все бинарные фреймы (Opcode 0x02), которые ваш сервис отправляет в сокет, содержат чистые Opus пакеты голоса бота, а в обратную сторону сервер присылает бинарные фреймы с чистым Opus звуком микрофонов людей из комнаты.
  • Мультиплексированный режим (mode=mux). Позволяет одному бэкенд процессу управлять сразу несколькими независимыми ИИ агентами в одной комнате. Входящие бинарные фреймы от ботов имеют 2-байтный префикс [slot, audio_level] перед полезной нагрузкой Opus, а исходящие бинарные фреймы с голосом людей содержат префикс [len(speaker_id), audio_level, speaker_id...], чтобы ИИ точно знал, кто именно из участников комнаты сейчас говорит.
  • Текстовые команды управления. Поверх того же сокета можно отправлять JSON команды {"type": "spawn_agent", "slot": 1, "agent_id": "bot-alina", "track_id": "ai-bot-alina"} для динамического добавления новых ботов (сервер ответит событием ai_agent_ready и оповестит комнату), {"type": "remove_agent", "slot": 1} для удаления бота и {"type": "clear_buffer"} для мгновенной очистки очереди аудио.
  • Встроенный пейсер 20 мс и детектор перебивания (VAD Barge In). Нейросети часто генерируют звук неравномерными пачками. Встроенный пейсер сервера буферизует до 600 фреймов (12 секунд речи) на каждого агента и плавно выпускает их в комнату ровно каждые 20 миллисекунд с правильным шагом RTP Timestamp (+960 отсчетов). Одновременно сервер следит за уровнем громкости микрофонов людей по заголовкам RFC 6464. Как только человек произносит 3 голосовых фрейма подряд, сервер фиксирует перебивание, при включенном флаге auto_flush=true мгновенно очищает очередь несказанных фраз бота и отправляет в сокет событие ai_vad_barge_in, а после 360 миллисекунд тишины присылает событие окончания фразы ai_vad_speech_end.
  • Инжект одиночных фреймов (POST /ai?room=room-dialog). Для простых голосовых уведомлений можно отправить raw Opus фрейм обычным HTTP POST запросом без открытия WebSocket.

Межсерверное каскадирование (/cascade/) и релей MoQ (/moq/)

Для горизонтального масштабирования комнат между несколькими серверами предусмотрен шлюз Slyber Cascade Pipe (/cascade/, требует заголовок X-Slyber-Node-Secret).

  • На принимающей ноде Б вызывается POST /cascade/ с полем "direction": "ingress", именем комнаты, трека, кодеком и целевым SSRC.
  • На отдающей ноде А вызывается POST /cascade/ с полем "direction": "egress" и UDP адресом ноды Б.
  • Нода А пересылает пакеты по UDP, снабжая каждый пакет 28-байтным заголовком (магические байты SC, версия протокола, флаги ключевого кадра и слоя, 64-битный номер пакета и 16-байтная криптографическая подпись HMAC-SHA256-128, вычисленная от NODE_SECRET). При выключенном флаге ALLOW_INTERNAL_CASCADE встроенный фильтр SSRF строго блокирует любые попытки указать в качестве цели локальные, приватные (RFC 1918) или CGNAT (100.64.0.0/10) адреса.

При включении флага ENABLE_MOQ_RELAY=true становится доступен эндпоинт GET /moq/{room_id}/{track_id} (требует Bearer токен с правом подписки), который упаковывает медиапоток комнаты в объекты спецификации moqt-draft-22 с разбивкой групп строго по смене RTP Timestamp ключевого кадра (защита от MoQ Group Storm).

Мониторинг, инспектор и метрики Prometheus

Сервер предоставляет два защищенных эндпоинта телеметрии (доступных по заголовку X-Slyber-Node-Secret или токену node-admin).

  • GET /inspector/stats возвращает подробный JSON с состоянием рантайма Go (аптайм, число горутин, объем живой кучи в мегабайтах через безблокировочный интерфейс runtime/metrics), статистикой стека Pion WebRTC (секция webrtc_pion с числом активных сессий, треков и принятых/отправленных байт), метриками QoS (секция webrtc_qos со счетчиками nacks_retransmitted, plis_forwarded, plis_sent_to_pub и ratelimit_drops) и счетчиками всех шлюзов (секция gateways). Этот эндпоинт напрямую используется визуальным стендом тестирования Slyber Inspector.
  • GET /metrics отдает все показатели узла в стандартном текстовом формате Prometheus (метрики slyber_sfu_uptime_seconds, slyber_sfu_active_rooms, slyber_sfu_webrtc_sessions, slyber_sfu_rtp_rx_bytes_total, slyber_sfu_rtp_tx_bytes_total, slyber_sfu_nacks_retransmitted_total, slyber_sfu_ai_active_agents и другие) с тегом node для построения дашбордов Grafana.