Медиа-звонки и запись на Jitsi — интеграционный гид (messenger)
Дом интеграции media-стека звонков контекста messenger с саморазмещённым Jitsi. Здесь описано, как
абстрактные контракты домена и API (нейтральные «media-стек / SFU», MediaJoinModel) отображаются на
конкретные компоненты Jitsi: prosody, jicofo, JVB (SFU), jibri (запись), coturn (TURN). Доменные и
API-документы остаются нейтральными (ADR-0062) — конкретика Jitsi живёт только здесь и в
api/internal/ (вебхуки от media-стека).
Назначение папки. Это не спецификация домена, а гид/раннбук интеграции: он называет компоненты и конфиг-ключи Jitsi, указывает пути в
thirdparty/jitsi/*и объясняет, что PIN дорабатывает. Контракт (сущности, поля, статусы, события, ошибки) — вdomain/,api/,events/; здесь — как это работает на Jitsi.
Обзор
Звонки и конференции PIN — это нативный клиент поверх lib-jitsi-meet (без веб-SPA jitsi-meet),
подключённый к саморазмещённому Jitsi. Медиа (звук/видео/демонстрация экрана) идёт клиент ↔ SFU (JVB) —
бэкенд messenger не в медиа-плоскости: он раздаёт вход в комнату (имя + короткоживущий JWT), принимает
серверные вебхуки о жизненном цикле и финализирует записи.
- SFU = JVB (jitsi-videobridge): маршрутизация медиа между участниками (SFU, не mesh). Для 1:1 включаем
p2p.enabled(медиа напрямую, JVB подключается при escalation/3+). - Сигналинг/присутствие = prosody + jicofo: комнаты MUC, роли, admission. Авторитет состава — серверные
hook-и prosody (вебхуки в
messenger), не клиентские события (jitsi-rooms.md). - Запись = jibri (по политике
RecordingPolicy.ShouldAutoRecord): захват → выгрузка в file storage (recording-pipeline.md). Файл записи хранитmessengerкакFileId+ метаданные, бинарь — в file storage (ADR-0032, call-recording.md INV-REC-6). - NAT/TURN = coturn: обход NAT для клиентов за симметричным NAT.
Бэкенд messenger stateless относительно медиа: не подключается к XMPP, не хранит SDP/ICE/токены
(INV-CALL-4/6, INV-CONF-7). Он только минтит JWT входа (jitsi-jwt.md) и принимает вебхуки
(../api/internal/).
Feature-флаги
| Флаг | Гейтит | Поведение при false |
|---|---|---|
CALLS_MEDIA_ENABLED | media 1:1-звонков (комната + токен) | 503 MSG_CALLS_DISABLED на media-операциях 1:1 |
CONFERENCE_CALLS_ENABLED | групповые конференции в чате сделки | 503 MSG_CONFERENCES_DISABLED |
RECORDINGS_ENABLED | запись сессий (jibri) | запись не стартует; сессия/звонок работают без записи |
Авто-запись — не булев флаг, а типизированное решение RecordingPolicy.ShouldAutoRecord(chatKind, sessionKind) (recording-pipeline.md). Исторический CALLS_SIGNALING_ENABLED
(signaling-only стадия) поглощён CALLS_MEDIA_ENABLED.
Карта сущностей ↔ Jitsi
| Сущность (дом) | Роль в Jitsi | Комната |
|---|---|---|
CallSessionEntity (1:1) | MUC-комната на 2 участников (p2p предпочтителен) | call-{CallSessionId} |
ConferenceSessionEntity | MUC-комната сделки, динамический ростер | conf-{ConferenceSessionId} |
CallParticipantEntity | occupant MUC; presence-вебхук — авторитет ростера | — |
CallRecordingEntity | сессия jibri (file mode) → file storage | — |
MediaRoom (owned VO) | { RoomName, Domain } — маршрутный id комнаты (не медиа/PII) | — |
Имя комнаты детерминировано из id сессии, потому что reservation-вебхук prosody несёт только имя —
по нему messenger находит сессию (jitsi-rooms.md).
Документы гида
Реализация и поставка (аналитик → разработчик)
Как это построить и в каком порядке, спека → код, предпосылки и приёмка.
| Документ | О чём |
|---|---|
| session-lifecycle.md | Жизненный цикл сессии (1:1 и конференция): как создать/открыть, как подключить/добавить участников (join/invite/decline/remove), как закрыть — все пути, гонки, реконнект, sequence-диаграммы, матрица «действие → эндпоинт → переход → событие» |
| implementation-plan.md | Мастер-план поставки: фазы Ф0–Ф6 (DoR/задачи/DoD/риски), дерево зависимостей, RACI, критический путь, порядок мержа, два master sequence-диаграммы, продакшн-чеклист |
| backend-implementation.md | Спека → код (.NET/SDK Talent.Common.*): раскладка проектов, агрегаты/EF (ConfigureOwnedTypes MediaRoom, XOR-CHECK, partial-индексы), DDL+миграции, CQRS-операции всех эндпоинтов, RecordingPolicy, JitsiTokenService, filestorage-адаптер, HMAC-фильтр internal, outbox→dispatch |
| filestorage-prerequisites.md | Пошаговый чеклист изменений в talent.microservices.filestorage: категория CALL_RECORDINGS, видео content-types, сидеры, миграция, стриминг-загрузка |
| testing-and-acceptance.md | Сквозная верификация: локальный dev-стек docker-jitsi-meet, пирамида тестов, e2e по UC-005/006/007, тесты безопасности, acceptance-чеклист, наблюдаемость |
Компоненты и конфигурация Jitsi
Как контракт отображается на конкретные компоненты, конфиги и правки Jitsi.
| Документ | О чём |
|---|---|
| jitsi-deployment.md | k8s-топология: prosody/jicofo/JVB/jibri/coturn, реплики, порты, env-матрица, prosody/jicofo config-скетчи, секреты/сеть/health; как stateless-бэкенд взаимодействует |
| jitsi-manifests.md | k8s/Helm YAML-скетчи всех компонентов (Deployment/Service/HPA/ConfigMap/Secret), UDP-hostPort JVB, /mnt/recordings jibri, TLS-ingress → /xmpp-websocket |
| jitsi-jwt.md | минтинг JWT входа в .NET (HS256 + app_secret); claim-структура + пример payload; ротация ключа; маппинг MediaJoinModel.AccessToken |
| jitsi-rooms.md | именование комнат, authoritative-lifecycle через mod_reservations (wire-формат), presence-вебхук через кастомный prosody-модуль, sequence-диаграмма |
| jitsi-client.md | нативный lib-jitsi-meet на Next.js 16: connect → join → tracks → события → мост в SignalR; FSD-раскладка |
| recording-pipeline.md | сквозная авто-запись: policy → jibri → finalize-скрипт → ingest → file storage → Available → Kafka |
| jitsi-modifications.md | инвентарь изменений в thirdparty/jitsi/*: полный текст pin_finalize.sh, скетч mod_pin_muc_presence.lua, per-component change list с путями |
| transcription-roadmap.md | будущая фаза STT/конспект (шов, не блокирует) |
Границы и предпосылки
- Нейтральность именования. В
domain/,api/{calls,conferences,recordings}/и hub — только «media-стек / SFU» иMediaJoinModel; «Jitsi/jibri/prosody» допустимы лишь здесь и вapi/internal/(вебхуки — их предмет). - Right-sizing (ADR-0056). Целевая нагрузка низкая (1–10k активных, конференции редки) — минимальные реплики, один регион, без Octo (jitsi-deployment.md).
- Config-reference vs IaC. Мета-репозиторий Jitsi поставляет Nomad-IaC
(
thirdparty/jitsi/infra-provisioning/nomad/*) как референс конфигурации; PIN пишет собственные Helm/k8s-манифесты, перенося оттуда env-переменные и параметры. - Блокирующие предпосылки file storage. Для записей нужны новая категория
CALL_RECORDINGSи видео content-types (mp4/webm/mkv) на стороне file storage (recording-pipeline.md).
Связанные документы
- Сущности: call-session.md, conference-session.md, call-participant.md, call-recording.md.
- API: calls, conferences, recordings, internal (вебхуки); realtime: hub.
- События: conference-ended.md, call-recording-available.md.
- Контекст: messenger README.
- Решение: ADR-0062 медиа-стек и запись на Jitsi (supersedes ADR-0055 §2.4); ADR-0056 simplicity-first, ADR-0032 retention.