Проект: Битва с чебурнетом, или Как я теперь созваниваюсь с женой  Публичный пост
9 октября 2026  109
Битва с чебурнетом, или Как я теперь созваниваюсь с женой
https://call.zhivem.global/how

Предыстория ⬇️

В силу обстоятельств мы с женой временно живем на две страны, и созваниваться с каждым днём все сложнее, вечно какие-то приколы.
В общем, я прожил мем наяву:
• мальчик: блин, наверное теперь общаться не получится...
• мужчина: написал свою звонилку

Время на MVP

Первая рабочая версия заняла один вечер. Но радоваться рано. За вечер я поднял сигналинг на ноде, открыл две вкладки, увидел себя в двух окошках и решил что всё готово, я гений и тд. Радовался где-то час. Потом попробовал позвонить с телефона.

Дальше было три месяца вечеров, и почти всё ушло не на фичи, а на то, чтобы оно работало у живых людей с живым интернетом:

  • Восстановление после обрывов
  • Удержание экрана на телефоне
  • Чат, который не теряет сообщения, когда связь моргнула
  • Панель диагностики, чтобы хоть понимать, что происходит

Сама звонилка реально была готова в первый вечер. Остальное уже борьба с реальностью.

Стек

Нода плюс вебсокет для сигналинга, чистый WebRTC на клиенте без фреймворков, Railway для хостинга, TURN от Cloudflare.

А, ну и с UI поигрался, чтобы не было вот этого "Собрал за час сайт на клоде, РАЗРАБОТЧИКИ ВСЁ".

На самом деле, архитектура совсем не rocket science. Думаю, интереснее рассказать, откуда зародились мысли сделать прям свое. Сначала пошёл по очевидному пути поднять self-hosted Jitsi. Docker-compose есть, инструкций полно, выглядит буквально как "развернул и забыл".

Развернул. Реально работает. Но только внутри локальной сети.

Оказалось, чтобы выпустить такое наружу, нужен открытый входящий UDP, Jitsi Videobridge живёт на нём. Railway во входящий UDP не умеет.

Пришлось посидеть и крепко подумать с командой:

Итоги брейншторма: SFU это сервер, который собирает потоки со всех участников и раздаёт остальным. Он нужен, когда участников трое и больше. А у нас два устройства. Для двоих есть P2P: браузеры соединяются напрямую, а сервер только знакомит их друг с другом и отходит в сторону.

После этого всё сложилось. Сигналинг это обычный вебсокет, то есть TCP, никакого UDP не надо. Медиа через сервер не идёт, значит хостинг стоит копейки.

НеЗапуск и первые пользователи

Формально ещё не запустился, утрясаю лигал вопросы. Не пойду в продажи, пока это не закрою.

А вот бета-тестеры нашлись забавно. Зашёл в тредс, увидел пост в духе "кто как сейчас общается с родственниками в РФ?" и оставил там коммент, рассказал про свою звонилку. Отдельно написал коротенький пост, что ищу пять добровольцев — пришло шесть человек. Пятеро пользуются, трое уже дали качественную обратку.

Подводные камни

Тут целый список, и почти ничего я не предвидел.

Звук

Opus настроен на речь, а не на музыку. Мы хотели не только болтать, но и смотреть что-то вместе через шаринг экрана. Картинка пошла нормально, а звук превратился в кашу.

Оказалось, WebRTC по умолчанию настраивает кодек под голос: моно, низкий битрейт, подавление эха, шумодав (спойлер — не работает, расскажу дальше). Лечится только правкой SDP руками: находишь строчку a=fmtp у нужного кодека и дописываешь туда стерео и битрейт.

Шумодав

Браузерный вариант показался мне слабоватым, и я притащил RNNoise. Это нейросетевой шумодав, который крутится прямо в браузере через wasm, звук никуда не уходит. Первая же проверка закончилась фразой от собседника: "я слышу, как ты печатаешь".

Предположил, что RNNoise умеет справляться с монотонным шумом по типу вентилятора, а щелчки клавиатуры это импульсный шум. Видимо, короткие и резкие звуки модель не трогает, потому что боится срезать голос.

Код остался в проекте, но висит фичефлагом до лучших времён.

Симметричный NAT

Пошёл тестировать по-настоящему: ноут по вайфаю, телефон на мобильном интернете. Соединение не собралось вообще. Так я узнал, что у операторов внешний порт для каждого получателя разный, и собеседник банально не знает куда стучаться. Прямого пути нет физически.

Всё с той же командой в лице клода и чашки кофе пошли раскуривать матчасть про ретрансляторы. Свой поднимать ну совсем не хотелось. Решение было найдено на Cloudflare — у них есть TURN-сервис, стоит пять центов за гигабайт, но перед этим они щедро насыпают терабайт бесплатно. Для двоих это что-то типа бесконечность и даже еще больше. В общем, приемлемо, забрал в проект.


Вот так выглядит панель диагностики в разных сценариях ⬆️

iOS в фоне

Вот это не обойти никак. Если страницу увести в фон, то система сама заглушит микрофон, и звонок обрывается.

Например, Zoom или Meet живут в фоне только потому, что это нативные приложения с VoIP-режимом и CallKit. Веб-странице такие права не дают. Частично спасает Screen Wake Lock: пока разговор открыт, телефон хотя бы не гаснет сам. Но стоит свернуть браузер или переключиться на другую вкладку — конец разговора.

Safari

Этот великий браузер на десктопе упорно не собирал внешние адреса, только локальные. И при этом я не видел ни одной ошибки в консоли.

На айфоне с той же конфигурацией работал нормально. Копать не стал, решил оно того не стоит.

Экономика

Потратил на домен и хостинг, суммы несерьёзные. Заработал ноль, продаж пока не было. Модель задумана простая: бесплатно двадцать минут в сутки, дальше подписка.

Стоимость поставил $7 в месяц или $59 в год, ну и лайфтайм за $119.
Экономика сходится сама собой из-за архитектуры. Медиа идёт мимо сервера, TURN бесплатный до терабайта, себестоимость пользователя почти нулевая. Великих потоковых объемов я не ожидаю.

Главная дыра не в цене, а в оплате. Человек заходит на сайт, видит продукт, но купить в два клика не может. Пока что разбираюсь с Merchant of Records совместно с юристом.

Планы на будущее

Первое и главное — нормальная оплата на сайте. Как написал чуть выше, смотрю в сторону Merchant of Records, чтобы не возиться с налогами в разных странах.

Потом хочу сделать отдельные страницы под конкретные вопросы вместо одностраничника. В SEO совсем не разбираюсь, изучаю методом тыка. Пока вот узнал, что Гугл ранжирует страницы, а не сайты. У меня ранжировать нечего.

Из продуктового хочется порешать историю со звонком в фоне на айфоне и закрыть вопрос с шумодавом. А, ещё шаринг экрана пока что тоже закрыт фичефлагом, но с ним хотя бы понятно что делать. Уделю 3-4 вечера и все будет супер.

Ищу помощь Клуба

Очень нужны советы!

  1. Кто-нибудь подключал Merchant of Records на грузинское ИП? Интересует именно верификация, бенефициар с российским паспортом, но с грузинским внж. Если есть живой опыт с Paddle, Polar, Creem или кем-то похожим — очень пригодится.

  2. Может, кто сталкивался с тем, что сафари на макоси вообще не собирает ICE-кандидаты? Я сдался, но любопытство осталось.

Совет от меня напоследок

Не тащите SFU, если вас двое. Я потерял на этом неделю, а в итоге этот космический корабль оказался не нужен.
Для тестов собирайте нормальную связку: ноут по вайфаю, телефон через мобильный интернет. Всё интересное живёт там. Локальный тест вам ничего не покажет, он просто сделает вид, что всё хорошо.

Откомментируйте первым 👇

😎

Автор поста открыл его для большого интернета, но комментирование и движухи доступны только участникам Клуба

Что вообще здесь происходит?


Войти  или  Вступить в Клуб