Началась эта история чуть менее 10 лет назад, и началась она с того, что однажды мне пришла в голову идея, что было бы неплохо иметь возможность наблюдать за квартирой, пока находишься в длительных отъездах, например в отпуске. Тогда задача виделась достаточно тривиальной, но в итоге растянулась на долгие годы. Ниже я постараюсь рассказать о всех этапах что я прошел на пути к текущему (и не факт, что финальному) решению.
Итерация первая, IP камеры будет достаточно
Самое первое и самое очевидное что нужно было сделать - приобрести IP камеру. Уже тогда было понимание что использование аналоговой камеры будет неправильным решением, поскольку требует дополнительного, и достаточно громоздкого, оборудования. В случае же IP камеры, было предположение что ее одной будет достаточно. Ну что ж, иду в ближайший магазин и приобретаю практически первое что попадается под руку и стоит вменяемых денег. Приношу домой, подключаю, настраиваю - и приходит озарение: в той же самой локальной сети получить доступ к видео потоку не проблема, а как-же получить к нему доступ извне? Открывать порты и открывать потенциально дырявое устройство всему миру? - бред, ибо как раз в то время шумел по всему миру ботнет Mirai. Да и заставлять конечного пользователя лезть в настройки роутера - очень неправильный (и потенциально опасный) подход. А значит нужен некий дополнительный элемент для обеспечения доступа извне к камере внутри закрытой сети ?
Итерация вторая, патчу GStreamer RTSP server
Ну что ж, надо, значит надо. Приобретенная камера поддерживает доступ по протоколу RTSP, а это весьма популярный протокол, и как следствие, имеет смысл строить решение вокруг него. И первое что приходит в голову, после ознакомления с RTSP протоколом - мне нужен некий сервер для размещения где-нибудь в облаке, и умеющий с одной стороны получать видео поток с камеры, а с другой выдавать этот же поток пользователю. Но здесь снова возникает вопрос, открывать порты очень плохая идея, а значит в локальной сети нужен некий активный агент, который, с одной стороны, будет подключаться к камере и получать видео поток с камеры, а с другой, посылать этот же поток на сервер ? Изобретать свой протокол для общения между сервером и агентом сильно не хочется, а значит смотрим внимательно на описание RTSP протокола и пытаемся найти решение. После внимательного изучения я наткнулся на упоминание RTSP команды RECORD. Что же она дает? - а как раз то что мне нужно, возможность с клиентского устройства посылать видео поток на сервер! А RTSP оказался гораздо мощнее чем я привык о нем думать!
Ну допустим, а что с сервером то? Неужели самому писать? - похоже на то ? Никаких готовых решений на тот момент я не нашел, может плохо искал, а может и не особо хотел найти (был азарт "запилить велосипед", я-ж программист!). Хорошо, значит нужно искать хоть что-то, что позволило бы не реализовывать свой RTSP сервер с нуля (что с большой долей вероятности отодвинуло бы сроки завершения проекта в бесконечность). Поскольку к тому моменту у меня уже был некоторый опыт работы с GStreamer, первое что я сделал - проверил, нет ли чего готового к использованию там? Оказалось есть! Не в самом GStreamer, но в библиотеке поддерживаемой той-же командой - GStreamer RTSP Server. Удача! Второй удачей оказалась наличие поддержки RECORD в этой библиотеке. Но обнаружилась и ложка дегтя - текущая реализация не позволяет перенаправлять видео полученное по RECORD другим клиентам ? Значит придется делать то чего сильно не хотелось - патчить GStreamer RTSP Server для добавления нужного мне функционала. Долго ли коротко ли, но мне удалось это сделать! И оно даже работало ? Но беда пришла откуда не ждали - пока я ковырялся с реализацией новой логики, вышла новая версия библиотеки ? Попытка сделать git rebase на master бранч (а это обязательное условия для возможной последующей подготовки патча для отправки в основной репозиторий) показала что в основном проекте произошли существенные изменения, и обойтись механической подгонкой моих изменений не получается. Пришло понимание, что если я буду двигаться этим же путем, то ситуация с большой долей вероятности повторится, а значит нужно искать другое решение ?
Итерация третья, не патчу GStreamer RTSP server, но использую gst-interpipe
Эх, ну что ж... Пытаюсь найти решение позволяющее передавать видео потоки между GStreamer пайплайнами (pipeline - это собранная и настроеная цепочка из нескольких GStreamer элементов для обработки видео или аудио потоков). Такой подход позволил бы мне совсем не менять GStreamer RTSP Server и выполнить реализацию полностью на уровне моего приложения. Некоторое количество поисков в интернете привело меня к библиотеке под названием gst-interpipe от RidgeRun - она предназначена как раз для решения упомянутой выше проблемы. Отлично, пишу соответствующий код и в конечном итоге получаю нечто что даже работает ?
Так, часть вопросов решена. Но есть нюанс, в текущей реализации возможен доступ к видео потоку извне в произвольный момент времени только если сервер получает видео поток со стороны агента 24*7, т.е. даже если нет ни одного клиента. Жуткий расход сетевого трафика в пустую. Плохо, очень плохо! ? А значит нужен некий канал для общения между сервером и агентом, для извещения последнего о подключении клиента.
Эх... Беру asio, Google protobuf и добавляю недостающий функционал. Долго ли, коротко ли, но в итоге получается очередное нечто что даже работает?
Отлично, остался последний вопрос - а смотреть то как? В текущей реализации везде RTSP, соответственно браузер не может быть использован в качестве клиента (NPAPI интерфейс уже благополучно похоронен к этому времени). Можно конечно использовать любой медиа проигрыватель типа VLC, но UX (user experience) такого подхода просто ужасен. И даже это не все проблемы. В конечном итоге мне гарантировано понадобится механизм аутентификации для предотвращения доступа к личным видео потокам со стороны посторонних, а RTSP протокол не поддерживает шифрования. Существует конечно модификация протокола с поддержкой шифрования - RTSPS, но он очень мало распространен, да и вопрос с поддержкой браузеров как основного инструмента потребления контента остается нерешенным ?
Итерация четвертая, мне нужен WebRTC!
Так как же мне получить возможность использовать в качестве клиента браузер? Смотрю на список поддерживаемых браузерами протоколов и понимаю что самым адекватным вариантом является WebRTC:
1. Поддерживается всеми современными браузерами
2. Изначально решен вопрос обхода NAT
3. Шифрует видео потоки по умолчанию
4. Имеет минимальную задержку (latency)
Ну допустим, а как же преобразовать RTSP в WebRTC? Долгие поиски решения привели меня к Open Source проекту под названием Janus Gateway (ныне Janus WebRTC Server). Почему именно он? - во-первых, он написан на языке C (не возникнет лишних сложностей при необходимости его модификации), во-вторых, стандартная поставка содержит streaming плагин помимо прочего умеющий транслировать видео поток IP камеры в браузер. Отлично, провожу некоторое количество экспериментов с ним и выясняю дополнительный положительный момент - streaming плагин не делает абсолютно никакого перекодирования видео потока при его отправке в браузер (что сильно снижает требования к оборудованию), все что необходимо - это поддержка камерой h264 кодека для кодирования видео (на самом деле h264 baseline profile, но плагин делает кой-какой трюк, благодаря которому браузер начинает понимать не только baseline profile).
Ну что ж, отлично, лезу в исходники streaming plugin и понимаю что все не так радужно. Во-первых, streaming плагин требует прямого доступа к RTSP источнику (здравствуй port forwarding на роутере). Во-вторых, плагин использует бесконечное воспроизведение даже если нет ни одного просматривающего клиента (здравствуй расход трафика в пустую). Значит придется опять писать код. Поскольку GStreamer показал себя как весьма гибкий инструмент, принимаю решение интегрировать его с Janus. Долго ли, коротко ли, но в итоге получается очередное нечто что даже работает?
И тут приходит очередная новость - в GStreamer добавляют поддержку протокола WebRTC... Да сколько можно то! Снова все переделывать!
Итерация пятая, мне нужен свой протокол!
Так чем-же меня не устраивал Janus? Причин несколько:
1. Использовать полноценный сервер рассчитанный на сотни (а то и тысячи) одновременных подключений там где будет от силы пара - это явное "из пушки по воробьям"
2. Janus - это отдельный процесс, управление которым добавит дополнительных сложностей в конечное приложение, а в данном конкретном случае смысла в этом нет абсолютно никакого, т.к. в рамках монолита реализовать логику однозначно проще, а с учетом предполагаемого количества клиентов (даже если это будут десятки) задумываться о горизонтальном масштабировании смысла нет никакого, достаточно вертикального.
Итак, принимаю решение о реализации очередного велосипеда использующего WebRTC в качестве протокола передачи видео и webrtcbin из GStreamer в качестве конкретной его реализации. Но есть нюанс, если сравнивать WebRTC с RTSP можно увидеть явное концептуальное отличие: в описании WebRTC нет никакой конкретики касающейся способа передачи информационных сообщений между участниками. В RTSP для этого есть явно определенный стандартом набор команд, а WebRTC описывает исключительно вопросы касающиеся передачи собственно видео/аудио/данных. Реализация механизма обмена сообщений для всех вопросов согласования отдается на откуп конкретному приложению. А значит мне нужен свой протокол для обмена сообщениями. Но зачем изобретать очередной велосипед? Почему бы не взять за основу то что себя уже давно зарекомендовало? А именно набор команд из RTSP и создать на их основе реализацию адаптированную для использования с WebRTC? То что в итоге получилось я недолго думая назвал WebRTSP (как объединение RTSP и WebRTC) и как оно конкретно выглядит я расскажу в следующей части.
Продолжение следует...
Комментарии (24)

leongurman
03.01.2026 08:52Agent DVR https://www.ispyconnect.com/docs/agent/about
хочешь сервисом, хочешь демоном, хочешь контейнером. все локально. WireGuard в соседнем контейнере решает проблему с удаленным доступом. в плюсах - интеграция с HA.

byte-coder
03.01.2026 08:52Что-то как-то все замутно у вас получается... Не, ну может я что-то не понимаю, но все же мне кажется есть более простые решения и ничего патчить не нужно)) Короче, решение такое: ставите какой-нибудь сервер видеонаблюдения, у меня, вот например, сейчас стоит Shinobi, а вообще я пробовал разные сервера, MotionEye, ZoneMinder и еще какие-то уже не помню, но не суть... Поставили сервер видеонаблюдения и поставили сервер WireGuard - — протокол виртуальной частной сети ... например, настраиваете сервер на 10.0.0.1, а клиентов на 10.0.0.2,3,4... и так далее. Никаких портов не надо пробрасывать, все работает внутри этой сети и все шифруется от посторонних глаз)) Все легко и просто)) У меня даже есть две камеры на моей усадьбе, которая находится в глуши непросветной, там глушь, лес, болота и речка с медведями, а на дереве скрытая антенна, которая ловит мобильную сеть, а в контейнере Репка Пи стоит, и все работает как часы. Ничего патчить не надо)) Не ну может у вас какая-то цель своя или путь самурая, я может не уловил из статьи, но я уловил, что вы там порты боитесь пробрасывать, так вот там не надо.. ВайрГард ставите на какой-нибудь ВПС дешевый за 75 рублей в месяц и в ус не дуете))) как я)))

aborouhin
03.01.2026 08:52+1. Загоняем все камеры в один VLAN, даём доступ к этому VLAN только серверу видеонаблюдения, ну а как уже внешний доступ к этому серверу открыть - ну так же, как и к остальной домашней сети. У меня только через VPN, но можно и обратный прокси в DMZ поставить.
В копилку вариантов софта добавлю ещё Frigate. У меня долгое время стоял ZoneMinder, но потом на Frigate перешёл, там всё гораздо современнее выглядит и очевиднее настраивается.

RSATom Автор
03.01.2026 08:52Проблема в том что настройка WireGuard (или подобных) предполагает чуть более высокую квалификацию чем настройка агента работающего в локальной сети.
Опять же, в финальном варианте ничего патчить уже не нужно - есть готовый набор приложений для которых нужно только настроить конфиги. История про патчинг - всего лишь ретроспектива решений которые были рассмотрены исторически.
leongurman
03.01.2026 08:52настройка WireGuard (или подобных) предполагает чуть более высокую квалификацию
нет. можно использовать https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy

andreymal
03.01.2026 08:52А не смотрели MediaMTX? Судя по описанию, он умеет примерно всё упомянутое

RSATom Автор
03.01.2026 08:52Возможно я ошибаюсь, но я не вижу у MediaMTX возможности работы в режиме агента. Т.е. когда нечто работает за NAT и подключается к серверу в облаке (VPS). В противном случае проблема с необходимостью открытия портов на роутере никуда не девается.

andreymal
03.01.2026 08:52Кажется, в роли такого агента может быть банальный ffmpeg (да и gstreamer наверно тоже)

RSATom Автор
03.01.2026 08:52Да, может. Но как быть с расходом трафика когда нет ни одного активного клиента?

andreymal
03.01.2026 08:52А, я не обратил внимания, что для вашего юзкейса это проблема
Лично я наоборот делаю круглосуточную запись, чтобы по записям можно было потом какие-нибудь инциденты разбирать

RSATom Автор
03.01.2026 08:52А вы пробовали просматривать записи за несколько дней с целью поиска некоторого кратковременного события? - очень неблагодарное занятие. В связи с чем запись по движению считаю более предпочтительным подходом...

andreymal
03.01.2026 08:52Пробовал, мне норм, но видимо у меня юзкейс всё-таки другой, я от записи по движению наоборот специально отказался

RSATom Автор
03.01.2026 08:52Вполне допускаю разные требования в разных случаях. Если вам так удобней или предпочтительней по некоторой причине - почему бы и нет?

aborouhin
03.01.2026 08:52Это во Frigate очень удобно реализовано, кстати. Сбоку временная шкала в виде осцилограммы, обозначающей интенсивность движения в каждый момент времени. Т.е. сразу видно, когда что-то происходило и куда нужно прокрутить.
От распознавания движения отказался - в тупом режиме даёт кучу ложных срабатываний (привет снегу, каплям дождя, мошкам/паукам), а AI (у того же Frigate основная фишка) железо пока не тянет, надо или перенести видеонаблюдение с древнего сервера на менее древний, или Coral TPU купить.

PwrUsr
03.01.2026 08:52мне это кажется не очень надежным, лучше иметь запись и до движения (особенно если оно было очень быстрое), а вот метки движения нужны...

RSATom Автор
03.01.2026 08:52Я думаю технически это возможно отправлять на сервер запись с включенным некоторым количеством времени до события движения.

DarkTiger
03.01.2026 08:52Я игрался с вот этим, и оно даже заработало. А уж как прокинуть что-то защищенное из нужной локации до малинки - миллион и один вариант.
https://habr.com/ru/articles/208058/
Хватило меня на год, после чего решил, что я устал и пусть из моего видеонаблюдения сделают ботнет, или кому-то позарез понадобится видео бродячих котов у меня на даче зимой (кстати, один раз звонила соседка по даче, не видал ли я ейного кошака, и была очень обрадована, узнав, что вчера его видеокамера отдетектила, живой, значит - а то пропал неделю назад).
Купил IMOU 2 c двумя камерами, одна поворотная, и доволен как слон.
А летом я наблюдение отключаю, конечно, ибо действительно не фиг. Ну как отключаю... блокирую этот порт на роутере
Intercoms
03.01.2026 08:52С IMOU не решена проблема БЕСПЛАТНОЙ удаленной записи. Запись возможна только на карту внутри камеры. Но с точки зрения надёжности/временных затрат готовые облачные решения от Хиквизион/Дахуа и ещё парочки некоторых (которые взламываются на раз-два) все остальное реально изобретение велосипеда.

Intercoms
03.01.2026 08:52Как вариант SDK Hikvision есть в свободном доступе, можно и самому написать для себя сервер для записи с камер, и не только по RTSP. Если так чешутся руки, то лучше работать с тем что будет работать гарантированно.
wl2776
С нетерпением жду продолжения, т.к. есть желание сделать такое на даче.
Рассматривались ли всякие сторонние облачные решения типа ivideon, ipeye и прочих похожих?
RSATom Автор
Честно говоря нет, не рассматривал. Причин несколько: 1. Жаба. Большинство сервисов с возможностью хранения архивов платные, и пусть оно стоит смешных денег, но тем не менее. 2. Как я уже писал в статье, мне очень сильно не хотелось открывать порты для доступа к камере, а сервис с поддержкой агента для запуска внутри локальной сети появился позже (к сожалению забыл его название) 3. Мне очень сильно не хотелось отдавать персональные видео на сторону, поскольку я не мог предсказать кто именно может получить к ним доступ, тем более что идея была ставить камеру внутри квартиры.
RSATom Автор
Кстати, если хочется "здесь и сейчас", особых проблем нет. Все ПО опубликовано в Snapcraft Store и при наличии базовых навыков работы с линуксовой консолью может быть настроено самостоятельно. Следующие части я в любом случае напишу, но они будут больше ориентированы на техническую составляющую проекта. Прикладную часть я планирую описать в последней(предварительно третьей) части.
OFrol
Лично у меня для таких целей отлично работает связка Frigate и TPU-модуль Google Coral для ускорения распознавания (если точнее, то G650-04527-01).
Так же в параллель функционирует видеорегистратор от Dahua вместе с их бесплатным сервисом для доступа к данным этого видеорегистратора через облако: в самом облаке ничего не хранится, они только делают проксирование, чтобы не был нужен реальный IP.
Оба регистратора стоят у меня дома, а камеры в разных местах и связано всё через VPN. Благо внутри РФ wireguard работает без проблем.
Если сравнивать, то Frigate гораздо гибче и в нём лучше работает распознавание, но и Dahua неплох если нужно чтобы оно просто работало. Хотя в Dahua с настройками тоже придётся поразбираться - логика настроек там весьма извращённая
Intercoms
Первое нормальное решение. Ещё можно и Hikvision использовать. А что до логики настройки Дахуа - это дело привычки. А то у меня глаза полезли от наблюдения за мучениями автора.