- Выбор режима SDK (auto/shttp/native) для каждого регистратора - Раздел «Логи» в сайдбаре (только для администраторов) - Сворачиваемая боковая панель с сохранением состояния в localStorage - Прошивка регистраторов на дашборде (firmwareVersion из ISAPI) - Высота шапки 44 px — квадрат при свёрнутой панели - Новые иконки: видеокамера (Просмотр), звёздочка (Мои виды) - Дашборд пользователей: скрыты IP, модель и прошивка - Исправлено дублирование кнопки «Добавить» на странице Регистраторов
208 lines
17 KiB
Markdown
208 lines
17 KiB
Markdown
# Changelog
|
||
|
||
Все значимые изменения фиксируются в этом файле.
|
||
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/).
|
||
|
||
|
||
## [1.8.2] — 2026-04-13
|
||
|
||
### Добавлено
|
||
- **Выбор режима SDK для каждого регистратора** на вкладке «Регистраторы»:
|
||
- **Авто** (по умолчанию) — сначала SDK HTTP, при неудаче fallback на Native SDK → RTSP+PlayM4 → ffmpeg
|
||
- **HTTP SDK** — только SDK-over-HTTP (PLAYFAST/PLAYSLOW/PTS-sync), без fallback'ов
|
||
- **Native SDK** — только classic SDK-логин (`NET_DVR_Login_V40`), SDK HTTP пропускается
|
||
- Селект режима в таблице списка DVR (инлайн, сразу применяется) и в модалках добавления/редактирования
|
||
- Новый endpoint `POST /dvrs/<id>/sdk_mode` для быстрого переключения
|
||
- При смене режима кэши `_shttp_failed_ips`/`_shttp_ok_ips`/`_sdk_failed_ips` сбрасываются для этого IP, чтобы новый режим вступил в силу с ближайшей сессии
|
||
- **Раздел «Логи»** в сайдбаре (только администраторы): буфер последних 5000 строк (Flask + werkzeug), фильтры DBG/INF/WARN/CRIT, фильтр по дате, полнотекстовый поиск, автообновление 5 с
|
||
- **Сворачиваемая боковая панель**: два состояния — развёрнутая (иконки + подписи) и свёрнутая (только иконки 44 px); состояние сохраняется в `localStorage`
|
||
- **Прошивка регистратора** на дашборде: новая колонка «Прошивка» получает `firmwareVersion` через `/ISAPI/System/deviceInfo`
|
||
|
||
### Улучшено
|
||
- Высота шапки и логотипа уменьшена до 44 px — при свёрнутой панели в углу образуется точный квадрат
|
||
- Иконка раздела «Просмотр» заменена на значок видеокамеры, «Мои виды» — на звёздочку (избранное)
|
||
- Дашборд для обычных пользователей: скрыты колонки IP, Модель и Прошивка — отображаются только Название, Концепция и Статус
|
||
|
||
### Исправлено
|
||
- На странице «Регистраторы» дублировалась кнопка «Добавить» (появлялась и в топбаре, и в контенте)
|
||
|
||
### База данных
|
||
- Колонка `sdk_mode TEXT NOT NULL DEFAULT 'auto'` в таблице `dvrs` (автоматическая миграция через `ALTER TABLE IF NOT EXISTS`)
|
||
|
||
---
|
||
|
||
## [1.8.1] — 2026-04-13
|
||
|
||
### Добавлено
|
||
- **Ускорение архива до ×16** (раньше максимум был ×4): теперь диапазон 1/4 · 1/2 · ×1 · ×2 · ×4 · ×8 · ×16
|
||
- **Замедление воспроизведения** (Slow Forward) через SDK HTTP команду PLAYSLOW (0x0003010A): 1/2 и 1/4
|
||
- **Плашка «Slow internet»** поверх видео — красное предупреждение при отсутствии кадров >1.5с (на ускорении) или >2.5с (на ×1)
|
||
- **Синхронизация UI-времени по реальному timestamp с DVR**: часы в интерфейсе теперь идут в ногу с OSD на видео при любой скорости
|
||
- H.265: парсер MPEG-PS извлекает PTS из PES-заголовков каждого видеокадра
|
||
- H.264: `PlayM4_GetSystemTime()` возвращает абсолютное время декодированного кадра
|
||
- Новый endpoint `/view/<dvr_id>/playback/<ch>/pos` отдаёт `video_ms` от начала воспроизведения
|
||
- Клиент раз в 2 секунды запрашивает позицию и подгоняет `_pbWall` под ответ сервера
|
||
- **Поддерживаемые скорости на сервере**: `{-4, -2, 1, 2, 4, 8, 16}` (iRate как в jsVideoPlugin)
|
||
|
||
### Исправлено
|
||
- **Обрыв потока на ×4/×8/×16 через ~6 секунд**: DVR требует heartbeat-пакет PLAYFAST каждые ровно 3 секунды (подтверждено pcap-трассировкой оригинального плагина) — добавлен отдельный поток heartbeat-а с `threading.Event.wait(3.0)`
|
||
- **Повреждение данных в сокете** при одновременной записи из heartbeat-треда и основного ридера — добавлен `threading.Lock()` на все `sock.sendall()`
|
||
- **Развал потока при переходе ×2→×4→×8**: убран лишний `PLAYNORMAL` между последовательными ускорениями. Теперь отправляется только дельта команд (как делает оригинальный плагин в трассировке): ×2→×4 = 1×PLAYFAST, а не `PLAYNORMAL + 2×PLAYFAST`
|
||
- **Накопление рассинхрона UI/видео** на высоких скоростях: формула `wall_clock × rate` давала дрейф до 30+ секунд. Полностью заменена на синхронизацию по PTS/SystemTime с сервера
|
||
- **Замирание UI-часов при зависшем потоке**: детекция stale-кадров (>1.5с gap) останавливает счётчик времени, при возобновлении корректно доигрывает
|
||
|
||
### Технические детали
|
||
- Добавлена поддержка 33-битной обёртки PTS в парсере PES
|
||
- Поля `pts_base` / `video_ms` в `ChannelBuffer` для хранения видео-времени
|
||
- Функция `_rate_idx()` конвертирует rate (×1/×2/×4/−2/−4/…) в индекс (0/1/2/−1/−2) — упрощает расчёт дельты команд в `_set_speed`
|
||
- Команды SDK HTTP binary: `PLAYSTART=0x103`, `PLAYNORMAL=0x107`, `PLAYFAST=0x109`, `PLAYSLOW=0x10A`
|
||
|
||
---
|
||
|
||
## [1.8] — 2026-04-09
|
||
|
||
### Добавлено
|
||
- **Плавное ускоренное воспроизведение архива (×2, ×4, ×16)** через Hikvision SDK-over-HTTP протокол:
|
||
все кадры отрисовываются на реальной скорости, без прыжков по таймлайну
|
||
- SDK HTTP: Digest-аутентификация на сокете (2-step: получение nonce → запрос с Digest)
|
||
- SDK HTTP: команда PLAYFAST (0x00030109) для смены скорости без переподключения
|
||
- H.265 декодирование: парсинг MPEG-PS → извлечение H.265 elementary stream → декодирование через ffmpeg
|
||
- H.264 декодирование: PlayM4 (`libPlayCtrl.so`) для потоков с `codec_flags=01`
|
||
- Автоопределение кодека по IMKH-заголовку (`codec_flags[0]`: 01=H.264, 02=H.265)
|
||
|
||
### Исправлено
|
||
- SDK HTTP: deadlock при чтении ffmpeg stdout (отдельный поток для чтения)
|
||
- Prefetch endpoint: `NameError: _td` при клике по таймлайну
|
||
- Ускорение ×2/×4/×16 через native SDK (PlayM4_Fast + NET_DVR_PlayBackControl) не давало визуального эффекта — заменено на SDK HTTP PLAYFAST
|
||
|
||
---
|
||
|
||
## [1.7] — 2026-04-07
|
||
|
||
### Добавлено
|
||
- **Мои виды** — новый раздел в боковом меню: пользователь создаёт произвольные виды с любым набором камер из разрешённых ему регистраторов
|
||
- Камеры в виде перетаскиваются (drag-and-drop), порядок сохраняется
|
||
- Редактор вида: модальное окно с переименованием и управлением камерами (выбор по DVR с чекбоксами)
|
||
- SSE-эндпоинт `/api/myview/sse` — единый поток превью для камер с разных регистраторов
|
||
- Полноэкранный плеер (прямой эфир + архив + скачивание клипа) доступен из «Мои виды»
|
||
- Переименование каналов в «Мои виды»: каждый пользователь задаёт своё название, сохраняется в БД
|
||
- Версия приложения вынесена в константу `APP_VERSION` в начале скрипта
|
||
|
||
### Улучшено
|
||
- Архивный плеер: окно воспроизведения расширено с 1 до 24 часов — длинные записи больше не обрываются
|
||
- Архивный плеер: FPS берётся с регистратора через ISAPI (`maxFrameRate`), фоллбэк 20 fps
|
||
- Архивный плеер: при переключении времени (клик по таймлайну) предыдущий поток явно завершается — нет параллельных соединений
|
||
- Архивный плеер: ffmpeg-путь тоже throttle до реального FPS — потребление памяти при просмотре архива снижено
|
||
|
||
---
|
||
|
||
## [1.6.1] — 2026-04-07
|
||
|
||
### Улучшено
|
||
- Скачивание клипа: прогресс-бар с двумя фазами — «Загрузка с DVR» (байты / процент) и «Конвертация»
|
||
- Скачивание клипа: задание выполняется в фоновом потоке, браузер не блокируется
|
||
- Кнопка «Отменить» прерывает фоновое задание и сигнализирует SDK прекратить приём данных
|
||
|
||
---
|
||
|
||
## [1.6] — 2026-04-07
|
||
|
||
### Исправлено
|
||
- Скачивание клипов переведено на Hikvision SDK (`PlayBackByTime_V40` + data callback):
|
||
точное время начала по часам DVR, без seek-смещения
|
||
- SDK-библиотеки загружаются корректно: процесс перезапускается с правильным `LD_LIBRARY_PATH`,
|
||
чтобы `libPlayCtrl.so` находила зависимость `libAudioRender.so`
|
||
|
||
---
|
||
|
||
## [1.5] — 2026-04-06
|
||
|
||
### Добавлено
|
||
- Дашборд обычного пользователя: карточки «Время» (живые часы) и «Версия»
|
||
- Дашборд: обычный пользователь видит только разрешённые ему регистраторы
|
||
- IP регистратора в шапке предпросмотра — кликабельная ссылка на веб-интерфейс устройства
|
||
|
||
### Безопасность
|
||
- **CSRF-защита:** все state-changing запросы (POST/PUT/DELETE) проверяют токен сессии;
|
||
токен автоматически добавляется в формы и fetch-запросы через JavaScript
|
||
- **Куки сессии:** установлены флаги `HttpOnly` и `SameSite=Lax` — куки недоступны из JS
|
||
и не отправляются при кросс-сайтовых запросах
|
||
- **Открытый редирект:** параметр `next` после логина принимается только как относительный путь,
|
||
исключая редирект на внешние домены
|
||
- **XSS:** все пользовательские данные в HTML-шаблонах экранируются через `html.escape()`
|
||
вместо частичного `replace('"', '"')`
|
||
- **Валидация параметров:** `channel`, `year`, `month` проверяются на допустимый формат и диапазон
|
||
до использования в XML-запросах и вычислениях
|
||
- **Контроль доступа:** `/api/dvr/<id>/ping` теперь проверяет права пользователя на конкретный DVR
|
||
- **Небезопасный ключ по умолчанию:** при запуске без `SECRET_KEY` выводится предупреждение в stderr
|
||
|
||
### Убрано
|
||
- Лишние папки и скрипты со старым кодом который уже нигде не используется
|
||
|
||
### Исправлено
|
||
- Удаление пользователя не срабатывало — клик всплывал на строку таблицы и перехватывался её `onclick`
|
||
- После добавления CSRF-защиты ломались пинги регистраторов (порядок загрузки скриптов)
|
||
- После выхода из просмотра канала предпросмотр не возобновлял поток
|
||
|
||
### Улучшено
|
||
- Предпросмотр каналов, плеер, календарь и таймлайн теперь полностью адаптируются к светлой/тёмной теме
|
||
- Кнопка «Войти» на странице логина: hover больше не сливается с фоном
|
||
- IP регистратора в шапке: обводка-кнопка без подчёркивания, появляется только после выбора DVR
|
||
- Архивный плеер: спиннер ожидания при загрузке потока (переключение режима, перемотка, клик по таймлайну)
|
||
- Архивный плеер: отображение текущего времени воспроизведения обновляется каждую секунду
|
||
- Таймлайн: убраны сегменты записей, метки каждый час (0–24) вместо каждых 3 часов
|
||
- Скачивание клипа: поля времени разбиты на отдельные ЧЧ / ММ / СС — каждая часть редактируется независимо
|
||
- Скачивание клипа: кнопка «Отменить» прерывает загрузку и завершает ffmpeg-процесс на сервере
|
||
|
||
---
|
||
|
||
## [1.4] — 2026-04-05
|
||
|
||
### Добавлено
|
||
- Сохранение пользовательского порядка каналов предпросмотра (drag-and-drop, per-user)
|
||
|
||
---
|
||
|
||
## [1.2] — 2026-04-05
|
||
|
||
### Добавлено
|
||
- Смена пароля веб-пользователей (включая admin)
|
||
- Отключение/включение учётных записей (включая admin)
|
||
- Docker-контейнер: `dvr_admin_docker/` с Gunicorn, инструкция деплоя `DEPLOY.md`
|
||
- Ключ шифрования Fernet через переменную окружения `FERNET_KEY`
|
||
|
||
### Исправлено
|
||
- Скачивание клипа всегда начиналось с начала сегмента — теперь с запрошенного времени (byte-range seek)
|
||
- Колонки таблицы веб-пользователей съезжали при добавлении колонки «Статус»
|
||
|
||
---
|
||
|
||
## [1.1] — 2026-04-03
|
||
|
||
### Добавлено
|
||
- Панель сохранения клипа: выбор времени начала/конца, формат mp4/mkv/gif
|
||
- Быстрое скачивание клипов через ISAPI HTTP download (~14 MB/s вместо RTSP)
|
||
- YouTube-подобный спиннер загрузки для предпросмотра, основного потока и архива
|
||
- Адаптивный FPS основного потока и архива (подстраивается под DVR)
|
||
|
||
### Исправлено
|
||
- ffmpeg-процессы не завершались при переключении между DVR — утечка CPU
|
||
- Предпросмотр не загружался на DVR со спецсимволами в пароле (`;#{}]`)
|
||
- Клипы скачивались с начала сегмента вместо запрошенного времени
|
||
|
||
### Улучшено
|
||
- Предпросмотр: 1 fps на канал через `-skip_frame noref` (снижение нагрузки на CPU)
|
||
- SSE-поток предпросмотра ставится на паузу при открытии полноэкранного плеера
|
||
|
||
---
|
||
|
||
## [1.0] — 2026-04-01
|
||
|
||
### Добавлено
|
||
- Централизованное управление регистраторами Hikvision
|
||
- Авторизация с bcrypt, шифрование паролей DVR через Fernet
|
||
- Предпросмотр каналов через SSE (Server-Sent Events)
|
||
- Просмотр архива с календарём и треком записей
|
||
- Управление пользователями и правами доступа к DVR/концепциям
|
||
- Поддержка Hikvision SDK (libhcnetsdk, libPlayCtrl) для Hi-Watch HEVC+
|