Переговорка (ToshaStream): стрим-сервер и голосовая для команды
собственный продукт в продакшене, версия 1.50.0: голос, чаты и закрытый эфир
Закрытая площадка на своём сервере: трансляция по SRT с двумя качествами, просмотр в браузере, голосовая связь напрямую между участниками через WebRTC, чаты и роли доступа. Стрим-сервер и голосовая для команды.

Задача
Прежняя схема была голым nginx-rtmp без настроек: трансляция периодически обрывалась, а подключиться к потоку и даже писать в него мог любой, кто знал адрес. Ролей и закрытых сессий не было. Для рабочего созвона такая связка не годится так же, как для трансляции.
Нужна была закрытая площадка для узкого круга людей: голосовые каналы, текстовые чаты и, когда нужно, трансляция игрового процесса с домашнего компьютера. Плюс два условия. Зритель с телефона на LTE и зритель на гигабитном канале должны получать разный поток, а не один компромиссный. А сервис не должен ронять соседей: раньше сервер стрима работал на одной машине с входным узлом VPN, и любой сбой стрима грозил VPN у всех клиентов.
Решение
В репозитории продукт называется «Переговорка» (прежнее имя — ToshaStream). Он открывается в браузере по секретной ссылке, а трансляцию можно смотреть ещё и в VLC. Страница работает в двух режимах: «Переговорка» (голос и чаты без плеера) и «Эфир» (плеер, чат эфира и голосовая рядом). Что сделано по README и журналу выпусков:
- Приём потока по SRT с шифрованием и паролем, резервный приём по RTMP.
- Два качества одновременно: родное 3440×1440 и облегчённое 1720×720 для мобильного интернета.
- Просмотр в браузере через HLS и через WebRTC (WHEP) с задержкой меньше секунды, в VLC — по RTSP и SRT.
- Голосовая на WebRTC-mesh со своим TURN: три общих канала, звонки в личных беседах, группы, режим «только голос».
- Показ экрана через сервер: 1080p, 30 кадров в секунду, до 18 Мбит/с.
- Чаты: три общих, личные, группы и чат эфира; реакции, ответы, опросы, закреп, поиск, предпросмотр ссылок, вложения, голосовые сообщения.
- Роли гость, свой, админ и «только личка», аккаунты на время, журнал входов и кнопка «выйти везде».
- Пуши на каждое устройство без дублей и настройка «без звука» по беседе.
- Ночной снимок базы, проверка здоровья контейнеров и автоперезапуск залипшего сервиса.
Как это устроено
SRT вместо RTMP
SRT (Secure Reliable Transport) — протокол передачи видео поверх UDP, который повторно запрашивает потерянные пакеты. Поток с ПК стримера приходит на сервер по SRT под паролем и с ключом шифрования. RTMP оставлен запасным приёмом. Сам сервер видео не перекодирует, поэтому качество эфира целиком зависит от настроек на игровом ПК; инструкция по OBS собрана отдельно.
Два качества эфира без перекодирования на сервере
Оба потока, 3440×1440 и 1720×720, кодирует видеокарта на ПК, а сервер только раздаёт. Единственное, что перекодируется, — звуковая дорожка в AAC для Safari, и это единицы процентов ядра процессора. Обратная сторона: при выключенном ПК нет ни одного из потоков.
Просмотр: HLS для устойчивости, WHEP для скорости
HLS (потоковое видео сегментами) даёт 6–8 секунд задержки, но выдерживает нестабильную мобильную сеть, и в нём можно отмотать назад примерно на 16 секунд (8 сегментов по 2 секунды). WHEP — способ получить поток через WebRTC с задержкой меньше секунды. Зритель выбирает между обычным и «быстрым» режимом. Поток 1440p в браузере играют Chrome, Edge и Safari, а для Firefox есть 720p в H.264.
Голосовая на WebRTC-mesh со своим TURN
WebRTC-mesh означает, что каждый участник соединяется напрямую с каждым: голос через сервер не идёт вовсе, сервер лишь сводит участников и передаёт служебные пакеты. Отсюда задержка в десятки миллисекунд и почти нулевая нагрузка на сервер. Расплата — каждый шлёт голос каждому, поэтому предел стоит осознанно: 10 человек на канал. TURN — ретранслятор для тех, к кому нет прямого соединения. В coturn включены временные учётные данные на час, секрет наружу не выходит, а расшифровать разговор ретранслятор не может.
Закрытый доступ: auth_request в nginx и роли
Каждый запрос к HLS, WHEP и звуку проверяется через auth_request: nginx перед выдачей спрашивает у сервиса, вошёл ли человек. Для VLC и внешних плееров есть отдельный секрет. Роли живут в базе и меняются из админки на ходу, без перезапуска и обрыва чужого разговора. Роль «только личка» видит одну переписку с админом: общие чаты, каналы, эфир и чужие имена для неё закрыты на сервере. Изменяющие запросы принимаются только POST-ом с проверкой Sec-Fetch-Site.
Чаты, голосовые сообщения и история
История чатов лежит в SQLite и переживает перезапуск. Голосовое сообщение записывается прямо из поля ввода (до 5 минут), а сервер перекодирует его в mp3 через ffmpeg, чтобы его играли и iPhone, и Android, и компьютер. Ссылки получают предпросмотр, который собирает сервер, с защитой от SSRF: внутренние и частные адреса не открываются вовсе. Уведомления не дублируются: пока человек читает чат на одном устройстве, пуши не идут ни на какие другие.
Устойчивость сервиса
Контейнеры отвечают на проверку здоровья, а чат — на /healthz с чтением и записью базы. Сторожевой таймер поднимает залипший контейнер в течение минуты, но не чаще трёх раз в час. База снимается по ночам, а отдельная машина забирает снимки и проверяет восстановление; сбой приходит сообщением в Telegram. Сервис работает на отдельной машине, поэтому уронить VPN не может.
Результат
- Задержка просмотра меньше секунды через WHEP, 6–8 секунд через HLS.
- До 10 человек на голосовой канал напрямую, без нагрузки на сервер.
- Рабочие созвоны и трансляции идут на собственной инфраструктуре, без сторонних мессенджеров.
- История чатов хранится 90 дней и переживает перезапуск.
- Голос защищён сквозным шифрованием между браузерами.
Технологии: что и зачем
- Go — сервис чата, аккаунтов, ролей, сигналинга голосовой и счётчика зрителей.
- MediaMTX — приём SRT и раздача HLS, WHEP, RTSP.
- WebRTC и coturn — голос напрямую между участниками и собственный TURN.
- SQLite — аккаунты, сообщения, состояние прочтения.
- nginx — вход по HTTPS и проверка доступа на каждый запрос.
- Docker Compose — запуск сервисов с потолком по процессору и памяти.
Статус
Версия 1.50.0 от 29 сентября 2026 года, в продакшене, собственный продукт. Рабочее название в README — «Переговорка»; внутренние имена путей и потоков пока прежние.
Известные ограничения по README: текстовый чат не сквозной, его читает тот, у кого есть root на машине; вход в эфир ограничен аккаунтом, но не ролью; групповой голос — mesh, а не SFU, поэтому больше 10 человек на канал потребует другой схемы; запись эфира сейчас выключена, включать её заново нужно вместе с настроенной ротацией. В планах: проверить эфир после правки задержки SRT, обкатать Telegram-бота управления аккаунтами, сменить пароль публикации SRT.
Вопросы по проекту
Почему для трансляции SRT, а не RTMP, и как это убирает обрывы?
Какая задержка у трансляции в браузере?
Слышит ли сервер голосовые разговоры?
Можно ли вести рабочие созвоны и чаты на своём сервере, а не в облачном мессенджере?
Какие данные хранятся и кто имеет доступ?
Можно ли развернуть такую систему для другой команды?
Ещё по этому направлению
OshaVPN Router: своя прошивка для MikroTik — VPN на весь офис
прошили заказчику MikroTik с Авито: весь офис за VPN, российское напрямую, зарубежное через туннель, на устройствах ничего не нужно ставить
VPN-инфраструктура: входной узел в России, выход в Европе
собственный продукт: релей в России, постоянный туннель и узел в Нидерландах
Корпоративный шлюз на Xray и nginx для IT-команды
заказ IT-компании: рабочие инструменты снова доступны на своих серверах
Нужно похожее?
Расскажите о задаче — покажем, как решали такое, и прикинем объём работ.