4.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
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, and cryptographic integrity verification.
Running the App
Desktop mode:
npm install
npm start
Web/Python mode:
python3 app.py
# Serves on http://0.0.0.0:5152
The Python server uses only stdlib modules. Electron dependencies are managed through package.json and package-lock.json.
Checks:
npm run check
xvfb-run -a npm run smoke
Architecture
Backend (app.py)
Minimal HTTP server with three routes:
GET /— servestemplates/index.htmlGET /static/*— serves static files with path traversal protectionGET /api/verify-cert?serial=...&certificateHash=...— proxies certificate verification tohttps://aware.avasecurity.com/api/v1/public/verifyServerCertificate
Frontend (templates/index.html)
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.
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 (
isImportingflag) - Multi-camera grid — responsive CSS grid (1–9 cameras), drag-to-reorder, click-to-expand
- Playback engine —
requestAnimationFrametick 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
- 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
- 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 were intentionally removed. Keep future work focused on core video player behavior unless the product direction changes.
Memory Management
Video elements must be properly destroyed to avoid browser memory exhaustion:
destroyVideoEl(videoEl)— pauses video, removessrc, calls.load()to force browser to release buffered data. Must be called before removing video elements from DOM.video.preload = 'metadata'— all playback videos use metadata-only preloading to avoid buffering entire files into RAM.newSession()— comprehensive teardown: destroys all video elements, revokes all blob URLs, nulls blob references, releases WebGL contexts, clears all state.isImportingguard — prevents concurrent file imports which could cause race conditions and duplicate segments.- Slideshow video elements are destroyed on pane transitions and when slideshow is toggled off.
Key Conventions
- All frontend code lives in
templates/index.html— CSS at top, then the IIFE script block - Video elements are created on-demand and hidden (not removed) for performance
- Segment visibility is recalculated every animation frame during playback
- The
batchingSegmentsflag defers rendering during bulk file imports - Keyboard shortcuts are defined inline (Space=play/pause, arrows=seek, S=slideshow, M=magnifier, F=fullscreen, [/]=speed, 0=reset zoom)
- Right-side panel (log) is the only slide-out; opening it does not affect other panels