dvr_admin/CHANGELOG.md
deeily f87c227330 Release dvr_admin v1.8.1: sync UI по PTS, ×16, slow-internet
- Heartbeat PLAYFAST каждые 3с с sock lock — стабильность потока на ускорении
- Переключение скорости только дельтой команд (без лишнего PLAYNORMAL)
- Диапазон 1/4…×16, добавлен Slow Forward (PLAYSLOW)
- Плашка "Slow internet" при отсутствии кадров
- Синхронизация UI по реальному PTS с DVR (MPEG-PS для H.265, PlayM4_GetSystemTime для H.264)
- Endpoint /playback/<ch>/pos + poll раз в 2с на клиенте
2026-04-13 16:08:10 +03:00

181 lines
15 KiB
Markdown
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.

# Changelog
Все значимые изменения фиксируются в этом файле.
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/).
## [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('"', '&quot;')`
- **Валидация параметров:** `channel`, `year`, `month` проверяются на допустимый формат и диапазон
до использования в XML-запросах и вычислениях
- **Контроль доступа:** `/api/dvr/<id>/ping` теперь проверяет права пользователя на конкретный DVR
- **Небезопасный ключ по умолчанию:** при запуске без `SECRET_KEY` выводится предупреждение в stderr
### Убрано
- Лишние папки и скрипты со старым кодом который уже нигде не используется
### Исправлено
- Удаление пользователя не срабатывало — клик всплывал на строку таблицы и перехватывался её `onclick`
- После добавления CSRF-защиты ломались пинги регистраторов (порядок загрузки скриптов)
- После выхода из просмотра канала предпросмотр не возобновлял поток
### Улучшено
- Предпросмотр каналов, плеер, календарь и таймлайн теперь полностью адаптируются к светлой/тёмной теме
- Кнопка «Войти» на странице логина: hover больше не сливается с фоном
- IP регистратора в шапке: обводка-кнопка без подчёркивания, появляется только после выбора DVR
- Архивный плеер: спиннер ожидания при загрузке потока (переключение режима, перемотка, клик по таймлайну)
- Архивный плеер: отображение текущего времени воспроизведения обновляется каждую секунду
- Таймлайн: убраны сегменты записей, метки каждый час (024) вместо каждых 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+