Skip to main content

Конфиги, скрипты, systemd

Готовые заготовки для пилота. Значения-плейсхолдеры (IP, логины) заменить своими.


1. cameras.csv — исходный список камер

Формат, под который заточены скрипты ниже:

name,ip,user,password
cam0001,10.10.1.11,admin,Passw0rd
cam0002,10.10.1.12,admin,Passw0rd
cam0003,10.10.1.13,admin,Passw0rd

2. go2rtc — генератор конфига из CSV

gen_go2rtc.py:

#!/usr/bin/env python3
"""Генерирует go2rtc.yaml из cameras.csv (name,ip,user,password).
На каждую камеру: основной поток (101) + субпоток (102)."""
import csv, sys

HEADER = """api:
listen: ":1984"
rtsp:
listen: ":8554"
webrtc:
listen: ":8555"
streams:
"""

def main(csv_path, out_path):
lines = [HEADER]
with open(csv_path, newline="") as f:
for row in csv.DictReader(f):
n, ip = row["name"], row["ip"]
u, p = row["user"], row["password"]
base = f"rtsp://{u}:{p}@{ip}:554/Streaming/Channels"
lines.append(f" {n}: {base}/101\n")
lines.append(f" {n}_sub: {base}/102\n")
with open(out_path, "w") as f:
f.write("".join(lines))
print(f"written {out_path}")

if __name__ == "__main__":
csv_path = sys.argv[1] if len(sys.argv) > 1 else "cameras.csv"
out_path = sys.argv[2] if len(sys.argv) > 2 else "go2rtc.yaml"
main(csv_path, out_path)

Запуск: python3 gen_go2rtc.py cameras.csv go2rtc.yaml


3. MediaMTX — генератор конфига из CSV

gen_mediamtx.py:

#!/usr/bin/env python3
"""Генерирует mediamtx.yml из cameras.csv.
На каждую камеру: основной (101, on-demand) + субпоток (102, on-demand)."""
import csv, sys

HEADER = """rtspAddress: :8554
hlsAddress: :8888
webrtcAddress: :8889
api: yes
apiAddress: :9997
paths:
"""

PATH_TMPL = """ {name}:
source: rtsp://{u}:{p}@{ip}:554/Streaming/Channels/101
sourceProtocol: tcp
sourceOnDemand: yes
sourceOnDemandCloseAfter: 10s
{name}_sub:
source: rtsp://{u}:{p}@{ip}:554/Streaming/Channels/102
sourceProtocol: tcp
sourceOnDemand: yes
sourceOnDemandCloseAfter: 10s
"""

def main(csv_path, out_path):
out = [HEADER]
with open(csv_path, newline="") as f:
for row in csv.DictReader(f):
out.append(PATH_TMPL.format(
name=row["name"], ip=row["ip"],
u=row["user"], p=row["password"]))
with open(out_path, "w") as f:
f.write("".join(out))
print(f"written {out_path}")

if __name__ == "__main__":
csv_path = sys.argv[1] if len(sys.argv) > 1 else "cameras.csv"
out_path = sys.argv[2] if len(sys.argv) > 2 else "mediamtx.yml"
main(csv_path, out_path)

4. systemd-юнит для go2rtc

/etc/systemd/system/go2rtc.service:

[Unit]
Description=go2rtc streaming relay
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=go2rtc
Group=go2rtc
ExecStart=/usr/local/bin/go2rtc -config /etc/go2rtc/go2rtc.yaml
Restart=always
RestartSec=5
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

Активация:

sudo useradd -r -s /usr/sbin/nologin go2rtc
sudo mkdir -p /etc/go2rtc
sudo cp go2rtc.yaml /etc/go2rtc/
sudo systemctl daemon-reload
sudo systemctl enable --now go2rtc
sudo systemctl status go2rtc

5. systemd-юнит для MediaMTX

/etc/systemd/system/mediamtx.service:

[Unit]
Description=MediaMTX streaming server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=mediamtx
Group=mediamtx
ExecStart=/usr/local/bin/mediamtx /etc/mediamtx/mediamtx.yml
Restart=always
RestartSec=5
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

LimitNOFILE поднят — на большом парке камер много открытых сокетов.


6. Заготовка HTML-мозаики (WebRTC, go2rtc)

grid.html — сетка нужных камер для руководства. Плитки подключаются к go2rtc по WebRTC при загрузке страницы (мгновенное переключение). Использует субпотоки.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Мониторинг</title>
<style>
body { margin:0; background:#111; }
.grid { display:grid; grid-template-columns:repeat(3,1fr); gap:2px; }
.grid iframe { width:100%; aspect-ratio:16/9; border:0; }
</style>
</head>
<body>
<div class="grid" id="grid"></div>
<script>
// Список камер для стены. Используем субпотоки (_sub) для лёгкости.
const SERVER = location.hostname + ":1984";
const cams = ["cam0001_sub","cam0002_sub","cam0003_sub",
"cam0004_sub","cam0005_sub","cam0006_sub"];
const grid = document.getElementById("grid");
for (const c of cams) {
const f = document.createElement("iframe");
f.src = `http://${SERVER}/webrtc.html?src=${c}`;
f.allow = "autoplay";
grid.appendChild(f);
}
</script>
</body>
</html>

Открывается по ссылке с любого устройства, ничего ставить не нужно. Количество колонок в grid-template-columns и список cams — под свои раскладки.


7. Проверка после запуска

# go2rtc жив, панель отвечает
curl -s http://localhost:1984/api/streams | head

# RTSP-поток тянется (нужен ffprobe из ffmpeg)
ffprobe -v error -rtsp_transport tcp rtsp://localhost:8554/cam0001

# в браузере
# http://<server>:1984/ — панель со списком
# http://<server>:1984/stream.html?src=cam0001 — один поток

iVMS-4200: Add Device → Custom Protocol / IP Channel → RTSP → rtsp://<server>:8554/cam0001.