Конфиги, скрипты, 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.