Video surveillance based on NanoPi R4S, rclone and mediamtx

In this article I will tell you how I organized a primitive video recorder for myself, which:

  1. It can broadcast video to any device that has a browser that supports h264, without using Chinese servers.

  2. Keep a loop recording in mp4 format and save it remotely.

  3. Costs less than $100.

Initially, I had the task of organizing a recorder that would continuously record everything that was happening from the cameras and upload the recordings to a remote server via a secure channel. Having mistakenly assumed that this was a completely trivial task, I bought myself a Dahua NVR NVR5208-EI recorder… Imagine my disappointment when it turned out that the purchased device contained a number of fatal flaws:

  1. Of the remote storages, only FTP/SFTP is supported. Moreover, it is impossible to connect to SFTP using an ssh key (only login and password).

  2. Saves video in unusable dav format. There is no convenient way to convert this mess to mp4.

  3. Gives these dav files some delirious names.

  4. It's not really configurable – the setup interface very meager.

  5. It's glitchy (sometimes it writes, sometimes it doesn't) and doesn't provide any logs.

Hidden text

The incompetence of the official support of dahuatech.com deserves a special mention. I purchased a remote FTP storage, where I intended to store records, but the recorder stubbornly could not connect to it. I connect to different devices without problems, but the recorder displays failed… Instead of helping to solve the problem, the support took the position of “There is something wrong with your server, sort it out yourself“And after that, my question was forwarded to the engineering department, after 2 weeks the answer came “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.» As a result, it was experimentally discovered that the Dahua equipment only works with OpenSSL version 3+, and 1.0.2k-fips was installed on the server…

Having realized the futility of moving towards ready-made registrars, I had to look for alternative options. As a result, I managed to create a stable solution based on R4S, rclone and mediamtx.

Necessary components:

  1. Internet connection with a real IP address. If your provider provides network access via CGNAT, you will not be able to organize webrtc broadcasting.

  2. Cameras capable of outputting RTSP stream in h264 format. Ideally, take cameras that can output 2 high-quality streams (h254 and h265) simultaneously. I use dahua IPC-HDW3841T-ZS-S2 cameras.

  3. Hosting, domain name, SSL certificate.

  4. Remote storage where video will be uploaded using rclone. SFTP, Yandex.Disk, Google Drive, Dropbox, etc. are supported.

  5. NanoPi R4S with OpenWRT (hereinafter referred to as R4S). It can be easily replaced with any single-board computer with Linux of similar power, but in this article I will use R4S. I use it as a router, but due to its excess power, it is quite capable of also acting as a recorder for 8 cameras.

Setting up cameras

For live webrtc broadcasting, you need to receive an RTSP stream from cameras with a resolution of 1920×1080, H264 video codec and G711 audio codec. To save the video, ideally receive another stream with H265 video codec, AAC audio codec and a resolution of 2560×1440.

Settings of one of my cameras

Settings of one of my cameras

Some clarifications:

  1. I don't use smart codec and AI codec. They seem to be buggy: only the size of the saved file increases.

  2. For saving, it is optimal to use CBR with a key frame at least once every 3 seconds. Bitrate and Framerate are selected individually. VBR is also suitable for broadcasting (especially via cellular networks).

Since the link to the RTSP stream contains a login and password, it is advisable to create a separate user to access the streams. In my case, the links look like this:

  • rtsp://rtsp:password@192.168.1.1/cam/realmonitor?channel=1&subtype=0 – for the main H265 stream

  • rtsp://rtsp:password@192.168.1.1/cam/realmonitor?channel=1&subtype=2 – for additional H264 stream.

Setting up R4S

On R4S you need to install OpenWRT. It is further assumed that the reader will be able to handle its initial setup and connect to the Internet.

Scheme of work: media server mediamtx continuously saves recordings from cameras in 5-minute fragments to a temporary directory. Every 3 minutes, files are transferred to the storage. Once a day, the storage is cleared of obsolete files.

We install it using standard tools rclone And luci-app-ttyd. From the main menu, go to Services => Terminal, log in, and use the command rclone config we launch interactive configurator and create a connection to a remote storage named main (will be found in configuration listings below).

In order not to wear out the memory card, it is optimal to store video files on the R4S in the temporary directory /tmp/cams, which is located in the RAM. By default, the section for temporary files is quite small… But the R4S has as many as 4 GB of RAM on board! For a router, 1 GB is more than enough, so we direct the remaining 3 GB to temporary storage. In System => Startup => Local Startup, we enter the command:

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

To apply the settings now without rebooting, you should also run this command in the terminal.

Now in the firewall settings we will open port 8889 through which webrtc broadcasting will be carried out.

In the firewall, we allow all incoming traffic to port 8889 R4S

In the firewall, we allow all incoming traffic to port 8889 R4S

Next, we create the directory /etc/config/mediamtx in which we will place the files:

  • certificate.crt And certificate.key – files with the SSL certificate and its private key.

  • rclone.sh – is launched by the task scheduler every 3 minutes and transfers video files to the storage. Contents:

#!/bin/sh

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

# Лог последнего переноса
date > /etc/config/mediamtx/move.log
#!/bin/sh

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

# Лог последнего удаления
date > /etc/config/mediamtx/delete.log
  • mediamtx And mediamtx.yml – files from the mediamtx distribution (executable file and configuration). Download is available at linkfor R4S we select the release for arm64v8.

In the task scheduler System => Scheduled Tasks we write the lines for execution rclone.sh And rclone_del.sh:

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

The mediamtx media server is supplied as an executable file. In order for it to run in the background and start with the system, it needs to be created initscript. Based on instructions create a file /etc/init.d/mediamtx (required with launch rights). Contents:

#!/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
}

Setting up mediamtx

In the configuration file /etc/config/mediamtx/mediamtx.yml find the record section and edit the following parameters:

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

Next we move on to the section paths: and configure the streams. For a camera that can give 2 streams, 2 entries are specified:

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

If there is only one stream, the entry looks like this:

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

If everything is configured correctly, after launching mediamtx, the following will become available from the local network: webrtc broadcasts by addresses http://r4s:8889/stream-nameand in the catalog /tmp/mediamtx/ mp4 files will start appearing. Also, the task scheduler should already be running and launching rclone every 3 minutes so that it uploads these files to the remote storage.

Setting up a domain

Using the fact that ssl with domain verification protects not only the domain itself, but also its www subdomain, you can save money and get by with just one such ssl: the domain should point to the hosting (where the application is located), and the www subdomain should point to R4S. Depending on how the provider provides you with a real IP (static IP or DDNS), for the www subdomain you need to enter the appropriate resource A, AAAA or CNAME record.

Back to mediamtx.ymlgo to the webrtc section and enter the ssl certificate and domain (example.net is given as an example):

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]

After restarting, the webrtc broadcast should become publicly available at https://www.example.net:8889/stream-name If everything is ok, we move on to the last stage.

Restricting access and viewing

Access to the broadcast, of course, should be limited. And I wanted to overload this small project with a complex authentication system and database. Fortunately, any hosting allows you to limit access to the selected directory by login and password. Based on framework7, a small SPA application the deployment of which comes down to 3 steps:

  1. Download all contents of the catalog build to the hosting (not necessarily to the root, it can also be to the directory).

  2. Restrict access to the directory build/restricted http authentication.

  3. Fill out the file build/restricted/cameras.jsonspecifying access to your streams.

 {
	"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}]
	]
}

List of material-icon icons publicly available. Using the last parameter, you can flip the camera image clockwise. {"rotate":90} or counterclockwise {"rotate":-90} arrows. This is especially convenient if the camera is filming a narrow passage and the installer has turned it 90°.

SPA Screenshots

SPA Screenshots

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *