В предыдущей части я привел ретроспективу эволюции своего подхода к созданию домашней системы видеонаблюдения. Финальным результатом этой эволюции стала идея создания собственного протокола для передачи видео потоков на основе WebRTC. О технических деталях этого протокола я и попытаюсь рассказать в этой части.

Что из себя представляет WebRTC?

WebRTC - это протокол предназначенный для передачи данных между двумя произвольными устройствами как в локальной сети так и через интернет. В качестве данных могут выступать видео/потоки либо данные приложений.

Ключевые особенности протокола:

  1. Минимальная задержка от момента захвата видео/аудио на стороне отправителя до момента их воспроизведения на стороне получателя (от ста миллисекунд)

  2. Шифрование всех передаваемых данных

  3. Встроенные средства обхода NAT

На данный момент существует несколько реализаций протокола реализованных на разных языках программирования. Большинство реализаций являются Open Source. Ниже приведены только некоторые из них:

  1. Библиотека WebRTC.org. Считается эталонной реализацией. Разрабатывается компанией Google и используется в браузерах Chrome, Chromium и прочих на их основе (например Microsoft Edge). Основной язык реализации - C++. Как часть проекта разрабатываются адаптеры для языков Java (Kotlin) и Objective C (Swift), что позволяет использовать эту библиотеку в приложениях для платформ Android и iOs

  2. Элемент webrtcbin из библиотеки GStreamer. Язык реализации - C

  3. Библиотека Pion. Язык реализации - Go

  4. Библиотека Mediasoup. Языки реализации - C++, Rust

  5. Janus Gateway (Janus WebRTC Server). Язык реализации - C

  6. Jitsi Videobridge и Jitsi Meet. Язык реализации - Java

Ключевой особенностью большинства реализаций является практически гарантированная совместимость между ними на уровне протокола.

Как устроен WebRTC простыми словами

Как было указано выше, WebRTC протокол предназначен для осуществления взаимодействия между произвольными устройствами. А значит заранее невозможно предсказать какими именно возможностями обладает каждое из устройств. В первую очередь речь идет о поддерживаемых каждой из сторон кодеков для кодирования звука и видео. Для решения этой проблемы WebRTC предлагает механизм согласования возможностей и потребностей между сторонами, для нахождения варианта устраивающего обе стороны. Как это происходит: одна из сторон создает так называемый offer в котором описывает что она умеет и что хотела бы получать, передает offer другой стороне, которая в свою очередь на основе этого offer создает answer в котором указывает что именно из offer может предоставить и в каком формате. Что же именно согласовывается:

  1. Какой набор потоков каждая из сторон желает отправлять и получать. Потенциально это может быть набор из произвольного количества видео/аудио потоков и потоков данных. Например, одна из сторон может желать отправлять видео и аудио, а получать только данные (или вообще ничего не получать)

  2. В каком виде стороны могут отправлять и получать видео/аудио. Здесь речь идет в первую очередь о поддерживаемых кодеках и дополнительных параметрах кодирования звука и видео

Хорошо, возможности согласовали. Осталось согласовать каким именно образом передавать данные, т.е. вопросы сетевого взаимодействия между устройствами. Проблема в том что устройства могут располагаться в произвольном месте сети, и заранее невозможно предсказать каким именно способом возможно осуществлять передачу данных. Для этого WebRTC предлагает механизм ICE Negotiation. Описать его можно достаточно просто: каждая из сторон собирает информацию о том какими способами к ней можно подключиться и передает эту информацию другой стороне (физически информация о возможных каналах для подключения передается между участниками в виде ICE Candidates). На основе этой информации обе стороны пытаются подключиться друг к другу, перебирая все возможные варианты.

Зачем такие сложности? - если не учитывать различные крайние случаи, то возможных вариантов 3 и все их нужно отработать:

  1. Оба устройства находятся в прямой видимости. Например в одном сегменте локальной сети или в разных сегментах но с настроенным роутингом (правила передачи IP пакетов между сетями). Это самый простой вариант - обе стороны могут просто подключится друг к другу без каких либо проблем (но даже в этом случае есть нюансы, но я их опущу для простоты изложения)

  2. Одно из устройств находится за NAT (т.е. за роутером, например в домашней локальной сети). Это исключает возможность прямого подключения к нему из интернета. А значит нужно применять разные хитрости вроде hole punching для создания двухстороннего канала между устройствами. Если упрощенно, то устройство находящееся за NAT отправляя пакет данных (в случае UDP) на некий IP адрес, или создав соединение (в случае TCP), что дает противоположной стороне возможность отвечать. В данной схеме, помимо второго участника, практически всегда участвует STUN сервер, но что это такое и зачем оно нужно я пропущу для простоты повествования

  3. Оба устройства находятся за NAT. Самый сложный случай. Ни одно из устройств не имеет никаких возможностей подключится к другому. Обе стороны не обладают реальными IP адресами к которым можно подключаться. И использовать hole punching возможности тоже нет - для этого нужно послать хоть один пакет другой стороне. А значит без помощи извне не обойтись. В этом случае на сцену выходит TURN сервер. В этом сценарии он начинает выступать в роли ретранслятора, к которому у обоих устройств есть возможность подключиться и начать передавать и получать через него данные с другого устройства

А как взаимодействовать устройствам до того как создано WebRTC подключение?

В тексте выше, неоднократно упоминается необходимость передачи различной информации между устройствами еще на этапе согласования WebRTC подключения. А собственно как? Если канала взаимодействия между устройствами еще не существует, да и создать его, как выяснилось, может быть не так просто. А здесь начинается самое интересное. Этот вопрос абсолютно никак не регламентируется в рамках WebRTC. Предполагается что в каждом конкретном случае разработчик приложения решает этот вопрос самостоятельно. Поскольку изначально WebRTC разрабатывался как протокол для браузеров то типичным решением является взаимодействие устройств (в данном конкретном случае браузеров) через некий API сервер доступный всем потенциальным участникам взаимодействия. Собственно через него и осуществляется все взаимодействие. Но в этом подходе есть существенный момент - каждый вынужден создавать свой собственных протокол для согласования WebRTC подключения. Обычно это не является особо критической проблемой, но тем не менее. В моем случае встал антологичный вопрос, и мне пришлось изобрести очередной велосипед - здравствуй WebRTSP!

WebRTSP

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

  1. Протокол должен быть относительно простым

  2. Иметь возможность работать через браузер

  3. Быть двухсторонним

  4. Быть не сильно ужасным с прицелом на использование не только мной и не только в данном конкретном проекте

На самом деле исходный вопрос в конечном итоге распадается на 2:

  1. Какой канал использовать между клиентским устройством и сервером?

  2. Какой формат использовать для самих сообщений?

Вариантов для первого вопроса не так уж и много: HTTP и WebSockets. Через HTTP конечно можно реализовать двухстороннее взаимодействие, но ознакомление с возможными вариантами создало у меня стойкое ощущение "костыля". В итоге я выбрал WebSockets. В первую очередь, поскольку этот протокол изначально создан для двухстороннего взаимодействия. А во вторую, поскольку библиотеку, его реализующую, в наше время найти не проблема практически для любого языка/платформы.

Осталось решить с форматом сообщений. В этом тоже думать долго не пришлось, почему бы не взять RTSP за основу и не адаптировать его к моему случаю? Благо финальная задача практически идентична области применения RTSP. Так и сделал. Дальнейшая разработка показала что выбор был вполне оправдан. Пришлось конечно внести некоторые изменения в логику RTSP протокола для адаптации к особенностям WebRTC, но в итоге получилось нечто что даже работает ? Что доступно на данный момент: C++ реализация для клиента и сервера, TypeScript реализация для браузерного клиента, Proof-of-Concept реализация React компонентов, Proof-of-Concept клиента на Kotlin и Swift. Кроме того, реализованы и опубликованы в Snapcraft Store несколько приложений основанных на данной технологии. О использовании последних я и расскажу в следующей части.

Продолжение следует...

Комментарии (6)


  1. azzas
    04.01.2026 15:02

    Так ты ж нифига не запилил.

    Ох уж эти "статьи" без контента, растянутые в сериал.


    1. Viktor-T
      04.01.2026 15:02

      Это как? В конце статьи же ссылки. Да и в прошлой статье в комментах были ссылки на Snap.


      1. RSATom Автор
        04.01.2026 15:02

        "Не кормите тролля..."


      1. Markoovv
        04.01.2026 15:02

        Ссылки ссылками, человеку надо на блюдечке пронести. А так проект интересный, буду следить


  1. tklim
    04.01.2026 15:02

    А зачем это все? В самом простом случае, ВПН. Другие способы тоже в наличии. Если проблема в двух натах все равно не обойтись без внешнего сервера

    Ну и самое главное, смотреть поток с камеры в реальном времени - зачем? Чаще всего надо посмотреть запись по событию или просто за какой-то промежуток времени


  1. tarantula58910
    04.01.2026 15:02

    до лета 2025 ISS раздавал бесплатную версию SecurOS Lite (если поискать еще можно найти).
    подойдет как комбайн для начинающих.
    ограничения: не больше 32 камер и микрофонов, не больше 1 сервера,
    не больше 2 толстых спец.клиентов (web-клиенты и web-сервер работают отвратительно),
    сервер и клиенты только Windows. по-моему для разумных применений хватит.

    если хочется велосипедить с linux, web, без гамака и без лыж: https://github.com/Motion-Project/motion

    если хочется велосипедить с пихтоном, тензорфлоу и т.д. - очевидно frigate.

    все это без облачных хранилищ, на данных из которых чужие люди будут обучать свои нейросети,
    а вам за это даже не заплатят.

    ps: видеонаблюдение в туалетах, душевых и примерочных кабинках ведется для Вашей безопастности.