English · Русский
У десктоп-приложения есть headless-режим веб-сервера: тот же самый бинарник,
запущенный с флагом --server-only, отдаёт браузерную консоль к вашим
OpenIPC-камерам по локальной сети. Без облака и лишних сервисов — один пароль
администратора и порт.
- Живой грид (1 / 4 / 9 / 16 / 25) с сохранёнными раскладками и страницами, просмотр отдельной камеры, полноэкранные тайлы. Видео не перезапускается при переходах между страницами.
- Управление камерами — добавить / изменить / удалить, группы, экспорт/импорт бэкапа конфигурации.
- Поиск камер в сети — ONVIF, mDNS и опциональный обход подсети, с добавлением найденного прямо из браузера.
- PTZ — поворот, наклон, зум и пресеты для камер, которые это умеют. Короткое нажатие на пульт сдвигает камеру на один шаг, удержание — плавно ведёт; «домой» и шаговые кнопки появляются, только если камера их поддерживает.
- Снимки — кадр с любой камеры, с возможностью скачать.
- Архив — запись камеры прямо из браузера, затем календарь, просмотр, скачивание и экспорт отмеченного фрагмента; перемотка работает, потому что файл отдаётся по диапазонам. Обе морды пишут в одни и те же папки и индекс, так что записанное здесь видно и в десктопе.
- Пользователи и права — учётные записи с флагами прав и, при желании, подмножеством камер на каждого.
- H.264 по WebSocket (fMP4 + MSE); H.265 транскодируется на лету. Одна ffmpeg-сессия раздаётся всем зрителям одной камеры.
- Работает из любого браузера в сети — телефон, планшет, другой ПК.
- Английский / русский, тёмный скин Console как у десктопа.
Читает и пишет ту же базу, что и десктоп-приложение, — камеры, добавленные в одном, видны в другом.
-
Скачайте релиз-архив под свою ОС и распакуйте (
openipc-viewer-win-x64.zip,-linux-x64.tar.gz,-osx-arm64.tar.gz) или соберите из исходников. -
Задайте пароль администратора (иначе на каждом старте генерируется случайный и печатается в лог — годится для быстрой пробы, но не для постоянного развёртывания).
-
Запустите с биндом на локальную сеть:
Linux / macOS
export OPENIPC_WEB_ADMIN_PASSWORD='придумайте-надёжный' ./OpenIPC.Viewer.Desktop --server-only --lan --port 8787
Windows (PowerShell)
$env:OPENIPC_WEB_ADMIN_PASSWORD = 'придумайте-надёжный' .\OpenIPC.Viewer.Desktop.exe --server-only --lan --port 8787
-
Откройте
http://<ip-этой-машины>:8787с любого устройства в сети и войдите какadminс заданным паролем.
Без --lan сервер слушает только 127.0.0.1 (доступен лишь с этой машины) — это
безопасный дефолт. --lan биндит 0.0.0.0 и печатает предупреждение, потому что на
этом уровне нет TLS; для всего, что за пределами доверенной локалки, поставьте его
за reverse-proxy.
| Флаг | Значение | По умолчанию |
|---|---|---|
--server-only |
Запуск headless как веб-сервер (без десктоп-GUI) | — |
--port <n> |
TCP-порт для прослушивания | 8787 |
--lan |
Бинд 0.0.0.0 (доступен из локальной сети) |
выкл. (только localhost) |
| Переменная окружения | Значение |
|---|---|
OPENIPC_WEB_ADMIN_PASSWORD |
Пароль встроенного админа. Не задан → случайный, печатается в лог. |
OPENIPC_WEB_SEGMENT_SECONDS |
Длина одного сегмента записи. По умолчанию 600 (10 мин). |
Четыре способа, все пишут в одну и ту же базу:
-
Найти в сети — Поиск → Искать. Пассивные источники (ONVIF WS-Discovery, mDNS) работают всегда; глубокий скан дополнительно обходит подсеть — находит камеры, которые о себе не заявляют, но со стороны выглядит как сканирование портов. Выберите устройство, введите логин, Опросить — сервер прочитает с камеры настоящий RTSP-адрес и возможности, затем Добавить.
-
Через веб-интерфейс — Камеры → + Добавить камеру.
-
Импорт бэкапа — Система → Импорт JSON-файла, экспортированного из десктоп-приложения или другого инстанса (Система → Экспорт конфига его создаёт; пароли камер в экспорт никогда не попадают).
-
Использовать данные десктопа — запустите сервер на машине, где десктоп уже настроен; он использует ту же локальную базу:
ОС Путь к базе Windows %LOCALAPPDATA%\OpenIPC.Viewer\openipc-viewer.dbLinux ~/.local/share/openipc-viewer/openipc-viewer.db($XDG_DATA_HOME)macOS ~/Library/Application Support/OpenIPC.Viewer/openipc-viewer.dbУчётные данные камер лежат в хранилище секретов ОС, а не в этом файле.
Из коробки есть одна учётная запись — встроенный администратор с паролем из
OPENIPC_WEB_ADMIN_PASSWORD. Пользователи → + Добавить пользователя заводит
остальных, у каждого свои права:
| Право | Что даёт |
|---|---|
смотреть эфир |
видеть список камер и живое видео |
PTZ |
двигать камеру и управлять её пресетами |
экспорт |
вырезать и скачать фрагмент записи |
управление |
всё, что меняет установку: камеры, группы, раскладки, поиск, бэкапы, сессии, пользователи |
и, при желании, подмножество камер: оставьте «Все камеры» для полного доступа или отметьте те, которые пользователю можно. Остальные для него не существуют — их нет ни в списке, ни в сетке, ни в API.
Список пользователей лежит рядом с базой в web-users.json (пароли — PBKDF2-хеши,
в открытом виде не хранятся). Встроенный администратор продолжает работать и
после добавления пользователей: это способ вернуться, если последний аккаунт с
правом «управление» потерян, — берегите его пароль.
Изменения прав применяются со следующего входа пользователя.
Живому видео нужен ffmpeg. Порядок поиска: сначала бандл рядом с приложением
(runtimes/<rid>/native/ffmpeg), затем (macOS) префиксы Homebrew, затем
ffmpeg в PATH.
- Windows — в комплекте с релиз-архивом. Ничего ставить не нужно.
- Linux — в комплекте с релиз-архивом; либо
sudo apt install ffmpeg. - macOS — в комплект не входит. Поставьте
brew install ffmpeg@7; приложение само найдёт его в префиксе Homebrew (keg-only,PATHправить не нужно).
Сервер говорит по обычному HTTP. Чтобы открыть его в интернет или из недоверенной
сети, терминируйте TLS на reverse-proxy и проксируйте на локальный порт. Сервер уже
учитывает X-Forwarded-* от loopback-прокси, а сессионная cookie автоматически
становится Secure, как только запросы приходят по HTTPS.
Caddy (автоматические сертификаты Let's Encrypt, WebSocket проходит как есть):
cameras.example.com {
reverse_proxy 127.0.0.1:8787
}Запускайте приложение без --lan (бинд на localhost), когда прокси на том же
хосте — больше ничего в сеть выставлять не нужно. Если прокси на другом хосте,
биндите с --lan и укажите IP прокси, чтобы его forwarded-заголовки считались
доверенными (иначе проверки Origin/CSRF отклонят проксированные запросы):
./OpenIPC.Viewer.Desktop --server-only --lan --port 8787
# и задайте доверенные IP прокси — см. WebServerOptions.TrustedProxiesnginx — эквивалент, нужны заголовки WebSocket-апгрейда:
location / {
proxy_pass http://127.0.0.1:8787;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # WebSocket живого видео
proxy_set_header Connection "upgrade";
}Linux (systemd) — /etc/systemd/system/openipc-web.service:
[Unit]
Description=OpenIPC Viewer web server
After=network.target
[Service]
Environment=OPENIPC_WEB_ADMIN_PASSWORD=придумайте-надёжный
ExecStart=/opt/openipc-viewer/OpenIPC.Viewer.Desktop --server-only --lan --port 8787
Restart=on-failure
User=openipc
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now openipc-webWindows — запуск при входе через «Планировщик заданий» или обёртка в сервис через
NSSM. Задайте OPENIPC_WEB_ADMIN_PASSWORD как машинную переменную
окружения, чтобы сервис её подхватил.
- По умолчанию localhost. Выставление в сеть (
--lan) — опциональный шаг с предупреждением. - Своего TLS нет — используйте reverse-proxy для HTTPS (выше).
- Учётные записи и права. Логин ограничен по частоте (5/мин/IP); сессии — непрозрачные
токены в cookie
HttpOnly,SameSite=Strictсо скользящим TTL 12 часов. Каждый запрос проверяется на сервере: интерфейс прячет недоступное, но защита — не в сокрытии. - Веб-сервер — отдельная дверь к вашим камерам. Кто дотянулся до порта и имеет учётную запись, получает всё, что позволяют его права, — с любой машины. Выставляйте сервер в сеть осознанно и давайте каждому только нужные ему камеры.
- Экспорт конфига никогда не содержит паролей камер.
- Health-check:
GET /healthz(без авторизации) возвращает{"status":"ok","version":"…"}.
dotnet publish src/OpenIPC.Viewer.Desktop -c Release -r linux-x64 \
--self-contained true -o publish
# Нужен Node — сборка компилирует React-морду и вшивает её.
./publish/OpenIPC.Viewer.Desktop --server-only --lan --port 8787Замените linux-x64 на win-x64 / osx-arm64 при необходимости.
Отдельного фронтенда в деплое нет. Браузерная морда — это SPA на React + Vite,
чей скомпилированный вывод вшивается внутрь серверного бинарника на этапе сборки, так
что в рантайме нет ни Node, ни dist/ для копирования, ни отдельного сервера статики —
только один исполняемый файл.
src/OpenIPC.Viewer.Web.Client React + TypeScript + Vite (исходники)
│ dotnet build / publish запускает MSBuild-таргет →
▼ npm run build (Vite выдаёт index.html + хешированные ассеты)
OpenIPC.Viewer.Web/wwwroot вывод сборки
│ вшивается как ресурсы в сборку →
▼
OpenIPC.Viewer.Web.dll скомпилированная SPA лежит *внутри* этой DLL
│ в рантайме Kestrel отдаёт её из памяти →
▼
GET / → встроенный index.html
GET /assets/* → встроенные JS / CSS
GET /grid, … → клиентские роуты SPA (fallback на index.html)Node — зависимость только этапа сборки (CI его ставит; сборка из исходников его требует). В скачанном релиз-архиве React-приложение уже впечено в бинарник. Такой подход (эмбед в DLL) ещё и означает, что веб-морда едет вместе со сборкой сервера независимо от того, какой хост её загружает, — а не зависит от специфичного для фреймворка пайплайна статических ассетов.