В этой статье я расскажу, как организовал себе примитивный видеорегистратор, который:

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

  2. Вести циклическую запись в формате mp4 и сохранять её удалённо.

  3. Стоит меньше 100$.

Изначально у меня была задача организовать себе регистратор, который будет непрерывно писать всё происходящее с камер и по защищённому каналу загружать записи на удалённый сервер. Ошибочно предположив, что это вполне банальная задача, я приобрёл себе регистратор dahua NVR NVR5208-EI… Каково же было моё разочарование, когда выяснилось, что купленное устройство содержит ряд фатальных недостатков:

  1. Из удалённых хранилищ поддерживается только FTP/SFTP. Причем к SFTP невозможно подключиться используя ssh-ключ (только логин и пароль).

  2. Сохраняет видео в неюзабельном dav формате. В природе не существует удобного способа конвертировать это безобразие в mp4.

  3. Дает этим dav-файлам какие-то бредовые имена.

  4. Толком не настраивается — интерфейс настройки весьма скуден.

  5. Глючит (то пишет, то не пишет) и не предоставляет никаких логов.

Скрытый текст

Отдельного упоминания заслуживает некомпетентность официальной поддержки dahuatech.com. Я приобрел удалённое FTP хранилище, где намеревался хранить записи, но регистратор упорно не мог к нему подключиться. Без проблем подключаюсь разных устройств, а регистратор выдаёт failed… Вместо помощи в решении, поддержка заняла позицию «у вас что-то не то с сервером, разбирайтесь сами». А после того, мой вопрос был перенаправлен в инженерный отдел, спустя 2 недели пришёл ответ «This sftp problem, with the customer's ftp server address, the development side made a lot of attempts, but also adjusted the encryption algorithm, but the authentication of the request sent to the server has been returned to the authentication failure, the device plus print to confirm that the username and password sent out of the problem, which requires the server to assist in investigating the reason why it will reject our login request.» В итоге экспериментальным путём выяснилось, что оборудование dahua работает только с OpenSSL версии 3+, а на сервере был установлен 1.0.2k-fips…

Поняв бесперспективность движения в сторону готовых регистраторов, пришлось искать альтернативные варианты. В итоге на основе R4S, rclone и mediamtx мне удалось создать стабильное решение.

Необходимые компоненты:

  1. Подключение к Интернету с реальным IP-адресом. Если ваш провайдер предоставляет доступ к сети через CGNAT, организовать webrtc трансляцию не получится.

  2. Камеры, способные выдавать RTSP поток в формате h264. В идеале брать камеры, которые способны выдавать 2 качественных потока (h254 и h265) одновременно. Я использую камеры dahua IPC-HDW3841T-ZS-S2.

  3. Хостинг, доменное имя, SSL-сертификат.

  4. Удалённое хранилище, куда при помощи rclone будет загружаться видео. Поддерживаются SFTP, Yandex.Disk, Google Drive, Dropbox и т. п.

  5. NanoPi R4S с OpenWRT (далее просто R4S). Его вполне можно заменить на любой одноплатник с линуксом аналогичной мощности, но в статье я буду использовать именно R4S. У меня он используется в качестве роутера, но, в силу избыточной мощности, вполне способен выполнять ещё и роль регистратора на 8 камер.

Настройка камер

Для живой webrtc трансляции нужно получать от камер RTSP поток с разрешением 1920x1080, видеокодеком H264 и аудиокодеком G711. Для сохранения видео, в идеале получать ещё один поток с видеокодеком H265, аудиокодеком AAC и разрешением 2560x1440.

Настройки одной из моих камер
Настройки одной из моих камер

Некоторые пояснения:

  1. Я не использую smart codec и AI codec. По ощущениям, они какие-то глючные: только размер сохраняемого файла увеличивается.

  2. Для сохранения оптимально использовать CBR с ключевым кадром не реже чем раз 3 секунды. Bitrate и Framerate подбираются индивидуально. Для трансляции (особенно через сотовые сети) подходит и VBR.

Поскольку ссылка на RTSP поток содержит логин и пароль, для доступа к потокам желательно создавать отдельного пользователя. В моём случае ссылки имеют вид:

  • rtsp://rtsp:password@192.168.1.1/cam/realmonitor?channel=1&subtype=0 – для основного H265 потока

  • rtsp://rtsp:password@192.168.1.1/cam/realmonitor?channel=1&subtype=2 – для дополнительного H264 потока.

Настройка R4S

На R4S необходимо установить OpenWRT. Далее предполагается, что читатель осилит его первоначальную настройку и сможет подключить к Интернету.

Схема работы: медиасервер mediamtx непрерывно сохраняет записи с камер отрывками по 5 минут во временный каталог. Каждые 3 минуты производится перенос файлов в хранилище. Раз в сутки хранилище очищается от устаревших файлов.

Стандартными средствами устанавливаем rclone и luci-app-ttyd. Из главного меню переходим в Services => Terminal, авторизуемся, командой rclone config запускаем интерактивный конфигуратор и создаём подключение к удалённом хранилищу с именем main (ниже будет встречаться в листингах конфигураций).

Чтобы не изнашивать карту памяти, хранить видеофайлы файлы на R4S оптимально во временном каталоге /tmp/cams, который расположен в оперативной памяти. Стандартно раздел для временных файлов довольно мал… Но у R4S на борту аж 4 Гб оперативки! Для роутера с лихвой хватит и 1 Гб, поэтому оставшиеся 3 Гб направляем в пользу временного хранилища. В System => Startup => Local Startup прописываем команду:

mount tmpfs /tmp -t tmpfs -o remount,size=3000m,nosuid,nodev

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

Теперь в настройках файрвола откроем порт 8889 через который будет вестись webrtc трансляция.

В файрволе разрешаем весь входящий трафик на порт 8889 R4S
В файрволе разрешаем весь входящий трафик на порт 8889 R4S

Далее создаём каталог /etc/config/mediamtx в который поместим файлы:

  • certificate.crt и certificate.key – файлы с SSL-сертификатом и его приватным ключом.

  • rclone.sh – запускается планировщиком задач каждые 3 минуты и выполняет перенос видеофайлов в хранилище. Содержимое:

#!/bin/sh

# Перенос файлов в удалённое хранилище
rclone move --min-age 3s --delete-empty-src-dirs --no-traverse /tmp/mediamtx main:/

# Лог последнего переноса
date > /etc/config/mediamtx/move.log
  • rclone_del.sh — запускается планировщиком задач раз в сутки и удаляет из хранилища устаревшие файлы. Содержимое:

#!/bin/sh

# Удаление устаревших файлов спустя неделю
rclone delete --min-age 1w main:/

# Лог последнего удаления
date > /etc/config/mediamtx/delete.log
  • mediamtx и mediamtx.yml – файлы из дистрибутива mediamtx (исполняемый файл и конфигурация). Скачивание доступно по ссылке, для R4S выбираем релиз для arm64v8.

В планировщике задач System => Scheduled Tasks прописываем строки для выполнения rclone.sh и rclone_del.sh:

*/3 * * * * /etc/config/mediamtx/rclone.sh
0 1 * * * /etc/config/mediamtx/rclone_del.sh

Медиасервер mediamtx поставляется в виде исполняемого файла. Чтобы он мог работать в фоновом режиме и запускаться вместе с системой, для него требуется создать initscript. На основе инструкции создаём файл /etc/init.d/mediamtx (обязательно с правами запуска). Содержимое:

#!/bin/sh /etc/rc.common

START=25
USE_PROCD=1

start_service() {
	procd_open_instance "mediamtx"
	procd_set_param command /etc/config/mediamtx/mediamtx /etc/config/mediamtx/mediamtx.yml
	procd_set_param stdout 1
	procd_set_param stderr 1
	procd_close_instance
}

reload_service() {
	echo "It reloads automatically";
	stop
	start
}

Настройка mediamtx

В конфигурационном файле /etc/config/mediamtx/mediamtx.yml находим секцию record и правим следующие параметры:

# Ежедневно записи сохраняются в новый каталог с текущей датой
recordPath: /tmp/mediamtx/%path/%Y-%m-%d/%H-%M-%S
recordFormat: fmp4
recordPartDuration: 1s
recordSegmentDuration: 5m
recordDeleteAfter: 7m

Далее переходим в секцию paths: и настраиваем потоки. Для камеры, которая умеет отдавать 2 потока, указываются 2 записи:

paths:
  # H264 поток для webrtc трансляции
  cam1:
    source: rtsp://rtsp:password@192.168.1.1/cam/realmonitor?channel=1&subtype=2
    record: no
    sourceOnDemand: yes

  # H265 поток для записи
  cam1r:
    source: rtsp://rtsp:password@192.168.1.1/cam/realmonitor?channel=1&subtype=0
    record: yes
    sourceOnDemand: no

Если же поток один, то запись выглядит так:

cam2:
  # H264 поток и для записи и webrtc трансляции
  source: rtsp://rtsp:password@192.168.1.2/cam/realmonitor?channel=1&subtype=0
  record: yes  
  sourceOnDemand: no

Если всё сконфигурировано верно, после запуска mediamtx, из локальной сети станут доступны webrtc трансляции по адресам http://r4s:8889/stream-name, а в каталоге /tmp/mediamtx/ начнут появляться mp4 файлы. Также уже должен работать планировщик задач и запускать каждые 3 минуты rclone, чтобы тот загружал эти файлы в удалённое хранилище.

Настройка домена

Используя тот факт, что ssl с проверкой домена защищает не только сам домен, но ещё и его www поддомен, можно сэкономить и обойтись всего одним таким ssl: домен должен указывать на хостинг (где размещено приложение), а поддомен www должен указывать на R4S. В зависимости от того, как провайдер предоставляет провайдер вам реальный IP (статический IP или DDNS), для поддомена www нужно внести соответствующую ресурсную A, AAAA или CNAME запись.

Возвращаемся к mediamtx.yml, переходим в секцию webrtc и прописываем ssl сертификат и домен (example.net указан в качестве примера):

webrtc: yes
webrtcAddress: :8889
webrtcEncryption: yes
webrtcServerKey: /etc/config/mediamtx/certificate.key
webrtcServerCert: /etc/config/mediamtx/certificate.crt
webrtcAllowOrigin: 'https://example.net'
webrtcTrustedProxies: []
webrtcLocalUDPAddress: www.example.net:8889
webrtcLocalTCPAddress: ''
webrtcIPsFromInterfaces: no
webrtcIPsFromInterfacesList: []
webrtcAdditionalHosts: [www.example.net]

После перезапуска, webrtc трансляция должна стать публично доступной по адресу https://www.example.net:8889/stream-name . Если всё ок, переходим к последнему этапу.

Ограничение доступа и просмотр

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

  1. Загрузите всё содержимое каталога build на хостинг (не обязательно в корень, можно и в каталог).

  2. Ограничьте доступ к каталогу build/restricted http аутентификацией.

  3. Заполните файл build/restricted/cameras.json, указав доступы к вашим потокам.

 {
	"caption":"Cameras",
	"host":"https://www.example.net:8889/",
	"streams":[
		["caption", "stream-name", "material-icon"],

		["East example", "cam1", "east", {"rotate":90}],
		["West example", "cam2", "west", {"rotate":-90}]
	]
}

Перечень иконок material-icon общедоступен. При помощи последнего параметра можно перевернуть изображение с камеры по часовой {"rotate":90} или против часовой {"rotate":-90} стрелки. Это особенно удобно, если камера снимает узкий проход и монтажник перевернул её на 90°.

Скриншоты SPA
Скриншоты SPA

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


  1. Aquahawk
    22.08.2024 16:13
    +2

    Я у себя на сервере вкрутил Agent DVR https://www.ispyconnect.com/docs/agent/about и очень им доволен, т.к. видеонаблюдение в подъезде очень удобна функция что пишет только отрезки где есть движение.


    1. Sunvas Автор
      22.08.2024 16:13
      +1

      Как он реагирует на движение котов / птиц / кустов?


      1. vesowoma
        22.08.2024 16:13

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


      1. rukhi7
        22.08.2024 16:13
        +1

        Кусты просто так не шевеляться, а если и шевелятся не плохо проверить что действительно это только ветер.


        1. Sunvas Автор
          22.08.2024 16:13
          +2

          Камеры с подсветкой и стоят на улице. В тёмное время суток видимость движения создают засветы от летающих насекомых. Встроенный intelligent detection всегда на это реагировал, создавай много ложных уведомлений. Поэтому я пока скептически отношусь ко всем AI решениям: нет гарантии что сработает когда надо и не сработает когда не надо.


  1. Aelliari
    22.08.2024 16:13
    +1

    Если ваш провайдер предоставляет доступ к сети через CGNAT, организовать webrtc трансляцию не получится.

    И да, и нет, вам действительно нужен «белый» ip-адрес, чтобы обеспечить прямой доступ к вашим ресурсам, но:

    1) Если вам для дома не принципиален доступ из интернета без сторонних средств - есть tailacale/zerotier/netmaker и другие.

    2) Если вам важно иметь доступ без сотороннего софта, и использование услуг cloudflare не попадает под вашу модель угроз - они предоставляют великолепный сервис даже для бесплатных аккаунтов. В частности вполне возможно находясь за NAT хостить публично-доступный (по ipv4 и ipv6) веб-ресурс с помощью демона cloudflared/warp через их CDN и их реверс-прокси

    P.S. Проброс трафика с копеечной vps с тоже возможен, правда это тоже костыль

    P.P.S. Это одна из причин, почему я - за ipv6


    1. Sunvas Автор
      22.08.2024 16:13
      +1

      В моих широтах IPv6 доступен с ~2016. Обходить cgnat про помощи vpn и прокси конечно же возможно, но для меня это костыли.


  1. eee
    22.08.2024 16:13
    +1

    Frigate не пробовали?


    1. Sunvas Автор
      22.08.2024 16:13

      1. npv3s
        22.08.2024 16:13

        Этот https://frigate.video


        1. Sunvas Автор
          22.08.2024 16:13

          Ознакомился. Мне кажется, оно избыточно для моей задачи. Плюс на главной прямо написано «...your camera feeds never leave your home», а мне нужно как раз обратное: дома вообще ничего не должно храниться.


          1. eee
            22.08.2024 16:13

            У меня как раз так и настроено. На даче две камеры, по SSTP коннект до квартиры по белому IP. В квартире сервак с Frigate, записывает по кругу на шпиндельный диск.


            1. Sunvas Автор
              22.08.2024 16:13

              Камеры сами напрямую коннектятся по SSTP или есть какой-то дополнительный узел?


              1. eee
                22.08.2024 16:13

                Коннектятся между собой роутеры Mikrotik


  1. Advisers
    22.08.2024 16:13
    +4

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


    1. kenomimi
      22.08.2024 16:13
      +1

      Ну как сказать дешевые... Мини-пк на интеле сравнимо стоят с мощными одноплатниками.


      1. Advisers
        22.08.2024 16:13

        Это да..., но факт, что и на дешёвых можно многое, вопрос скорее софта и развития индустрии.


  1. jackchickadee
    22.08.2024 16:13
    +1

    удаление устаревших файлов по дате-времени плохая практика.

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


    1. Sunvas Автор
      22.08.2024 16:13

      Почему плохая? Файлы на удалённом хранилище сохраняются одну неделю - мне этого вполне достаточно.

      Или вы о параметре recordDeleteAfter?


  1. eri
    22.08.2024 16:13

    Видеосервер классный, но ...

    Чтоб получить список видюшек он перечитывает mp4 файлы полностью - если записать 3 дня - ответ будет через 7 минут.

    Оно пропускает файлы. Если лежит порезанное по 20 минут - из 200 файлов отображаются 3-4.

    Внешняя база и парсер записей необходимы


  1. neobuh
    22.08.2024 16:13

    Подключение к Интернету с реальным IP-адресом. Если ваш провайдер предоставляет доступ к сети через CGNAT, организовать webrtc трансляцию не получится.

    Я вот подумал, провайдеры могли бы доп. услугу предоставлять, вместо полноценного белого IP, которых мало, предоставлять reverse-proxy, со своим DNS именем и сертификатом за недорого.


    1. Sunvas Автор
      22.08.2024 16:13

      Зачем эти костыли, если есть IPv6?