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

Забавно, но именно эти профессиональные навыки неожиданно пригодились мне при строительстве собственного умного дома.

Содержание

Глава 1. Камеры вроде есть а вроде нет. Или история одного инженерного расследования.

Все началось в 2025 году, когда я занялся ремонтом новой квартиры.

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

Поэтому еще на этапе ремонта я решил не покупать отдельные "умные" устройства, живущие каждое в своем приложении, а построить единую экосистему. После изучения различных платформ выбор оказался очевидным – Home Assistant. Причина была очень простой. Мне хотелось самостоятельно выбирать оборудование, а не выбирать производителя. Сегодня это может быть кондиционер одного бренда, завтра робот-пылесос другого, послезавтра какой-нибудь DIY-проект на ESPHome. Home Assistant позволяет объединить всё это в единую систему и автоматизировать практически любые процессы. Именно эта свобода и стала решающим фактором.

За несколько месяцев квартира постепенно превратилась в настоящий полигон для автоматизации. Сегодня Home Assistant управляет:

  • освещением;

  • теплыми полами;

  • кондиционерами;

  • бойлером;

  • роботом-пылесосом;

  • системой защиты от протечек;

  • вентиляцией;

  • шторами;

  • чайником;

  • мультиваркой;

  • телевизором;

  • Яндекс Станциями;

  • дверным звонком;

  • шлагбаумом подземного паркинга;

  • и многими другими устройствами.

И панель управления умным домом на стене, которая ещё выступает как видеодомофон. 

Практически каждое из них удалось интегрировать относительно просто. Кроме одного...

Камеры, которые существуют... но только на сайте обслуживающей организации

Практически во всех современных жилых комплексах уже установлены камеры видеонаблюдения. Мой ЖК не стал исключением. Подъезды, двор, детские площадки, парковка, лифтовые холлы - камер оказалось более чем достаточно. На первый взгляд всё выглядело идеально: есть личный кабинет, есть просмотр онлайн. Но была одна маленькая проблема.

Для Home Assistant этих камер просто не существовало. Никакого RTSP. Никакого ONVIF. Никакого API. Никакой документации. Фактически камеры были полностью заперты внутри веб-интерфейса сайта управляющей компании.

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

Например:

  • автоматически открывать нужную камеру при звонке в дверь;

  • открывать шлагбаум, когда автомобиль подъезжает к нему;

  • сохранять собственный архив независимо от управляющей компании;

  • использовать детекцию движения;

  • распознавать людей и автомобили;

  • запускать любые автоматизации Home Assistant на основе событий с камер.

Именно тогда появилась мысль: если видео воспроизводится в браузере, значит браузер каким-то образом получает видеопоток. Вопрос заключался лишь в одном. Каким именно?

Как специалист по кибербезопасности, первое, что я сделал, – открыл инструменты разработчика браузера. Честно говоря, я рассчитывал увидеть один из привычных вариантов.

  • Либо RTSP.

  • Либо WebRTC.

  • Либо WebSocket.

  • Либо хотя бы какое-нибудь API, которое возвращает ссылку на поток.

Но действительность оказалась намного интереснее.

Вместо привычной схемы практически вся система видеонаблюдения представляла собой обычный iframe, встроенный в страницу личного кабинета. Сам iframe указывал уже не на сайт управляющей компании, а на совершенно другой сервис.

RTSP.RU.

Именно в этот момент стало понятно, что настоящее расследование только начинается. Если видеопоток уже существует внутри RTSP.RU, значит остается понять лишь две вещи:

  • каким образом сервис получает ссылку на поток;

  • можно ли использовать этот поток вне браузера.

Я тогда еще не подозревал, что ответ на этот вопрос приведет меня к исследованию структуры HLS-потоков, динамических токенов, API go2rtc и, в конечном итоге, позволит превратить обычный облачный сервис видеонаблюдения в полноценные локальные RTSP-камеры с собственным архивом, видеоаналитикой и интеграцией в Home Assistant.

Именно с этого момента обычная задача по подключению камер неожиданно превратилась в небольшое инженерное расследование.

Глава 2. Первые следы. Что на самом деле происходит при просмотре камеры?

После того как стало понятно, что управляющая компания использует сервис RTSP.RU, захотелось ответить на один простой вопрос.

Каким образом браузер вообще получает изображение с камеры?

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

  • RTSP;

  • WebRTC;

  • MJPEG;

  • HLS;

  • WebSocket с собственной реализацией передачи видео.

Я открыл инструменты разработчика браузера (Chrome DevTools) и начал наблюдать, что происходит в момент открытия страницы с видеонаблюдением. Обычно именно здесь можно довольно быстро понять архитектуру любого веб-сервиса.

Первое разочарование

Честно говоря, я ожидал увидеть что-то вроде этого.

rtsp://...

или

wss://...

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

Но ничего подобного не было. Вместо этого практически вся страница состояла из обычного iframe.

И выглядел он примерно так.

<iframe
width="640"
height="480"
src="https://rtsp.me/embed/KPbwo57M/"
frameborder="0"
allowfullscreen>
</iframe>

На первый взгляд ничего необычного. Но именно эта строка оказалась самым важным элементом всей системы.

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

KPbwo57M

На тот момент я еще не понимал, что именно означает эта последовательность символов. Но было очевидно одно: именно она определяет, какую камеру необходимо показать пользователю. Это уже было интересно. Получается, что сайт управляющей компании практически ничего не знает о видеопотоке. Он просто вставляет iframe с определенным идентификатором камеры. А дальше всю работу берет на себя RTSP.RU.

Что находится внутри iframe?

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

Я открыл содержимое страницы iframe и снова включил вкладку Network. На этот раз картина оказалась намного интереснее.

Практически сразу браузер начал загружать файлы с расширением:

.m3u8

Именно в этот момент стало понятно, что сервис использует HLS (HTTP Live Streaming).

Это сразу многое объяснило. Во-первых, HLS идеально подходит для просмотра видео через браузер. Во-вторых, большинство мобильных приложений тоже прекрасно умеют работать с таким форматом.

Но появилась новая проблема: Home Assistant напрямую с такими потоками работает далеко не так удобно, как с обычным RTSP. Особенно если речь идет о дальнейшей интеграции с Frigate.

Вот она – ссылка на видеопоток

Через несколько секунд в списке сетевых запросов появилась ссылка примерно такого вида.

https://msk.rtsp.me/
hNn2ldTc7s0SvyG6dWBO4Q/
1776155468/
hls/
qDVeNFd8.m3u8

В этот момент появилось ощущение, что задача практически решена. Нужно лишь скопировать ссылку. Добавить ее в Home Assistant. И наслаждаться результатом. К сожалению, все оказалось немного сложнее.

Самая неприятная особенность

Я открыл поток через VLC. Видео прекрасно воспроизводилось. Прошло несколько минут. Все работало. Еще несколько минут... И вдруг поток просто перестал открываться.

Сначала я решил, что виноват интернет. Потом подумал на браузер. Потом на VLC. Но спустя несколько экспериментов стало понятно - причина совершенно в другом.

Каждая ссылка жила всего около десяти минут. После этого RTSP.RU генерировал новую. Старый URL переставал существовать.

То есть происходило примерно следующее.

10:00
https://msk.rtsp.me/
A1B2C3/
1776155000/
hls/
XXXX.m3u8

Через десять минут.

10:10
https://msk.rtsp.me/
F9K8L7/
1776155600/
hls/
XXXX.m3u8

Для браузера это не проблема. Он просто получает новую ссылку автоматически. Пользователь этого даже не замечает. А вот для Home Assistant это настоящая катастрофа. Любая интеграция ожидала увидеть один постоянный RTSP-адрес, а не URL, который исчезает каждые несколько минут.

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

Наблюдение инженера

В этот момент я поймал себя на интересной мысли. Практически все попытки интеграции подобных сервисов в интернете строятся вокруг поиска "правильной ссылки". Но сама постановка задачи неверная.

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

Но оставалось еще несколько вопросов. Из чего вообще состоит эта загадочная ссылка? Почему меняется только часть символов? Что означает длинная последовательность после имени сервера? Почему один параметр меняется каждые десять минут, а другой – никогда?

Ответы на эти вопросы оказались намного интереснее, чем можно было ожидать.

Глава 3. Reverse Engineering RTSP.RU. Что скрывается внутри ссылки на видеопоток?

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

Что именно меняется в ссылке?

На первый взгляд все HLS-ссылки выглядели совершенно случайным набором символов.

Например:

https://msk.rtsp.me/hNn2ldTc7s0SvyG6dWBO4Q/1776155468/hls/qDVeNFd8.m3u8

Через несколько минут ссылка становилась уже такой:

https://msk.rtsp.me/vx3fEswWm_r3fLjpyqZpsA/1776156062/hls/qDVeNFd8.m3u8

Если посмотреть бегло, кажется, что изменилось практически всё. Но опыт работы в информационной безопасности подсказывает простую вещь. Если система генерирует идентификаторы автоматически, то они редко бывают полностью случайными. Обычно в них можно найти определенную закономерность. Именно этим я и решил заняться.

Разбираем URL по частям

Если разделить ссылку на логические блоки, получится намного понятнее.

https://msk.rtsp.me

 ├── hNn2ldTc7s0SvyG6dWBO4Q
 │ 
 ├── 1776155468
 │
 ├── hls
 │
 └── qDVeNFd8.m3u8

Каждая часть отвечает за свою задачу.

Сервер

msk.rtsp.me

Это вполне ожидаемо. Во время экспериментов попадались разные серверы.

Например:

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


Второй элемент

hNn2ldTc7s0SvyG6dWBO4Q

Вот здесь начиналось самое интересное. Именно эта часть менялась каждые несколько минут. Причем абсолютно всегда.

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

Назовем его условно:

session_token

Именно он делает ссылку "одноразовой".


Третий элемент

1776155468

Сначала он тоже выглядел случайным. Но стоило посмотреть внимательнее...

Это обычный Unix Timestamp. То есть время генерации ссылки. Причем оно почти идеально совпадало с моментом открытия камеры.

Получается, что RTSP.RU буквально встраивает время создания прямо в URL. Еще одно подтверждение того, что ссылка действительно временная.


Последний элемент

qDVeNFd8.m3u8

А вот здесь меня ждал небольшой сюрприз.

Этот идентификатор... не менялся вообще. Сколько бы раз я ни открывал одну и ту же камеру, последний элемент всегда оставался одинаковым.

Именно тогда появилась первая гипотеза. Вероятно, это постоянный идентификатор конкретного видеоканала.

Условно:

channel_token

Получалась довольно интересная структура.

https://

сервер /

временный токен /

время создания /

hls /

постоянный идентификатор камеры

Другими словами: меняется не камера - меняется только право доступа к ней. Это довольно элегантное решение с точки зрения архитектуры.

Неожиданная находка

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

Например:

HD

qDVeNFd8

SD

8dFNeVDq

Я несколько раз перепроверил и не поверил своим глазам.

Если внимательно посмотреть... Получается вот что:

HD

qDVeNFd8

↓

SD

8dFNeVDq

То есть идентификаторы практически являются зеркальным отражением друг друга.

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

Почему два потока – это хорошо

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

Логика получается следующая. Поток низкого качества используется исключительно для анализа изображения и поиска движения. Он требует значительно меньше ресурсов процессора. А как только Frigate обнаруживает событие, запись уже ведется из HD-потока.

В результате система получает сразу несколько преимуществ:

  • значительно ниже нагрузка на CPU;

  • выше качество записанного видео;

  • меньше вероятность пропустить событие;

  • экономится место в архиве.

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

Главное открытие

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

Архитектура RTSP.RU устроена значительно интереснее. Сервис динамически выдает временный URL, который действует ограниченное время. После истечения срока действия создается новый session_token, и браузер автоматически продолжает работу уже с новым адресом.

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

Если нельзя заставить ссылку жить дольше, значит нужно научиться автоматически получать новую раньше, чем перестанет работать старая. Оставалось только придумать, как сделать это полностью автоматически. И желательно так, чтобы Home Assistant вообще ничего не заметил.

Глава 4. Почему простые решения не работают

К этому моменту задача выглядела уже намного понятнее.

Мы знали несколько важных вещей.

  • RTSP.RU использует HLS.

  • Прямая ссылка на поток существует.

  • Каждая ссылка живет около десяти минут.

  • После этого сервис выдает совершенно новый URL.

Казалось бы, решение где-то совсем рядом. Оставалось только научиться автоматически получать новую ссылку. Но на практике все оказалось немного интереснее.

Первая идея – просто сохранить ссылку

Это первое, что приходит в голову практически любому.

  • Открываем DevTools.

  • Копируем URL.

  • Добавляем его в Home Assistant.

  • Получаем изображение.

  • Работает.

  • Ровно десять минут.

  • После этого поток просто исчезает.

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

Вторая идея – обновлять поток вручную

Следующая мысль тоже вполне логичная.

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

  • Например, запускать небольшой Bash-скрипт по cron.

  • Получили новый URL.

  • Обновили конфигурацию.

  • Перезапустили Home Assistant.

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

Каждые десять минут:

  • перезапуск интеграции;

  • переподключение всех клиентов;

  • повторное открытие потока;

  • потеря нескольких секунд видео.

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

Третья идея – пусть обновляется сам VLC

На этом этапе я попробовал использовать VLC. Ведь браузер каким-то образом автоматически получает новые ссылки. Может быть, VLC тоже умеет это делать?

К сожалению, нет. Для VLC это обычный HLS URL. Как только срок действия ссылки заканчивается, проигрыватель честно пытается открыть уже несуществующий адрес. И закономерно получает ошибку.

Может быть, поможет FFmpeg?

Следующим кандидатом оказался FFmpeg. Он умеет автоматически переподключаться, умеет восстанавливать соединение и переживать временные ошибки сети. Но есть одна проблема: FFmpeg прекрасно работает тогда, когда URL остается прежним. В нашем случае меняется не соединение – меняется сама ссылка и никакие параметры reconnect здесь уже не помогают. Для FFmpeg старый URL просто перестает существовать.

В этот момент стало понятно главное

Все предыдущие варианты объединяла одна общая ошибка: каждый из них пытался сделать постоянной ссылку, которая по своей природе постоянной быть не может. Но ведь браузер прекрасно продолжает работать. Почему?

Потому что браузер вообще не пытается использовать старый URL. Он каждый раз получает новый.

Скрипт sh, который получает данные

/bin/bash
# Берем URL плеера встроенного в  iframe
PAGE_URL=https://rtsp.me/embed/KPbwo57M/

# ip адрес API Go2RTC должен быть открыт порт 1984
API_URL="http://ip_адрес_HomeAssistant:1984/api/streams"
UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"

echo "Получаем страницу..."
HTML=$(curl -s -A "$UA" "$PAGE_URL")

# Определяем домен rtsp.me из найденных ссылок
RTSP_HOST=$(echo "$HTML" | grep -oE "https://[a-z0-9-]+\.rtsp\.me" | head -n1 | sed 's#https://##')

if [ -z "$RTSP_HOST" ]; then
echo "Ошибка: не удалось определить сервер rtsp.me"
exit 1
fi

echo "Найден сервер: $RTSP_HOST"

# --- HD поток (последний .m3u8) ---
HD_URL=$(echo "$HTML" | grep -oE "https://${RTSP\_HOST}[^\"']+\.m3u8" | tail -n1 | cut -d"=" -f1 | tr -d "\r\n")

# --- SD поток (первый .m3u8) ---
SD_URL=$(echo "$HTML" | grep -oE "https://${RTSP\_HOST}[^\"']+\.m3u8" | head -n1 | cut -d"?" -f1 | tr -d "\r\n")

# Проверки
if [ -z "$HD_URL" ]; then

    echo "Ошибка: HD URL не получен"
fi

if [ -z "$SD_URL" ]; then
    echo "Ошибка: SD URL не получен"
fi

HD_FFMPEG="ffmpeg:${HD_URL}%23video=copy%23an%23rtsp_transport=tcp%23reconnect=true%23jitter_buffer=2"
SD_FFMPEG="ffmpeg:${SD_URL}%23video=copy%23an%23rtsp_transport=tcp%23reconnect=true%23jitter_buffer=2"

echo "HD: $HD_FFMPEG"
echo "SD: $SD_FFMPEG"

curl -s -X PUT "${API_URL}?name=rtsp_hd&src=${HD_FFMPEG}" \
     -H "Content-Type: text/plain"

curl -s -X PUT "${API_URL}?name=rtsp_sd&src=${SD_FFMPEG}" \
     -H "Content-Type: text/plain"

echo "Потоки обновлены"

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

Пусть Home Assistant всегда обращается к одному и тому же RTSP-адресу. А где-то между ним и RTSP.RU будет небольшой "посредник", который незаметно подменяет источник видео каждый раз, когда RTSP.RU выдает новый токен.

Получалась примерно такая схема.

                RTSP.RU
                  │
        новый HLS каждые 10 минут
                  │
             Наш небольшой сервис
                   │
        всегда один и тот же RTSP
                    │
             Home Assistant

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

Первая – регулярно получать новый HLS URL. Вторая – незаметно для клиентов переключать источник видеопотока.

Если удастся найти такой инструмент, Home Assistant никогда не узнает, что настоящая ссылка меняется каждые десять минут. Для него камера всегда будет выглядеть как обычная локальная RTSP-камера. Оставалось только понять, существует ли вообще такой инструмент.

И неожиданно оказалось, что он уже давно был установлен у меня в системе.

Имя ему – go2rtc.

Именно он позже станет главным героем всей этой статьи.

Глава 5. Go2RTC – инструмент, который решил проблему, о существовании которой даже не подозревал

Когда появилась идея использовать промежуточный шлюз между RTSP.RU и Home Assistant, возник вполне закономерный вопрос.

Писать собственный сервис или поискать готовое решение?

Как и любой инженер, я предпочитаю сначала разобраться, не решил ли кто-то эту задачу раньше. Оказалось – решил. Причем этот инструмент уже давно работал у меня в Home Assistant.

Что такое go2rtc

Большинство пользователей Home Assistant знают go2rtc исключительно как компонент для работы с RTSP-камерами.

Конфигурация go2rtc:

mqtt: 
enabled: true 
host: core-mosquitto 
port: 1883 
user: mqtt_user 
password: mqtt_password

api: 
listen: ":1984" 
origin: "*" 

rtsp:
listen: ":8554"
protocols: [tcp]

webrtc:
listen: ":8556/tcp"

ffmpeg:
global: "-hide_banner -loglevel warning -fflags nobuffer -flags low_delay"

h264: >
  -c:v libx264
  -preset medium
  -profile:v high   
-level 4.1  
  -pix_fmt yuv420p  
  -crf 23  
  -maxrate 4000k  
  -bufsize 8000k  
  -g 50  
  -keyint_min 50  
  -r 25  
  -x264-params "keyint=50:min-keyint=50"  
  -bf 2  
  -refs 3  
  -direct-pred auto  
  -me_method hex  
  -subq 7  
  -trellis 1 
   -an                        

streams: 
rtsp_hd:     - ffmpeg:https://spb.rtsp.me/1NKuwXhKdhw7DkcrAmWNtA/1782299382/hls/KPbwo57M.m3u8#video=copy#an#rtsp_transport=tcp#reconnect=true#jitter_buffer=2

  rtsp_sd:     - ffmpeg:https://spb.rtsp.me/1NKuwXhKdhw7DkcrAmWNtA/1782299382/hls/KPbwo57M.m3u8#video=copy#an#rtsp_transport=tcp#reconnect=true#jitter_buffer=2

Если максимально упростить, то обычно его используют так:

IP-камера
    │
    ▼
  go2rtc
   │
   ▼
Home Assistant

Иногда к этой схеме добавляется Frigate. Иногда WebRTC. Иногда трансляция в браузер. Но практически всегда go2rtc воспринимают просто как удобный RTSP-прокси.

Честно говоря, до этого момента я тоже использовал его именно так. И совершенно не подозревал, что самая интересная возможность скрывается совсем в другом месте.

Неожиданное открытие

Изучая документацию API, я наткнулся на метод, который сначала не произвел особого впечатления. Он позволял изменить источник существующего потока без перезапуска go2rtc.

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

Есть поток с именем:

podjezd_hd

  • Home Assistant знает только это имя.

  • Frigate знает только это имя.

  • Карточка камеры знает только это имя.

Все клиенты подключаются исключительно к нему.

Но...

Источник этого потока можно заменить буквально одной HTTP-командой.

При этом:

  • имя камеры остается прежним;

  • RTSP-адрес не меняется;

  • клиенты продолжают работать;

  • переподключение практически незаметно.

В этот момент стало понятно, что проблема уже фактически решена.

Новая архитектура

До этого момента схема выглядела примерно так.

RTSP.RU
    │
    ▼
Home Assistant

Главная проблема заключалась в том, что RTSP.RU каждые несколько минут выдавал новый URL.

Home Assistant этого не понимал.

После появления go2rtc архитектура полностью изменилась.

          RTSP.RU
              │
      новый HLS каждые 10 минут
              │
              ▼
         Bash-скрипт
              │
    обновляет источник через API
              │
              ▼
           go2rtc
              │
      постоянный RTSP-адрес
              │
              ▼
      Home Assistant
              │
              ▼
           Frigate

На первый взгляд кажется, что появился лишний элемент. На самом деле именно go2rtc берет на себя всю сложность интеграции. Для Home Assistant больше не существует никаких токенов, временных ссылок или HLS. Он работает с обычной RTSP-камерой.

Почему это оказалось настолько удобно

Самое интересное заключается даже не в смене источника. Главное преимущество такой схемы – полная изоляция Home Assistant от внешнего сервиса.

Теперь вся логика взаимодействия с RTSP.RU сосредоточена в одном месте. Если завтра изменится формат ссылок или алгоритм авторизации, достаточно изменить только Bash-скрипт. Конфигурация Home Assistant, Frigate и go2rtc останется прежней. Это классический принцип, который хорошо известен в разработке программного обеспечения.

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

Еще один приятный бонус

Во время тестирования выяснилась неожиданная особенность – Home Assistant практически не замечает момент переключения источника.

Если Bash-скрипт получает новый HLS URL немного раньше окончания действия старого, смена происходит настолько быстро, что карточка камеры продолжает показывать изображение без каких-либо заметных разрывов.

Для пользователя это выглядит так, будто поток никогда не менялся. Хотя в реальности за сутки источник обновляется более сотни раз.

Мысль инженера

Именно в этот момент я понял, что задача была вовсе не про Home Assistant. Она была про интеграцию двух систем, которые используют совершенно разные модели работы.

RTSP.RU ожидает, что клиент будет регулярно получать новые временные ссылки.

Home Assistant ожидает, что адрес камеры никогда не изменится.

Go2RTC оказался тем самым "переводчиком", который позволил обеим системам работать так, словно они изначально были созданы друг для друга. Оставалось реализовать последнюю часть этой схемы. Научить систему автоматически получать новые ссылки на HLS-потоки и передавать их в go2rtc без какого-либо участия пользователя.

Именно этим мы сейчас и займемся.

Глава 6. Реализация. Интеграция  Go2RTC, Frigate и Home Assistant

После того как были получены стабильные потоки через RTSP/HLS и организован слой доставки через go2rtc, следующим логическим шагом становится интеграция аналитики и событийного слоя.

На сайте обслуживающей организации я получил URL iframe всех нужных мне камер. Для каждой камеры сделал скрипт по аналогии с примером bash скрипта выше и сделал автоматизацию:

alias: Обновление всех RTSP потоков каждую минуту (параллельно)
description: Запускает все скрипты обновления RTSP каждую минуту параллельно
triggers:
  - seconds: /59
    trigger: time_pattern
actions:
  - data: {}
    action: shell_command.update_rtsp_stream_28_8_13
  - data: {}
    action: shell_command.update_rtsp_stream_28_8_17
- data: {}
    action: shell_command.update_rtsp_stream_28_8_8
  - data: {}
    action: shell_command.update_rtsp_stream_28_6_p_7_3
  - data: {}
    action: shell_command.update_rtsp_stream_28_8_5
  - data: {}
    action: shell_command.update_rtsp_stream_28_8_4
  - data: {}
    action: shell_command.update_rtsp_stream_28_8_21
  - data: {}
    action: shell_command.update_rtsp_stream_86_6_p_7_2
mode: parallel
max: 6

Для возможности запуска нужно добавить в /homeassistant/configuration.yaml раздел со скриптами:

shell_command:
  update_rtsp_stream_28_6_p_7_3: '/config/scripts/28.6_p.7_3.sh'
  update_rtsp_stream_28_8_13: '/config/scripts/28.8_13.sh'
  update_rtsp_stream_28_8_17: '/config/scripts/28.8_17.sh'
  update_rtsp_stream_28_8_8: '/config/scripts/28.8_8.sh'
  update_rtsp_stream_28_8_5: '/config/scripts/28.8_5.sh'
  update_rtsp_stream_28_8_4: '/config/scripts/28.8_4.sh'
  update_rtsp_stream_28_8_21: '/config/scripts/28.8_21.sh'
  update_rtsp_stream_86_6_p_7_2: '/config/scripts/28.6_p.7_2.sh'

Если go2rtc решает задачу транспорта видео, то Frigate и Home Assistant превращают поток в систему реагирования.

Роль Frigate в архитектуре

Frigate используется как локальный NVR с детекцией объектов в реальном времени.

Конфигурация frigate:

mqtt:
  host: core-mosquitto
  port: 1883
  user: mqtt_user
  password: mqtt_password

database:
  path: /media/frigate/frigate.db

# ==================== Логирование ====================
logger:
  logs:
    frigate.record.maintainer: info

# ==================== DETECTORS ====================
detectors:
  cpu1:
    type: cpu
    num_threads: 3
  cpu2:
    type: cpu
    num_threads: 3
  cpu3:
    type: cpu
    num_threads: 3

# ==================== FFMPEG ====================
ffmpeg:
  global_args: -hide_banner -loglevel warning
  input_args:
    - -rtsp_transport
    - tcp
    - -fflags
    - +genpts+discardcorrupt
    - -flags
    - low_delay
  output_args:
    record: preset-record-generic

# ==================== RECORD ====================
record:
  enabled: true
  alerts:
    retain:
     days: 7
      mode: active_objects
    pre_capture: 10
    post_capture: 10
  detections:
    retain:
     days: 7
      mode: active_objects
    pre_capture: 10
    post_capture: 10

snapshots:
  enabled: true
  timestamp: true
  bounding_box: true
  retain:
   default: 7

birdseye:
  enabled: true
  mode: motion 

objects:
  track:
    - person
    - car

detect:
  enabled: true
  width: 640
  height: 360
  fps: 5

# ==================== КАМЕРЫ ====================
cameras:

  rtsp_cam:
    enabled: true
    ffmpeg:
      #hwaccel_args: preset-rpi-64-h264
      inputs:
      - path: rtsp://ip_адрес_HomeAssistant:8554/rtsp_hd?rtsp_transport=tcp
          roles: [record]
        - path: rtsp://ip_адрес_HomeAssistant:8554/rtsp_sd?rtsp_transport=tcp
         roles: [detect]
    motion:
      mask: 0.648,0,1,0,1,0.069,0.651,0.072

# ================= Глобальные настройки для всех камер ============

motion:
  threshold: 30
  contour_area: 10
  improve_contrast: true
version: 0.17-0
semantic_search:
  enabled: false
  model_size: small
face_recognition:
  enabled: false
  model_size: small

Его ключевая особенность — работа не с «видео как картинкой», а с потоком событий:

  • движение

  • человек

  • транспорт

  • зоны интереса

  • триггеры событий

Архитектурная связка системы

Полная цепочка выглядит так:

Камера → go2rtc → Frigate → Home Assistant → пользователь

Но важно понимать: каждый слой выполняет строго свою функцию.

Компонент

Роль

Камера

источник видеопотока

go2rtc

транспорт и стабилизация

Frigate

аналитика и детекция

Home Assistant

автоматизации и UI

Почему Frigate нельзя ставить “в лоб”

Частая ошибка – подключать камеры напрямую в Frigate.

Проблемы:

  • нестабильные RTSP потоки

  • обрывы соединений

  • дублирование FFmpeg процессов

  • высокая CPU нагрузка

В связке с go2rtc это решается принципиально иначе:

Frigate получает уже стабилизированный поток.

Использование go2rtc как upstream слоя

go2rtc в этой архитектуре становится единым источником правды для всех потребителей потока.

Камера → go2rtc → Frigate → события → Home Assistant

Преимущества:

  • один поток на камеру

  • отсутствие дублирования RTSP соединений

  • предсказуемая нагрузка

  • стабильность детекции

Детекция событий и передача в Home Assistant

Frigate формирует события:

  • motion

  • person detected

  • vehicle detected

  • zone entry/exit

Эти события передаются в Home Assistant через MQTT или native integration.

Home Assistant как событийный центр

Home Assistant в этой архитектуре не обрабатывает видео.

Он выполняет роль:

  • оркестратора событий

  • UI панели

  • системы автоматизаций

Пример автоматизации:

  • Frigate фиксирует человека

  • Home Assistant:

    • включает свет

    • отправляет push

    • записывает clip

    • активирует сценарий безопасности

 

Глава 7. Оптимизация производительности и снижение нагрузки

После успешной интеграции камер в Home Assistant большинство пользователей сталкивается с новой проблемой – нестабильной работой видеопотока. Камеры могут периодически зависать, появляться с задержкой или вовсе переставать отображаться через некоторое время.

На практике причина чаще всего заключается не в самой камере, а в том, как организована обработка видеопотока.

Почему HLS плохо подходит для Home Assistant

Многие облачные сервисы отдают видео именно в формате HLS (.m3u8).

На первый взгляд это удобно:

  • поток открывается практически в любом браузере;

  • поддерживается адаптивное качество;

  • нет необходимости устанавливать дополнительные кодеки.

Однако для Home Assistant такой вариант далеко не идеален.

При каждом просмотре происходит:

Home Assistant
       │
       ▼
 go2rtc
       │
       ▼
 HTTP HLS
       │
       ▼
 Скачивание сегментов (.ts)
       │
       ▼
 FFmpeg
       │
       ▼
 Декодирование
       │
       ▼
 WebRTC

Получается несколько лишних этапов обработки.

В результате:

  • увеличивается задержка;

  • возрастает использование процессора;

  • появляются разрывы изображения при плохом соединении.


Почему go2rtc значительно улучшает ситуацию

Именно поэтому я практически всегда использую go2rtc как промежуточный сервер.

Он выполняет сразу несколько задач:

  • ✔ поддерживает постоянное соединение с камерой;

  • ✔ автоматически переподключается после обрыва;

  • ✔ преобразует HLS в WebRTC;

  • ✔ позволяет нескольким клиентам смотреть один поток одновременно.

Например:

Телефон
           \
 Планшет ----> Home Assistant
           /
 Браузер
         │
         ▼
      go2rtc
         │
         ▼
      HLS поток

Без go2rtc каждый клиент создавал бы собственное подключение к облачному серверу.


Использование параметра reconnect

Одной из наиболее полезных возможностей FFmpeg внутри go2rtc является автоматическое переподключение.

Например:

streams:
  entrance:
    - ffmpeg:
https://example.com/stream.m3u8#video=h264#an#reconnect=1

Параметр

reconnect=1

позволяет автоматически восстановить соединение после временной недоступности сервера.

На практике это значительно уменьшает количество ситуаций, когда поток приходится перезапускать вручную.


Отключение ненужной обработки

Если звук не требуется, его лучше сразу отключить.

Например:

#an

Это позволяет:

  • снизить загрузку процессора;

  • уменьшить сетевой трафик;

  • сократить задержку.

Для большинства камер видеонаблюдения звук используется редко, поэтому данная оптимизация практически не имеет недостатков.


Выбор качества потока

Практически все облачные сервисы предоставляют несколько вариантов качества.

Например:

HD

и

SD

Если камера используется:

  • в панели Home Assistant;

  • на мобильном телефоне;

  • в режиме постоянного просмотра,

часто разумнее использовать SD-поток.

Разница в нагрузке может быть весьма заметной.

HD лучше оставить:

  • для записи;

  • полноэкранного просмотра;

  • детального анализа изображения.

 

Заключение

Когда я начинал эту историю, задача выглядела предельно простой: «подключить камеры двора к Home Assistant». По факту же это оказалось полноценным инженерным расследованием – с reverse engineering чужого сервиса, разбором структуры URL, экспериментами с FFmpeg и в итоге собственной архитектурой из go2rtc, Frigate и Home Assistant.

Если собрать весь этот опыт в несколько выводов, получится примерно следующее:

Проблема почти никогда не там, где кажется на первый взгляд

Изначально казалось, что не хватает «правильной ссылки» на видеопоток. На самом деле не хватало понимания архитектуры: RTSP.RU сознательно делает ссылки временными, и бороться с этим бессмысленно. Как только я перестал искать постоянный URL и начал искать способ автоматически получать новый, задача решилась сама собой.

go2rtc оказался не «RTSP-прокси», а универсальным адаптером

Большинство пользователей Home Assistant используют go2rtc исключительно для подключения IP-камер и даже не подозревают о возможности подменять источник потока на лету через API. Именно эта функция стала ключом ко всей интеграции: Home Assistant и Frigate продолжают работать с одним и тем же RTSP-адресом, даже когда реальный источник за кулисами меняется десятки раз в сутки.

Разделение ответственности – рабочий принцип не только в коде

Вся логика получения новых ссылок вынесена в отдельный Bash-скрипт, который ничего не знает ни про Frigate, ни про Home Assistant. Если завтра RTSP.RU изменит формат ссылок или механизм авторизации, поменяется только этот скрипт. Конфигурация Home Assistant, go2rtc и Frigate останется прежней. Такой подход избавляет от необходимости трогать всю систему целиком ради изменений в одном источнике.

Стабильный транспорт важнее «красивого» решения

Понижение нагрузки, разделение HD и SD потоков, отказ от лишней обработки звука, параметр reconnect – все эти детали кажутся мелочами, но именно они определяют, будет ли система работать стабильно месяцами, а не разваливаться при первом сбое сети.

В результате камеры видеонаблюдения, которые формально «не поддерживали» ни RTSP, ни ONVIF, ни какую-либо интеграцию, превратились в полноценные локальные камеры с собственным архивом, детекцией движения, распознаванием людей и автомобилей и участием в сценариях умного дома – открытие шлагбаума, push-уведомления при обнаружении человека у двери и многое другое.

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

На этом опыт с камерами не заканчивается – он, скорее, стал отправной точкой. Дальше в планах разобрать другие практические кейсы по настройке умного дома на Home Assistant: автоматизации, интеграции нестандартных устройств, оптимизацию производительности сервера и решения других задач, с которыми сталкивается почти каждый, кто строит свою систему, а не собирает её из готовых «коробочных» решений. Так что если тема зашла – не прощаюсь, продолжение следует…

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


  1. shadrap
    16.07.2026 11:47

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

    Но вцелом, исследование интересное..., спасибо за статью.