Делаем P2P-кинотеатр: как мы написали десктопное приложение для совместного просмотра видео на Electron

от автора

Я разработал десктопное приложение для 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)

Три главные ценности, на которых построен продукт:

  1. Всё одновременно. Трансляция экрана со звуком системы + голос по микрофону + видео с камеры — всё это работает одновременно. Не нужно выбирать, чем жертвовать. Один показывает экран, остальные смотрят и комментируют голосом.

  2. Напрямую, без серверов. P2P-соединение — видео и аудио идут напрямую между участниками. Никаких облачных серверов для медиа, никакой слежки, никаких теорий заговора. Сервер нужен только на секунду для установки соединения.

  3. Рация по пробелу. Режим 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

ссылка на оригинал статьи https://habr.com/ru/articles/1049068/