Files
CoRE.Vision/frontend/settings.html
T
git_admin 7060f26e86 cameras: surface per-camera REC (record-to-disk) toggle
`enabled` already gated recording only (go2rtc/live work regardless), but
it was a buried "Вкл" checkbox. Make it an explicit REC control:
- New "Запись" column with an inline REC switch in each camera row.
- Relabel the add/edit form toggle "Вкл" -> "REC" + tooltip.
- New POST /api/cameras/{id}/record {enabled} that flips recording through
  the supervisor only (no go2rtc re-sync, so live view doesn't blip).

Off = view-only (live via go2rtc); on = record segments to disk.
VERSION -> 0.0.124.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 18:21:49 +05:00

232 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CoRE.Vision — Настройки</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body data-page="settings">
<header>
<div class="brand">CoRE<span>.Vision</span></div>
<div class="spacer"></div>
<div class="stats" id="sys-stats"></div>
<div class="clock" id="clock"></div>
</header>
<div class="layout">
<aside>
<a class="nav-item" href="/" data-nav="live"><span class="ico"></span>Live view</a>
<div class="subnav">
<a class="subitem" data-grid="2" href="/?grid=2">4</a>
<a class="subitem" data-grid="3" href="/?grid=3">9</a>
<a class="subitem" data-grid="4" href="/?grid=4">16</a>
<a class="subitem" data-grid="5" href="/?grid=5">25</a>
<a class="subitem" data-grid="6" href="/?grid=6">36</a>
<a class="subitem" data-grid="7" href="/?grid=7">49</a>
<a class="subitem" data-grid="8" href="/?grid=8">64</a>
</div>
<a class="nav-item" href="/archive" data-nav="archive"><span class="ico">🗄</span>Архив</a>
<div class="aside-spacer"></div>
<a class="nav-item active" href="/settings" data-nav="settings"><span class="ico"></span>Настройки</a>
</aside>
<main class="settings-main">
<div class="tabs">
<button class="tab active" data-tab="cams" data-min-role="admin">Камеры</button>
<button class="tab" data-tab="layout">Раскладка</button>
<button class="tab" data-tab="player" data-min-role="operator">Плеер</button>
<button class="tab" data-tab="users" data-min-role="superadmin">Пользователи</button>
<button class="tab" data-tab="general" data-min-role="operator">Система</button>
<button class="tab" data-tab="optim" data-min-role="superadmin">Доп настройки</button>
</div>
<!-- ВКЛАДКА 1: Камеры -->
<div class="tab-panel" data-panel="cams" data-min-role="admin">
<div class="card">
<div class="card-head">
<h2>Камеры — 64 слота</h2>
<div style="display:flex;gap:8px">
<button id="bulk-edit">Изменить</button>
<button id="bulk-cancel" hidden>Отмена</button>
<button id="add-cam">+ Добавить камеру</button>
<button id="clear-cams" class="danger" title="Удалить все камеры (архив не трогается)">Очистить все</button>
</div>
</div>
<table class="cams">
<thead>
<tr><th style="width:48px">ID</th><th>Камера</th><th>IP</th><th>Потоки</th><th style="width:72px">Запись</th><th>Статус</th><th></th></tr>
</thead>
<tbody id="cam-rows"></tbody>
</table>
</div>
</div>
<!-- ВКЛАДКА 2: Система -->
<div class="tab-panel" data-panel="general" data-min-role="operator" hidden>
<div class="wrap">
<div class="card" data-min-role="admin">
<h2>Запись</h2>
<label class="fl" style="font-size:13px;color:var(--text)">Размер сегмента</label>
<select id="segment-size" style="margin-top:6px;display:block">
<option value="60">1 минута</option>
<option value="120">2 минуты</option>
<option value="300">5 минут</option>
<option value="600">10 минут</option>
<option value="900">15 минут</option>
</select>
<div style="margin-top:12px"><button id="segment-save">Сохранить</button></div>
<div class="muted" id="segment-saved" style="margin-top:8px;font-size:12px"></div>
</div>
<div class="card">
<h2>Хранилище</h2>
<div class="kv" id="storage-kv"><div class="muted">загрузка…</div></div>
</div>
<div class="card">
<h2>Система</h2>
<div class="kv" id="system-kv"><div class="muted">загрузка…</div></div>
</div>
</div>
</div>
<!-- ВКЛАДКА: Плеер и перекодирование (этот браузер) -->
<div class="tab-panel" data-panel="player" data-min-role="operator" hidden>
<div class="wrap">
<div class="card">
<h2>Плеер и перекодирование <span class="muted" style="font-weight:400;font-size:12px">— настройки этого браузера</span></h2>
<div class="muted" style="margin-top:-4px;margin-bottom:16px;font-size:12px">
Для каждого потока выберите способ воспроизведения: <b>как есть</b>
поток отдаётся без обработки (ffmpeg -c copy), браузер декодирует HEVC сам
(нужна аппаратная поддержка); <b>встроенный плеер</b> — декодирует H.265
в браузере софтом (WASM hevc.js, в Web Worker), тянет и основной поток
(3200×1800, включая тайлы), и субпоток, без нагрузки на сервер (декод
нагружает CPU клиента); <b>WebCodecs (железо)</b> — аппаратный декод H.265 на GPU клиента,
тянет основной поток 3200×1800 при 0% CPU сервера (рекомендуется для
основного потока); <b>перекодировать</b> — сервер транскодирует в H.264 /
VP9 (нагрузка на CPU сервера, для слабых клиентов).
</div>
<!-- 3 независимых профиля: 1 поток / 2 поток / архив -->
<div class="tr-block" data-tr="1">
<h3>1 поток (основной)</h3>
<div class="seg-toggle">
<label><input type="radio" name="mode-1" value="native"><span>Как есть</span></label>
<label><input type="radio" name="mode-1" value="player"><span>Встроенный плеер</span></label>
<label><input type="radio" name="mode-1" value="webcodecs"><span>WebCodecs (железо)</span></label>
<label><input type="radio" name="mode-1" value="transcode"><span>Перекодировать</span></label>
</div>
<div class="tr-row"></div>
</div>
<div class="tr-block" data-tr="2">
<h3>2 поток (суб)</h3>
<div class="seg-toggle">
<label><input type="radio" name="mode-2" value="native"><span>Как есть</span></label>
<label><input type="radio" name="mode-2" value="player"><span>Встроенный плеер</span></label>
<label><input type="radio" name="mode-2" value="webcodecs"><span>WebCodecs (железо)</span></label>
<label><input type="radio" name="mode-2" value="transcode"><span>Перекодировать</span></label>
</div>
<div class="tr-row"></div>
</div>
<div class="tr-block" data-tr="a">
<h3>Архив</h3>
<div class="seg-toggle">
<label><input type="radio" name="mode-a" value="native"><span>Как есть</span></label>
<label><input type="radio" name="mode-a" value="player"><span>Встроенный плеер</span></label>
<label><input type="radio" name="mode-a" value="transcode"><span>Перекодировать</span></label>
</div>
<div class="tr-row"></div>
</div>
<div style="margin-top:16px"><button id="prefs-save">Сохранить</button></div>
<div class="muted" id="prefs-saved" style="margin-top:8px;font-size:12px">Сохраняется в этом браузере</div>
</div>
</div>
</div>
<!-- ВКЛАДКА: Раскладка (назначение камер по ячейкам, этот браузер) -->
<div class="tab-panel" data-panel="layout" hidden>
<div class="card">
<div class="card-head">
<h2>Настройка раскладки</h2>
<div style="display:flex;align-items:center;gap:10px">
<label class="muted">Раскладка:</label>
<select id="layout-dim">
<option value="2">4 (2×2)</option>
<option value="3">9 (3×3)</option>
<option value="4">16 (4×4)</option>
<option value="5">25 (5×5)</option>
<option value="6">36 (6×6)</option>
<option value="7">49 (7×7)</option>
<option value="8">64 (8×8)</option>
</select>
<button id="layout-save">Сохранить</button>
</div>
</div>
<div class="muted" style="margin-bottom:12px">Назначьте камеру в каждую ячейку раскладки. Сохраняется в этом браузере.</div>
<div id="layout-grid" class="layout-grid"></div>
<div class="muted" id="layout-saved" style="margin-top:12px;font-size:12px"></div>
</div>
</div>
<!-- ВКЛАДКА: Доп настройки (только суперадмин) -->
<div class="tab-panel" data-panel="optim" data-min-role="superadmin" hidden>
<div class="wrap">
<div class="card">
<h2>Live view <span class="muted" style="font-weight:400;font-size:12px">— общая политика для всех клиентов</span></h2>
<label class="toggle" style="color:var(--text)">
<input type="checkbox" id="single-main">
Не более одного основного потока в режиме Live view
</label>
<div class="muted" style="margin-top:8px;font-size:12px">
Включено по умолчанию. Основной (HD) поток можно держать одновременно
только в одной ячейке — при переключении другой ячейки на «1»
предыдущая вернётся на субпоток. Снижает нагрузку на сеть и камеры.
</div>
<label class="toggle" style="color:var(--text);margin-top:18px">
<input type="checkbox" id="mode-16plus">
Режим 16+
</label>
<div class="muted" style="margin-top:8px;font-size:12px">
По умолчанию в Live view доступно не более 16 камер (сетки до 4×4).
Включите «16+», чтобы открыть раскладки 25 / 36 / 49 / 64.
</div>
<div class="muted" style="margin-top:12px;font-size:12px">
<b>Менять может только суперадмин с подтверждением пароля.</b>
</div>
<div style="margin-top:14px"><button id="optim-save">Сохранить</button></div>
<div class="muted" id="optim-saved" style="margin-top:8px;font-size:12px">Смена требует пароль</div>
</div>
</div>
</div>
<!-- ВКЛАДКА 4: Пользователи (только суперадмин) -->
<div class="tab-panel" data-panel="users" data-min-role="superadmin" hidden>
<div class="card">
<h2>Учётная запись</h2>
<div class="muted" id="me-info" style="margin-bottom:10px;font-size:13px"></div>
<button id="logout">Выйти из системы</button>
</div>
<div class="card">
<div class="card-head">
<h2>Пользователи и роли</h2>
<button id="add-user">+ Добавить пользователя</button>
</div>
<table class="cams">
<thead>
<tr><th>Логин</th><th style="width:160px">Роль</th><th style="width:220px">Пароль</th><th style="width:120px"></th></tr>
</thead>
<tbody id="user-rows"></tbody>
</table>
<div class="muted" id="users-msg" style="margin-top:10px;font-size:12px"></div>
</div>
</div>
</main>
</div>
<script src="/static/app.js"></script>
</body>
</html>