Skip to content

Latest commit

 

History

History
448 lines (346 loc) · 21.5 KB

ROADMAP.md

File metadata and controls

448 lines (346 loc) · 21.5 KB

План развития

Дорожная карта развития OpenIPC NVR по трём направлениям: мобильное приложение, GPU-ускорение детекции и интеграция с Home Assistant.


Содержание

  1. Мобильное приложение
  2. AI-детекция с NVIDIA CUDA
  3. Интеграция с Home Assistant
  4. Порядок работ

1. Мобильное приложение

Цель

Просмотр потоков, push-уведомления о событиях и открытие дверей СКУД с телефона.

Выбор технологии

Вариант Плюсы Минусы Решение
Flutter Один код на iOS и Android, нативный плеер через video_player, хорошая работа с HLS Dart в команде ✅ Основной
React Native Переиспользование знаний React, общая кодовая база с веб-интерфейсом Проблемы с фоновым видео и push ⬜ Резерв
Нативные (Swift/Kotlin) Максимальная производительность и доступ к API Двойная работа ❌

Решение: Flutter. Команда уже знакома с React, но для видеоплеера и push-уведомлений критичны нативные возможности, а Flutter даёт к ним прямой доступ при единой кодовой базе.

Архитектура

lib/
├── main.dart
├── api/
│   ├── client.dart          # HTTP-клиент, JWT, автообновление токена
│   └── models/              # Camera, Event, Recording, ACSController
├── screens/
│   ├── login_screen.dart
│   ├── cameras_screen.dart  # сетка превью
│   ├── player_screen.dart   # полноэкранный плеер + PTZ-жесты
│   ├── events_screen.dart
│   ├── recordings_screen.dart
│   └── acs_screen.dart      # открытие дверей
├── widgets/
│   ├── camera_tile.dart
│   ├── ptz_control.dart     # свайпы для поворота
│   └── event_card.dart
└── services/
    ├── push_service.dart    # FCM / APNs
    └── storage.dart         # защищённое хранение токена

Этапы

Этап 1. Базовая версия (2–3 недели)

  • Авторизация, хранение токена в flutter_secure_storage
  • Список камер с превью из /snapshot, обновление раз в 10 секунд
  • Полноэкранный плеер HLS через video_player
  • Выбор основного и дополнительного потока

Этап 2. События и уведомления (2 недели)

  • Лента событий с фильтром по камере и классу объекта
  • Push-уведомления: требуется завершить серверную часть (POST /notifications/register, отправка через FCM)
  • Просмотр кадра события крупным планом

Этап 3. PTZ и архив (1–2 недели)

  • Управление поворотом свайпами по экрану плеера
  • Зум щипком
  • Пресеты камер
  • Просмотр архива: выбор интервала, воспроизведение

Этап 4. СКУД и полировка (1–2 недели)

  • Список контроллеров и дверей, открытие по нажатию с подтверждением
  • События проходной с фотографиями
  • Тёмная тема, оффлайн-режим для списка камер

Технические решения

Задача Решение
Видео HLS для совместимости, WebRTC — при потребности в низкой задержке
Плеер video_player (нативный), при проблемах — better_player
Push firebase_messaging, токен через /notifications/register
Токен flutter_secure_storage (Keychain / Keystore)
Сеть dio с перехватчиком для JWT
Состояние Riverpod

Что требуется от серверной части

  1. Эндпоинт регистрации push-токена. Таблица push_tokens уже есть, нужен обработчик и отправка.
  2. Отдача снапшотов. Готово.
  3. WebRTC-сигнализация. go2rtc отдаёт WebRTC по WHEP (и MSE для браузера), но нужен удобный эндпоинт для мобильных клиентов.
  4. Обновление токена. Добавить POST /auth/refresh, чтобы не требовать повторного ввода пароля.

2. AI-детекция с NVIDIA CUDA

Текущее состояние

Детектор работает на CPU через ultralytics:

RTSP → ffmpeg (1 FPS) → NATS → YOLOv8 (CPU) → NATS → PostgreSQL

Производительность на CPU: примерно 5–10 кадров/с для модели yolov8n при разрешении 640×640. Этого хватает для 5–10 камер при частоте 1 кадр/с.

Цель

Обрабатывать 30–50 камер с частотой 5–10 кадров/с на одной GPU.

Варианты реализации

Вариант Плюсы Минусы Решение
ONNX Runtime + CUDA Максимальная скорость, минимальные зависимости, стабильный API Нужно экспортировать модель и писать пред/постобработку ✅ Основной
TensorRT Наивысшая производительность Жёсткая привязка к версии GPU и драйвера, сложная сборка ⬜ Для максимальной нагрузки
PyTorch + CUDA Минимум изменений в коде Тяжёлые зависимости, выше потребление памяти ⬜ Быстрый старт
Triton Inference Server Масштабирование, батчинг Отдельный сервис, сложнее эксплуатация ⬜ При росте

Решение: ONNX Runtime с провайдером CUDA. Даёт 5–10-кратный прирост относительно CPU, остается кроссплатформенным (можно откатиться на CPU без изменения кода) и не требует сборки под конкретную видеокарту.

Архитектура

┌──────────────┐   NATS    ┌─────────────────────────────────┐
│ frame        │──────────▶│  AI Worker (пул процессов)      │
│ publisher    │  кадры    │  ┌───────────────────────────┐  │
│ (по камере)  │           │  │ Батчер: собирает кадры    │  │
└──────────────┘           │  │ от разных камер в пакет   │  │
                           │  └─────────────┬─────────────┘  │
                           │                ▼                │
                           │  ┌───────────────────────────┐  │
                           │  │ ONNX Runtime + CUDA       │  │
                           │  │ YOLOv8, батч 8–16         │  │
                           │  └─────────────┬─────────────┘  │
                           │                ▼                │
                           │  ┌───────────────────────────┐  │
                           │  │ ByteTrack: трекинг        │  │
                           │  └───────────────────────────┘  │
                           └───────────────┬─────────────────┘
                                           │ NATS
                                           ▼
                                   события в PostgreSQL

Ключевая оптимизация — батчинг: кадры от разных камер собираются в пакет и обрабатываются за один проход GPU. Это даёт кратный прирост относительно покадровой обработки.

Этапы

Этап 1. Экспорт модели и замеры (3–5 дней)

# Экспорт в ONNX
yolo export model=yolov8n.pt format=onnx imgsz=640 half=True dynamic=True

# Проверка провайдеров
python -c "import onnxruntime as ort; print(ort.get_available_providers())"
# Ожидается: ['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']

Замерить базовую производительность на CPU и GPU, зафиксировать метрики: кадров/с, задержка, потребление видеопамяти.

Этап 2. GPU-детектор (1–2 недели)

  • Подготовка входного тензора: ресайз с сохранением пропорций, нормализация
  • Постобработка: фильтрация по уверенности, NMS
  • Батчинг кадров от нескольких камер
  • Отслеживание объектов (ByteTrack) с сохранением состояния по камерам
  • Настройка через переменные окружения:
Переменная Значение по умолчанию Описание
DEVICE auto auto, cuda, cpu
BATCH_SIZE 8 Кадров в пакете
CONFIDENCE 0.4 Порог уверенности
HALF_PRECISION true FP16 для ускорения
MAX_QUEUE 32 Ограничение очереди кадров

Этап 3. Оптимизация (1 неделя)

  • Проверить влияние FP16 на точность (обычно потеря менее 1%)
  • Профилировать узкие места: копирование памяти, предобработка
  • При необходимости — экспорт в TensorRT
  • Бенчмарк на целевом числе камер

Этап 4. Эксплуатация (3–5 дней)

  • Docker-образ с поддержкой GPU (nvidia-container-toolkit)
  • Метрики: загрузка GPU, очередь кадров, пропущенные кадры
  • Поведение при недоступности GPU: автоматический откат на CPU
  • Healthcheck

Docker для GPU

FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04

RUN apt-get update && apt-get install -y python3 python3-pip ffmpeg && \
    rm -rf /var/lib/apt/lists/*

RUN pip install --no-cache-dir onnxruntime-gpu ultralytics opencv-python-headless nats-py

COPY . /app
WORKDIR /app
ENTRYPOINT ["python3", "main_gpu.py"]

Запуск:

ai-detector:
  build: ./ai-detector
  deploy:
    resources:
      reservations:
        devices:
          - driver: nvidia
            count: 1
            capabilities: [gpu]
  environment:
    DEVICE: cuda
    BATCH_SIZE: "16"

Требуется установленный nvidia-container-toolkit на хосте.

Ожидаемые результаты

Конфигурация Кадров/с Камер при 1 кадр/с
CPU, 8 ядер 8 8
RTX 3060, батч 8 80–120 до 100
RTX 4090, батч 16 300+ ограничено сетью

Развитие модели

  • Обучение под задачу. Базовая модель YOLOv8 знает 80 классов COCO. Для распознавания номеров, спецодежды и лиц нужно дообучение на собственном датасете.
  • Классификация транспорта. Различать легковые, грузовые, автобусы.
  • Распознавание номеров — отдельная модель, привязка к треку транспорта.
  • Детекция оставленных предметов — анализ статичных объектов в зоне.

3. Интеграция с Home Assistant

Цель

Видеть камеры, события и управлять дверями из интерфейса умного дома.

Вариант интеграции

Есть два подхода:

Подход Плюсы Минусы Решение
Собственная интеграция (HACS) Полный контроль, нативные сущности, события шины Нужно сопровождать Python-код ✅ Основной
Generic Camera + REST sensors Без разработки Нет событий, ручная настройка каждой камеры ⬜ Быстрый старт
MQTT discovery Относительно просто Ограниченный набор сущностей ⬜ Дополнение

Решение: собственная интеграция через HACS с публикацией событий в шину Home Assistant. Дополнительно — поддержка MQTT discovery для тех, кто не хочет ставить HACS.

Архитектура интеграции

custom_components/openipc_nvr/
├── __init__.py          # настройка, координатор
├── manifest.json
├── config_flow.py       # добавление через интерфейс
├── const.py
├── api.py               # клиент к REST API NVR
├── camera.py            # сущность camera → HLS-поток
├── binary_sensor.py     # детекция движения
├── sensor.py            # число камер, событий
├── button.py            # перезапуск стримера, ребует
├── switch.py            # открытие двери
├── event.py             # события детекции
└── device_trigger.py    # триггеры для автоматизаций

Сущности

Платформа Сущность Описание
camera camera.<имя> Поток камеры (HLS)
binary_sensor binary_sensor.<имя>_motion Движение за последние N секунд
sensor sensor.nvr_online_cameras Камер онлайн
sensor sensor.nvr_events_24h Событий за 24 часа
sensor sensor.nvr_disk_usage Занято на диске, %
button button.<имя>_restart Перезапуск стримера
switch switch.<дверь> Открытие двери
event event.<имя>_detection Событие детекции

Этапы

Этап 1. Базовая интеграция (2 недели)

  • manifest.json с зависимостями
  • Настройка через интерфейс: адрес сервера, логин, пароль
  • Координатор с опросом /stats и /cameras раз в 30 секунд
  • Сущности camera и binary_sensor движения
  • Датчики статистики

Этап 2. События в шину HA (1–2 недели)

  • Опрос /events с отслеживанием последнего полученного события
  • Публикация в шину:
hass.bus.async_fire("openipc_nvr_detection", {
    "camera_id": event["camera_id"],
    "camera_name": camera_name,
    "object_class": event["object_class"],
    "confidence": event["confidence"],
    "timestamp": event["timestamp"],
})
  • Триггеры для автоматизаций через device_trigger.py:
automation:
  - alias: "Свет при обнаружении человека"
    trigger:
      - platform: device
        device_id: <id камеры>
        domain: openipc_nvr
        type: detection
        event_type: person
    action:
      - service: light.turn_on
        target:
          entity_id: light.porch

Этап 3. Управление и публикация (1–2 недели)

  • Кнопки перезапуска и перезагрузки
  • Открытие дверей СКУД
  • Публикация в HACS
  • README с примерами автоматизаций

Этап 4. MQTT discovery (опционально, 1 неделя)

Для пользователей без HACS: публикация сущностей по протоколу MQTT discovery. Требует добавления MQTT-клиента в бэкенд.

Пример автоматизации

automation:
  - alias: "Уведомление о человеке ночью"
    trigger:
      - platform: event
        event_type: openipc_nvr_detection
        event_data:
          object_class: person
    condition:
      - condition: time
        after: "23:00:00"
        before: "06:00:00"
    action:
      - service: notify.mobile_app
        data:
          title: "Движение на участке"
          message: >-
            {{ trigger.event.data.camera_name }}:
            обнаружен {{ trigger.event.data.object_class }}
          data:
            image: >-
              /api/v1/cameras/{{ trigger.event.data.camera_id }}/snapshot

Что требуется от серверной части

  1. Вебхуки или WebSocket. Сейчас события только опрашиваются через REST. Для мгновенной реакции нужен WebSocket-канал или вебхуки.
  2. Стабильный идентификатор камеры для привязки сущностей — уже есть (id).
  3. Смена пароля через API. Сейчас реализована только смена через БД.

4. Порядок работ

Предлагаемая последовательность с учётом зависимостей:

Приоритет Задача Срок Зависимости
1 WebSocket или вебхуки для событий 1 неделя —
2 POST /auth/refresh, смена пароля 3 дня —
3 Регистрация push-токенов и отправка FCM 1 неделя —
4 Запись видеоархива (ffmpeg → MinIO) 1 неделя —
5 GPU-детекция (ONNX + CUDA) 3–4 недели —
6 Интеграция с Home Assistant 4–5 недель п. 1
7 Мобильное приложение 6–8 недель п. 2, 3
8 WireGuard-управление туннелями 2 недели —

Задачи 1–4 — фундамент: без них мобильное приложение и интеграция с Home Assistant получатся урезанными.

Что можно сделать параллельно

  • GPU-детекция не зависит от остальных задач
  • WireGuard-управление не зависит ни от чего
  • Документация и тесты — постоянно

Открытые вопросы

  1. Хранение архива. Записи ведёт сам бэкенд (recorder_service.go: ffmpeg пишет отрезки, они уходят в MinIO), медиасервер в этом не участвует. Открытый вопрос — как связывать отрезки с метаданными в БД и как чистить старое.
  2. Глубина архива. Политика удаления: по возрасту, по занятому месту или по событиям?
  3. Резервное копирование. Нужна автоматизация выгрузки архива в внешнее хранилище.
  4. Масштабирование. При 50+ камерах потребуется разделение медиасерверов и балансировка.
  5. Распознавание лиц и номеров. Требует отдельных моделей и юридической проработки (персональные данные).