A Linux-native replacement for Hikvision's Windows-only "Local Service Component" DVR web plugin. A small Python backend + static web UI that talks to the DVR directly over its documented ISAPI (HTTP) and RTSP protocols — no closed-source SDK, no Windows box required.
This project is vibe coded — built in collaboration with an AI coding agent (Claude Code) rather than written by hand line-by-line.
- Live view — grid of all channels (analog + IP-proxy cameras), streamed to the browser via HLS.
- Playback & search — browse recordings by day, jump to a time, click a segment, or scrub a day timeline; continuous playback auto-advances across segment boundaries and skips real recording gaps instead of freezing.
- Snapshot & download — grab a still frame or export an MP4 clip for an arbitrary time range.
- PTZ control — pan/tilt/zoom for PTZ-capable channels via an on-screen D-pad.
- Shared-key auth — a single key gates both the API and the video streams themselves (live view/playback bypass the backend entirely, so both layers need protecting).
Two independent paths, since video never flows through the backend:
CONTROL PLANE (channels, search, snapshot, download)
Browser <--HTTP/JSON--> Backend (FastAPI) <--HTTP digest/XML--> DVR :80 (ISAPI)
MEDIA PLANE (live view + playback)
DVR :554 (RTSP) --> mediamtx (sidecar) --> HLS/WebRTC --> Browser <video>
The backend (app/) speaks ISAPI to the DVR for control operations
and manages mediamtx as a
sidecar process that bridges RTSP to HLS/WebRTC for the browser. The
frontend (static/) is plain HTML/JS with no build step or CDN
dependencies.
See ARCHITECTURE.md for the full technical reference, including
DVR firmware quirks this project works around.
- Linux, Python 3
- A Hikvision DVR/NVR reachable on the LAN with ISAPI + RTSP enabled
mediamtxbinary (downloaded automatically byrun.shon first run)
python3 -m venv .venv --without-pip
curl -sS https://bootstrap.pypa.io/get-pip.py | .venv/bin/python
.venv/bin/pip install -r requirements.txt
cp .env.example .env # fill in your DVR host/credentials and a generated AUTH_KEYGenerate an AUTH_KEY:
python -c "import secrets; print(secrets.token_urlsafe(24))"./run.shIdempotent — does first-run setup automatically (venv, dependencies, mediamtx download) if it hasn't run before, otherwise starts straight away. Equivalent to:
.venv/bin/python -m uvicorn app.main:app --host 127.0.0.1 --port 8896- Live view:
http://127.0.0.1:8896/ - Playback:
http://127.0.0.1:8896/playback
docker-compose.yml runs the same two-service split production uses
(dvr-window + mediamtx, see ARCHITECTURE.md "mediamtx as a
separate Swarm service") on a single machine via plain docker compose up — no Swarm cluster needed. Setup: .env (as above) for
HIKVISION_HOST/HIKVISION_USERNAME, plus secrets/hikvision_password
and secrets/auth_key (plain text — see secrets/*.example, both
gitignored). Then:
docker compose up -dLive view: http://localhost:8896/.
All configuration lives in .env (see .env.example) — never
committed. Required: HIKVISION_HOST, HIKVISION_USERNAME,
HIKVISION_PASSWORD, AUTH_KEY. Everything else (DVR/mediamtx ports,
local bind address) has sane defaults and is optional.
Live view, PTZ, playback/search, continuous playback, snapshot/download,
and auth are all implemented. Packaging (systemd service, install
script) is next — see PLAN.md for the full roadmap.
AGENTS.md— contributor/agent instructions, conventionsARCHITECTURE.md— technical design, protocol reference, known DVR quirksPLAN.md— roadmap and phase status
MIT — see LICENSE.