Replace the single fixed /records path with a list of storages and an
active selection (where new recordings go). Quota is now per-storage.
- config: StorageItem(id,name,type,path,quota_gb,nas-meta) + Storage keeps
global retention_days/segment_seconds; active + items. Migration from the
old single {path,quota_gb} schema → one local item.
- recorder: write to the active storage; restart_all() repoints on switch;
NAS-not-mounted guard (never write into the container overlay).
- indexer: scan ALL storage roots so recordings survive an active switch.
- retention: enforce quota PER storage via db.total_size_under /
oldest_recordings_under (path-prefix LIKE).
- api/storages: GET/POST/PUT/DELETE + activate + policy. NAS uses host-mount
(backend stores SMB params, generates the mount/fstab command, reports
ismount status). Retire old POST /api/storage.
- frontend: new "Хранилища" settings tab — table with inline per-row quota,
add form (local folder / NAS SMB), global policy (segment + retention).
- compose: add shared ./storages:/storages root for extra local folders and
host-mounted NAS shares.
VERSION 0.0.127.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The params row was a ragged flex-wrap and "Готовый профиль" was floated
with margin-left:auto, so controls didn't line up and the preset menu
dangled at an odd height. Split the row into a left grid (auto-fit
columns, controls bottom-aligned, full-width) and a separate right-side
"Готовый профиль" zone. Reorder fields logically: codec, H.264 profile,
preset, rate control, bitrate, QP, keyframe interval. Drop the now-dead
SOFT/MEDIUM/HARD button CSS.
VERSION -> 0.0.123.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The SOFT/MEDIUM/HARD selector lost its color coding when it became a
dropdown. Re-apply colors (SOFT red, MEDIUM yellow, HARD white) to the
options and to the select's shown value, and right-align the "Готовый
профиль" label (margin-left:auto) so it clearly sits on the right.
VERSION -> 0.0.122.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Double-clicking a grid cell now maximizes that camera ("solo") via a CSS
class on the grid instead of putting the tile into the browser Fullscreen
API. In fullscreen the soloed camera fills the screen; double-clicking
again returns to the grid (staying fullscreen). From windowed mode the
gesture also enters fullscreen so the camera fills the screen. ESC exits
fullscreen natively; on exit the solo state is cleared.
VERSION -> 0.0.121.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Style QP <input type=number> like the <select>s (it rendered with the
default white background -> stood out); add a disabled (greyed) style.
- QP vs bitrate are now mutually DISABLED instead of hidden: QP mode
greys the bitrate field, VBR/CBR greys the QP field. Hiding never
worked because .tr-row label{display:flex} overrode [hidden].
- Replace SOFT/MEDIUM/HARD preset buttons with a "Готовый профиль"
dropdown, placed last (rightmost) in the params row.
VERSION -> 0.0.120.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "Система" tab was a catch-all (Recording, Player & transcoding,
Storage, System info, Account). Split out two dedicated tabs:
- "Плеер": per-browser playback/transcode profiles. Kept at operator+
(the transcode option spawns server-side ffmpeg, i.e. CPU load).
- "Учётная запись": current user + logout. Ungated, so any signed-in
user (incl. viewers) can log out -- previously it was buried inside
the operator-only "Система" tab.
.tabs gets flex-wrap so the now-7 tabs wrap instead of overflowing.
VERSION -> 0.0.117.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>