Clone
1
Architecture
Omarchy-Big-PC edited this page 2026-08-28 14:49:54 +01:00

Architecture

One Python file, no dependencies beyond ffmpeg. Intentionally.

server.py

ThreadingHTTPServer bound to 127.0.0.1. Each request is handled by PlayerHandler:

  • GET / - serves index.html
  • GET /api/recordings?date=YYYYMMDD - clips for one day plus the list of all days
  • GET /video?date=...&name=...&offset=... - streams a clip
  • POST /api/upload?date=...&filename=... - raw body upload into the archive
  • POST /api/encode - starts the background encoder
  • GET /api/encode/status - encoder progress
  • GET/POST/DELETE /api/highlights - saved highlight periods
  • GET /api/system-highlights?date=... - events parsed from the recorder's fileindex.dat

The recording index lives in memory (server.recordings), built at startup by scan_recordings() and updated when uploads arrive. Restarting the server rescans the folder from disk, which is the only state that matters.

Video streaming

MP4 clips are served with HTTP Range support (send_range_file), so seeking is instant. AVI clips are transcoded on the fly by an ffmpeg subprocess (H.264/AAC, fragmented MP4 piped to the client) and killed when the client disconnects.

Upload safety

Uploads stream to <target>.uploading.mp4 first, then atomically rename. A dropped connection leaves a temp file, never a truncated clip in the index. Duplicate timestamps get HTTP 409; nothing is ever overwritten.

index.html

Single file, no framework. A <video> element, a canvas timeline, and a handful of panels. The timeline draws recorded minutes, highlights, and system events as colored bars over a 24h axis, with zoom (up to 24x).

Clip transitions: seekBy() and the ended handler walk the clip list so playback jumps across clip boundaries and empty gaps seamlessly.