LINUX.ORG.RU

VChat — простой видеочат на WebRTC

 sfu, ,


6

1

Рад представить вам мою поделку — простенький WebRTC-чат. «Поднимается» тремя командами.

Под капотом ReactJS (это фронт + завернут в ElectronJS если хотите приложение, чтобы был звук из системы во время стрима экрана и глобально работали горячие клавиши).

На бэкенде чисто WebSocket на Node.js + Mediasoup.js в качестве SFU-сервера. Лицензия — MIT.

Я не особо планирую поддерживать этот проект, но если будут серьезные баги и все такое, то я поправлю.

>>> Проект на GitHub

★★★

Проверено: CrX ()
Последнее исправление: hobbit (всего исправлений: 2)

чтобы не делать вот это руками

docker compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ -d <ВАШ_ДОМЕН>
docker compose run --rm certbot renew

на будущее советую посмотреть вот сюда https://github.com/jwilder/docker-letsencrypt-nginx-proxy-companion

сертификат будет подтягиваться сам, по надобности, после docker compose up без лишних телодвижений

gagarin0
()
Ответ на: комментарий от mittorn

А мне медиасуп понравился. Очень гибко можно регулировать медиа потоки как тебе в кайф + там сами воркеры на C++, а управлять ими можно из JS. В целом для домашнего чатика поиграть с кентами збс) нас был 9 человек максимум одновременно в «разных комнатах» и все работало збс ИМХО)

romanlinux ★★★
() автор топика
Последнее исправление: romanlinux (всего исправлений: 1)
Ответ на: комментарий от gagarin0

Оооо спасибо) Буду знать. Я еще думал про traefik, но потом решил, что слишком «сложна». Один фиг у девопсеров у которых несколько сайтов на серваке и так будет «общий траефик» и если они захотят, то просто к его сети подключат вчат

romanlinux ★★★
() автор топика
Ответ на: комментарий от romanlinux

мне не понравилось начиная с того, что бэкенд чекает юзерагент и кидает exception при установке rtc соединения.
Есть смысл чекаь юзерагент только чтобы отдать фронтенд с соответствующими полифиллами, но зачем это делать при установке rtc - не понятно.
Дальше он пытался дёрнуть какик-то отсутствующие апишеи. Казалось бы, в js можно заполифиллить всё что угодно, но они конечно же не могут и будут дёргать undefined без проверки

mittorn ★★★★★
()
Ответ на: комментарий от romanlinux

общий траефик

да, так и есть, по нормальну это называется http(s) ingress :)

gagarin0
()
Последнее исправление: gagarin0 (всего исправлений: 1)
Ответ на: комментарий от antonio-an

Не не не) тут в место P2P и MESH-сети используется Mediasoup.js - это SFU (Selective Forwarding Unit), где сам сервер выступает WebRTC-эндпоинтом. Вместо классической P2P-схемы с STUN/TURN, здесь mediasoup напрямую обрабатывает ICE-соединения через свой встроенный WebRtcServer.

То есть нет такой ситуации, когда если несколько пользователей находятся в одной сети, так сказать в «одном NAT», то между ними не создается связь на прямую. Тут всегда идут медиа-потоки, через сервер(смотреть файл /server/server.js)(он же грубо говоря STUN)

romanlinux ★★★
() автор топика
Ответ на: комментарий от antonio-an

Вот тут поднимается «STUN сервер грубо говоря».

https://github.com/outZoNe/vchat/blob/main/server/services/RoomManager.js#L55-L70

и работает он на IP вашего сервера. прописывается этот IP в .env в ANNOUNCED_IP=

https://github.com/outZoNe/vchat/blob/main/.env.example#L18


Таким образом. Трафик целиком идет, через Ваш сервер и «никто» не сможет его прослушать. Даже провайдер, потому что там все шифруется по DLTS, это как HTTPS, только для UDP.

Ну за исключением MIT атаки(человек по середине) от вашего провайдера.


Ну грубо говоря вот так это все работает)

romanlinux ★★★
() автор топика
Ответ на: комментарий от antonio-an

Еще раз подытожу:

Как это работает:

Mediasoup сам генерирует ICE-кандидатов на основе listenInfos (IP + порт) announcedIp (из переменной окружения ANNOUNCED_IP) — это публичный IP, который сообщается клиентам Каждый воркер слушает на своём порту: базовый порт MEDIASOUP_MIN_PORT (по умолчанию 40000) + индекс воркера Поддерживаются и UDP, и TCP Поскольку клиенты подключаются напрямую к серверу mediasoup (а не друг к другу), необходимость в STUN для определения публичного IP отпадает — сервер уже знает свой announcedIp. TURN тоже не нужен, так как нет P2P-соединений, которые могли бы быть заблокированы NAT.


ИМХО не нужно путать WebRTC и P2P

Потому что Web RTC - это в целом «технология для передачи данных между браузерами в реальном времени», а вот p2p - это уже конкретно «способ» как будут эти данные переданы. на прямую между пользователями (в случае p2p) или, через «сервер»(грубого говоря STUN) - в случае SFU.

У меня все по «SFU», потому что так проще ИМХО для клиента(не нужно держать отдельное соединение с каждым собеседником, особенно это круто для телефонов, чтобы батарея не сажалась в 0 за 30 мин) + все равно почти всегда, все собеседники за «своим NAT» и все равно понадобится STUN…

romanlinux ★★★
() автор топика
Последнее исправление: romanlinux (всего исправлений: 1)
Ответ на: комментарий от hobbit

А чего мне тут делать? Медиасоуп прекрасный проект, но вот допиливание дальше вокруг него это дело времени. Нужны месяцы. А запилить такое вот простенькое минимальное можно за день, если знаешь что делаешь.

И его основная прелесть в масштабировании. Изейшее.

Тут еще архитектуру сервера надо продумать. Я вот не подумал и у меня очень очень много запросов к файлам. Все хранится в json-файлах. Теперь переделываю архитектуру общую. Перевожу все на вебсокеты, статику и динамику некоторую перевожу в озу… Там вообще много интересного. Попробуй.

В целом моя архитектура на самом минимальном впс дожна в теории тыщи три юзеров выдержать.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 4)
Ответ на: комментарий от LightDiver

В целом моя архитектура на самом минимальном впс дожна в теории тыщи три юзеров выдержать.

Подскажите пожалуйста. А как вы это высчитывали? Мне просто интересно «прикинуть» на что способно «мое решение» на минимальной ВПС?

romanlinux ★★★
() автор топика
Ответ на: комментарий от romanlinux

Чтобы долго и нудно не вычислять заголовки, тела, размеры в озу и на диске, время дисковых операций, рекомендую например вот это:

https://www.npmjs.com/package/artillery

Войс конечно это не протестит, а вот эмуляцию юзеров должно.

А вообще, разбираем архитектуру проекта, смотрим что куда идет, в каких размерах, где что сохраняется, с какой частотой читается. И на глаз прикидывается.

Свои структуры данных то я знаю. Вижу что в них, знаю как они обрабатываются.

Как пример:

const start = performance.now();
const users = await loadJsonFile(filePath);
const end = performance.now();
console.log(`loadUsers: ${(end - start).toFixed(2)} ms`);

У меня это хобби - высчитывать абсолютно бесполезные цифры там, где это не требуется.

Самое надежное - тесты. Еще ни один теоретический подсчет не сошелся с реальностью. Практика всегда преподносит сюрпризы.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 2)

А для пользователя это типа Zoom в браузере? Как с авторизацией и вообще безопасностью?

Кто ЦА? Для бизнеса или образования, вроде бы, простовато. Школоте негде это развернуть. Остаются студенты и преимущественно молодые айтишники.

Vidrele ★★★★★
()
Ответ на: комментарий от LightDiver

Да, об этом я не подумал. Уйдем во фрагментированные наколеночные междусобойчики.

Vidrele ★★★★★
()
Ответ на: комментарий от Vidrele

Да по сути это Zoom. Я бы даже сказал «конкретный сервер в Discord». Потому что идея в том, что любой желающий человек в мире может просто открыть «сайт по ссылке», потом выбрать любую комнату(прям как голосовые комнаты в Discord) и общаться в ней.

Без регистрации и СМС.


На счет ЦА я не думал :(

Просто после того как Дискорд + телеграм(звонки без лагов) заблочили. А нам с друзьями очень хотелось поиграть в игры вместе и нам нужна была возможность: голоса + демонстрация экрана(игры). Я собственно и решил сделать эту поделку.


Да «развертывание» - сложновато. Нужно иметь ВПС + домен, чтобы был https, иначе браузеры не дадут доступ к микрофону или камере или стримингу экрана…


В целом эта новость была «создана» из-за новости о том как поднять свой Jitsi. И там в комментарии я просто упомянул мою поделку)) А модераторы. Посоветовали мне сделать из этого новость)

П.С.

На самом деле. Я прямо сейчас делаю(уже почти готово) SaaS решение(прям как «дискорд» очень грубо говоря), где можно будет просто зарегаться + создать свое «сообщество»(бесплатно), а там будут текстовые чаты и голосовые комнаты и можно будет приглашать других пользователей и общаться там(прям к в дискорде…) + есть приложение под windows и PWA для мобилок.

Но мне кажется. Модераторы ЛОРа не одобрят, если я «прорекламирую» это решение…

romanlinux ★★★
() автор топика

стильно, модно, молодёжно

z0idator
()

Какие системные требования к серверу?

В чём отличие от Jitsi? И вообще, зачем оно может быть нужно, если Jitsi есть?

VladimirP ★★★★
()
Ответ на: комментарий от romanlinux

Жесть, вот что значит - писал профессионал, а не фермер. У тебя вообще все сделано правильно. Вообще все. 3к пользователей выдержит легко, пока не упрется в ограничения ОЗУ.

Мой первый проект выдерживал от силы 30-100. Кучи обращений к дискам, все на диске было. Хттп запросы всякие. А до того, что у тебя я додумался только вчера как раз за час до того, как меня сюда призвали. За год разработки, короче.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от VladimirP

Вот скрин neofetch

https://allwebs.ru/image/%D0%91%D0%B5%D0%B7-%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8.pB31n4

В чём отличие от Jitsi? И вообще, зачем оно может быть нужно, если Jitsi есть?

Ну грубо говоря в плане «технологий» по сути одно и тоже. Но чисто визуально Jitsi это скорее google meet, а мне хотелось как в дискорде, чтобы был список комнат и было видно кто в какой комнате сидит и одним нажатием «прыгать» по комнатам и общаться. без «генерации ссылки на комнату»

Так что отличие, только в UI/UX я бы сказал. Ну и + jitsi «чуть-чуть» более «заморочнее» поднимается, а я хотел, что-то из разряда: просто docker-compose up -d и все)

UPD1: вот тут тоже верно заметили xDDD VChat — простой видеочат на WebRTC (комментарий)

UPD2: кстати только что вспомнил) У меня еще была цель добавить горячие клавишы (глобально) + стрим экрана со звуком, а это джаваскрипту в браузерах запрещено. Поэтому я это все завернул в ElectronJS и теперь можно просто во время игры не сворачивая ее. Нажать на HotKey(вот тут на скрине они есть https://github.com/outZoNe/vchat/blob/main/docs/2.png или можно забиндить на другие клавишы) и сразу начнется демонстрация «активного окна», то есть игры. Прям как в Дискорде)

romanlinux ★★★
() автор топика
Последнее исправление: romanlinux (всего исправлений: 2)
Ответ на: комментарий от pihter

Думаю да. в целом для UI я использовал Chakra UI. И фронт полностью адаптивный. У меня на android 13 и у друзей на айфонах(хз какая там iOS). все работало и мы спокойно общались

romanlinux ★★★
() автор топика
Ответ на: комментарий от romanlinux

А например через tor будет работать (где только tcp, и естественно нет внешнего ip)? Там TURN сервер нужен будет, вроде как.
В bigbluebutton, например, такой мощный костыль сделали, чтобы запускать всё на одном сервере - TLS терминируется на haproxy, который смотрит первый байт (или alpn если есть), и переключает соответственно на nginx или coturn.
ЧСХ работает, хотя вообще архитектурно bbb очень кривое уёжище, как по мне

TheAnonymous ★★★★★
()
Ответ на: комментарий от TheAnonymous

А например через tor будет работать (где только tcp, и естественно нет внешнего ip)?

Ох я такое даже не проверял. Но если UDP там запрещен, то логично предположить, что не будет работать)

Сори но мне даже лень такую «фичу» делать. Я просто смирюсь, что в торе не будет работать xD

romanlinux ★★★
() автор топика
Ответ на: комментарий от romanlinux

Ну тор как пример.
Со всякими прочими модными туннелями, которые работают как локальный прокси, тоже вопрос есть.
Да и вообще STUN не через всякий симметричный NAT пролезет.

Хотя в большинстве случаев работать будет, да, в том же bbb «встроенный» turn-сервер включили только в версии 2.6, до этого его надо было отдельно ставить (на своём айпишнике) и настраивать, на что многие забивали, и в целом работало.

TheAnonymous ★★★★★
()
Ответ на: комментарий от romanlinux

Спер алгоритм маршрутов войса. Практически полностью. Но! Творчески переработал ИИшкой, а значит по правилам нового времени это совершенно новый код. Господи, так хорошо все это не работало еще никогда у меня. Столько классных идей. Где ж ты ранше то был. Я б еще год возился со всем этим.

Минус несколько тысяч строк кода… Так чисто стало. У меня были асинхронные проверки, взаимные блокировки. Работало все с вероятностью 80%.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от LightDiver

Работало все с вероятностью 80%.

Kак говорится, «Спасибо, улыбнуло!..» :))

Somebody ★★★★
()
Ответ на: комментарий от hakavlad

Ни чем)

Вот тут я уже отвечал

VChat — простой видеочат на WebRTC (комментарий)

Просто хотел UI/UX как в дискороде сделать. Чтобы был список комнат и было видно кто в какой комнате сидит.

А jitsi ИМХО скорее google meet, где нужно по ссылкам прыгать.

Из плюсов, только наверное «приложение» и тем самым поддержка хоткеев и т.п.

romanlinux ★★★
() автор топика
Ответ на: комментарий от romanlinux

Проблема в том, что на мышь хоткей не повесишь в твоей реализации. А пользователям надо, например, на боковые кнопки мышь, ибо удобное.

Я потыкался, поизучал и сделал свой модуль на раст. Делал, как и все, на коленке быстро, работает кривее некуда. Надо полностью переделать. Как раз обдумываю детали. Тут еще и кроссплатформенность опять добавляется - глобальные хоткеи в винде и линуксе это вообще разные вещи.

LightDiver ★★★★★
()
Ответ на: комментарий от LightDiver

Проблема в том, что на мышь хоткей не повесишь в твоей реализации

ооо спасибо) Я чота даже и не подумал про хоткеи на мышь. Вечерком займусь этим вопросом, если кайф будет)

Только у меня нет мыши с «кнопками». ХЗ как тестить :(

romanlinux ★★★
() автор топика
Последнее исправление: romanlinux (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.