Я разработал десктопное приложение для Windows, которое позволяет смотреть видео вместе с друзьями онлайн. Ключевая возможность — всё одновременно: один участник транслирует экран со звуком системы, и при этом все могут общаться голосом через микрофон и включать свои камеры. Никаких серверов посередине — данные идут напрямую между участниками. В статье расскажу про архитектуру, ключевые технические решения и грабли, на которые мы наступили.
Предыстория
Всё началось с простой проблемы: мы с друзьями живём в разных городах, но хотим вместе смотреть кино. Существующие решения либо платные, либо требуют регистрации, либо не передают звук системы. А хочется просто включить фильм, кинуть друзьям ссылку и смотреть, комментируя в голосовом чате, нажимая пробел, когда хочешь что-то сказать — как настоящая рация.
Готовых бесплатных решений, которые делают именно это — экран + звук системы + голос поверх + без регистрации — мы не нашли. Решили написать своё.
Выбор технологий
Платформа — Windows. Цель — один портативный .exe, который можно кинуть другу и сразу начать смотреть.
Electron 34 — как основа десктопного приложения
WebRTC — для передачи видео и аудио напрямую между участниками
Socket.IO — для сигналинга (помочь участникам найти друг друга)
Сборка — electron-builder, portable.exe
Архитектура P2P-соединения
Участники соединяются напрямую (peer-to-peer). Видео и аудио не проходят через сервер — только напрямую между клиентами. Это даёт минимальную задержку, позволяет не платить за серверную пропускную способность и гарантирует, что ваши данные видит только тот, кому вы их отправили. Никаких облачных серверов, никакой записи разговоров, никаких «корпоративных аккаунтов», куда стекается всё ваше общение.
Архитектура P2P-соединения
Участники соединяются напрямую (peer-to-peer). Видео и аудио не проходят через сервер — только напрямую между клиентами. Это даёт минимальную задержку, позволяет не платить за серверную пропускную способность и гарантирует, что ваши данные видит только тот, кому вы их отправили. Никаких облачных серверов, никакой записи разговоров, никаких «корпоративных аккаунтов», куда стекается всё ваше общение.
A ────── P2P ──────────── Участник B
│ │
└──── P2P ───────────────┘
│
Участник C
Сервер нужен только на этапе установки соединения (сигналинг). Мы используем облачный сервер на Render.com и встроенный локальный сервер для работы по LAN.
После того как участники нашли друг друга, все данные идут напрямую. Сервер можно выключить — соединение останется.
Ключевые фичи, которые потребовали нетривиальных решений
Трансляция экрана со звуком системы
WebRTC в браузере не умеет захватывать звук системы при трансляции экрана. Electron даёт доступ к нативному API Chromium — getDisplayMedia с опцией audio: true. Пользователь видит диалог выбора окна, может выбрать свёрнутое окно и включить флажок «Поделиться звуком».
Браузерное ограничение: мобильная версия не может транслировать экран со звуком, только смотреть.
Режим рации (Push-to-Talk)
Мы сделали два режима работы микрофона:
Обычный: микрофон включён постоянно
Рация: микрофон работает только пока зажата кнопка
В десктоп-версии вход в режим рации — правая кнопка мыши по иконке микрофона. Говорить — зажать Пробел. В мобильной версии — двойной тап по микрофону.
Технически это просто включение/выключение локального трека, но важно было не трогать остальные соединения.
Плавающая панель при трансляции
Когда пользователь начинает транслировать экран, главное окно сворачивается, и появляется маленькое плавающее окно (310×78) с кнопками управления: микрофон, камера, рация, остановка трансляции. Оно всегда поверх других окон.
Рядом открывается окно камер участников (300×220) с превью всех камер и ползунками громкости.
Поддержка двух режимов: локально и через интернет
Приложение работает как через интернет (облачный сервер сигналинга), так и локально по LAN — без доступа в интернет. Это оказалось полезно для корпоративных сетей и мест с плохим интернетом.
Что пошло не так
Некоторые вещи пришлось переделывать по несколько раз:
Выбор окна для трансляции. Первая версия использовала кастомный пикер окон. Он не показывал свёрнутые окна и имел проблемы с обновлением списка. Перешли на нативный диалог Chromium — он показывает все окна, включая свёрнутые, и сам обновляется.
Модалка выбора окна на мобильной версии изначально была в 2 колонки — окна не влезали. Переделали на 3 колонки, стало нормально.
Сборка portable .exe. Electron-builder делает установщик, но нам нужен был один .exe без установки. Потребовалось отдельно собирать portable через --prepackaged.
Windows Defender. Каждая новая сборка с новым именем файла — чтобы не блокировался антивирусом.
Текущее состояние
Приложение работает, (последняя версия 1.8.0)
Три главные ценности, на которых построен продукт:
Всё одновременно. Трансляция экрана со звуком системы + голос по микрофону + видео с камеры — всё это работает одновременно. Не нужно выбирать, чем жертвовать. Один показывает экран, остальные смотрят и комментируют голосом.
Напрямую, без серверов. P2P-соединение — видео и аудио идут напрямую между участниками. Никаких облачных серверов для медиа, никакой слежки, никаких теорий заговора. Сервер нужен только на секунду для установки соединения.
Рация по пробелу. Режим Push-to-Talk: зажал пробел — говоришь, отпустил — тебя не слышно. Идеально для комментариев во время просмотра, чтобы не шуметь в эфире постоянно.
Полный список возможностей:
Трансляция экрана со звуком системы (Windows)
Голосовой чат через микрофон
Видеозвонок (камера каждого участника)
Режим рации Push-to-Talk (зажал пробел — говоришь)
До 5 участников в одной P2P-сетке
Работает без установки (portable .exe)
Без регистрации, без рекламы, без слежения
Два языка интерфейса: русский и английский
Мобильная версия (PWA) для просмотра с телефона
Весь проект — open source на GitHub.
Ссылки
Иcходный код: https://github.com/outmilker1978/hamsters-theater
Скачать: https://github.com/outmilker1978/hamsters-theater/releases
Сайт проекта: https://tvhamsters.outmilk.online


















