diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f44eeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +__pycache__/ +*.py[cod] +node_modules/ +dist/ +release/ +*.log +.DS_Store diff --git a/CLAUDE.md b/CLAUDE.md index a857a6d..086a53c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,16 +4,32 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -**Alta Video Player (WebAVP)** — a web-based surveillance video player for Alta/Ava Security camera exports. Users drag-drop video files or ZIP archives (including AES-256 encrypted ones) and get a multi-camera synchronized playback experience with timeline, digital zoom, cryptographic integrity verification, and automatic motion analytics. +**Alta Video Player (WebAVP)** — a web-based surveillance video player for Alta/Ava Security camera exports. Users drag-drop video files or ZIP archives (including AES-256 encrypted ones) and get a multi-camera synchronized playback experience with timeline, digital zoom, and cryptographic integrity verification. ## Running the App +Desktop mode: + +```bash +npm install +npm start +``` + +Web/Python mode: + ```bash python3 app.py # Serves on http://0.0.0.0:5152 ``` -No build step. No dependencies needed at runtime — `app.py` uses only Python stdlib (`http.server`). The `requirements.txt` (flask, requests, gunicorn) is vestigial; the server was rewritten to pure stdlib. +The Python server uses only stdlib modules. Electron dependencies are managed through `package.json` and `package-lock.json`. + +Checks: + +```bash +npm run check +xvfb-run -a npm run smoke +``` ## Architecture @@ -26,73 +42,31 @@ Minimal HTTP server with three routes: ### Frontend (`templates/index.html`) -Single self-contained HTML file (~5000 lines) with inline CSS and JavaScript in an IIFE. This is the entire application — there is no framework, no build system, no separate JS modules. +Single self-contained HTML file (~4000 lines) with inline CSS and JavaScript in an IIFE. This is the entire application — there is no framework, no build system, no separate JS modules. -**State model:** Global `channels` Map keyed by channel name. Each channel holds segments (video blobs + time ranges), metadata, DOM references, color, and zoom state. Global timeline state (`globalStart`, `globalEnd`, `currentTime`) synchronizes all cameras. Motion analytics state lives in the `motionState` object. +**State model:** Global `channels` Map keyed by channel name. Each channel holds segments (video blobs + time ranges), metadata, DOM references, color, and zoom state. Global timeline state (`globalStart`, `globalEnd`, `currentTime`) synchronizes all cameras. **Key subsystems:** - **File ingestion** — drag-drop files/folders, ZIP extraction (JSZip for plain, custom AES-256-CTR for encrypted), metadata pairing by base filename, concurrent import guard (`isImporting` flag) - **Multi-camera grid** — responsive CSS grid (1–9 cameras), drag-to-reorder, click-to-expand - **Playback engine** — `requestAnimationFrame` tick loop, per-channel segment visibility management, variable speed (0.25x–8x), frame stepping -- **Timeline** — interactive scrub bar with zoom (mouse wheel), minimap, per-channel segment indicators with color-coded dots, motion heatmap row +- **Timeline** — interactive scrub bar with zoom (mouse wheel), minimap, per-channel segment indicators with color-coded dots - **Digital zoom** — per-camera scroll-to-zoom (up to 10x) with click-drag panning - **Magnifier tool** — draw rectangle to zoom into region - **Slideshow mode** — animated grid showing only currently active feeds with transitions -- **Motion analytics** — automatic background motion detection on load (see below) - **Integrity verification** — offline X.509 certificate parsing, RSASSA-PKCS1-v1_5 and ECDSA signature verification via Web Crypto API, optional cloud verification through `/api/verify-cert` - **Session persistence** — IndexedDB caching of video blobs and metadata for page refresh survival **External dependency:** `/static/jszip.min.js` (vendored, for unencrypted ZIP parsing). -## Motion Analytics Subsystem - -Zero-dependency canvas-based motion detection that runs automatically when videos are loaded. - -### How it works -1. **Auto-scan on load** — `scheduleAutoScan()` is called from `flushPending()` and `loadSessionData()` after videos finish loading. Debounced 800ms to batch all segments. -2. **Dedicated scan videos** — scan creates temporary offscreen `