EyesOnGuj is a unified CCTV management, registry, GIS mapping, and video analytics platform built for Gujarat's statewide surveillance network.
Brings up Postgres + PostGIS and the FastAPI app in one command.
Prerequisites: Docker Desktop (Compose v2+)
-
Copy the env file and set a real
SECRET_KEY:cp .env.example infra/.env
Open
infra/.envand replace theSECRET_KEYline with a random value:python3 -c "import secrets; print(secrets.token_hex(32))"Everything else in
.env.examplealready has a working default, soSECRET_KEYis the only line you need to touch.docker-compose.ymlrefuses to start without it. -
Start the containers:
cd infra docker compose up -dThe first run builds the app image and the Postgres + PostGIS + pgvector database image, and creates the
sentinelrole/database automatically. The app image's first build can take a few minutes (its dependencies include PyTorch for the AI detection features) -docker compose logs -f appshows the install progress if you want to confirm it's still working.docker compose psshould showdbashealthyandappasrunningbefore moving on.You do not need to
pip installanything on your host for this - the app container installs its own dependencies during the build. -
Open the dashboard at
http://localhost:8000:- Map dashboard:
/ - Login:
/login - Camera registry:
/cameras - Live grid (30 cameras):
/grid - Live AI vehicle detection:
/detection - Pre-recorded video AI detection:
/recorded-detection - Vehicle watchlist:
/watchlist - Person watchlist & biometrics:
/watchlist/persons - Departments:
/departments - Districts:
/districts - Audit log:
/audit - Gap analysis:
/gap-analysis - API docs (Swagger):
/docs
- Map dashboard:
-
Demo accounts (password:
password123):admin_home(dept_admin- Home Department)admin_rto(dept_admin- Regional Transport Office)operator1(operator)viewer1(viewer)
-
Reset the database and seed data if needed:
docker compose down -v --rmi local docker compose up -d
Needs a local Postgres 16 with the postgis, pgcrypto, and vector (pgvector) extensions installed.
bash scripts/bootstrap_local_db.sh # one-time: creates the sentinel role + database
cd model1-registry
pip install -r requirements-dev.txt
pytestSee model1-registry/README.md's Testing section for details, including what to check if a run looks stuck.
The easiest way to run the full test suite locally is to reuse the same Postgres + PostGIS + pgvector database container used by the application.
From the repository root:
cd infra
docker compose up -dThe first run builds the database image and starts Postgres with the required postgis and pgvector extensions. Wait until the database is healthy:
docker compose psThen return to the repository root and install the development dependencies for all three models:
cd ..
pip install -r model1-registry/requirements-dev.txt
pip install -r model2_analytics/requirements-dev.txt
pip install -r model3_federation/requirements-dev.txtThe three models have separate development requirement files because their test and development dependencies are maintained independently.
On Windows, the Docker database is exposed on host port 5433. Set the test database port before running the suite:
set TEST_DB_PORT=5433
pytest -vOn PowerShell:
$env:TEST_DB_PORT = "5433"
pytest -vRunning pytest -v from the repository root runs the test suites across Model 1, Model 2, and Model 3.
If you need to completely reset the Docker database and start fresh:
cd infra
docker compose down -v
docker compose up -d- Backend Framework: FastAPI (Python 3.12)
- Database: PostgreSQL 16 + PostGIS 3.4 +
pgvectorextension - ORM & Migrations: SQLAlchemy 2.0 + GeoAlchemy2
- Frontend Architecture: Server-rendered Jinja2 templates + HTMX + Alpine.js (via CDN, no Node build step)
- Live Video & Analytics: HLS.js in-browser streaming, RTSP/HLS feeds, ANPR watchlist matching
- Containerization: Docker Compose (
infra/docker-compose.yml)
Project_Context.md Working technical specification & architectural decisions
HackathonPortal.md Hackathon challenge brief
docs/
model1/README.md Model 1 - full feature documentation (data model, every endpoint, GIS/gap-analysis internals)
PLATFORM.md The shared FastAPI app shell every model runs inside
SECURITY.md Auth, RBAC, audit trail & cybersecurity posture (cross-model)
API_Contract.md REST & WebSocket API specification
DATASET.md Dataset notes & video stream catalogue
shared/ Shared codebase across models
db/ SQLAlchemy models, schema.sql, triggers.sql, seed.sql
schemas/ Pydantic request & response models
adapters/ VMS adapter interface definitions
model1-registry/ Model 1 - Registry & GIS Foundation
app/ FastAPI application (routers, templates, static CSS/JS)
model2_analytics/ Model 2 - Analytics & Vehicle Tracking (ANPR, Watchlists, Alerts)
app/routers/ Watchlist CRUD router
pipeline/ Analytics & ANPR pipeline architecture
model3_federation/ Model 3 - Multi-VMS Federation (adapters, event bus, correlation engine)
adapters/ Per-vendor VMS adapters (ONVIF, REST, municipal, police, RTO)
api/router.py Federation REST + WebSocket endpoints, mounted into model1's app
infra/ Docker environment (docker-compose.yml, Dockerfile, Dockerfile.db)
scripts/ One-off setup scripts (e.g. bootstrap_local_db.sh for non-Docker local dev)
(Full documentation, request/response examples, and RBAC rules: docs/model1/README.md)
POST /api/v1/auth/login- Authenticate user and set httpOnly JWT cookiePOST /api/v1/auth/logout- Log out user and clear session cookieGET /api/v1/cameras- List, filter by department, district, and statusPOST /api/v1/cameras- Create new camera (manual entry,dept_adminscoped)POST /api/v1/cameras/bulk- CSV bulk camera import (dept_adminscoped)GET /api/v1/cameras/{id}- Get camera detail & VMS stream URLPATCH /api/v1/cameras/{id}- Update camera (writesstatus_historyaudit log)DELETE /api/v1/cameras/{id}- Soft delete camera (is_active = false)GET /api/v1/cameras/{id}/history- Camera audit historyGET /api/v1/audit- System-wide audit trail logsGET /api/v1/departments- List departments with active camera countsGET /api/v1/districts- List all 33 Gujarat districts with camera counts and GeoJSON boundariesGET /api/v1/gap-analysis- PostGIS spatial camera coverage calculation (1km buffer)
GET /grid- Control-Room Multi-Camera Live Grid UI (2x2, 3x3, 4x4 matrix views)GET /api/ingest- Hackathon ingestion contract - returns all cameras with RTSP/WHEP/HLS URLsGET /api/v1/grid/streams- JSON API: all active camera stream URLs (with dept/district filters)POST /api/v1/grid/sync- Sync camera catalogue from external source into DBGET /detectionsorGET /detection- Live AI Vehicle Detection DashboardGET /api/v1/detections- Paginated vehicle detection audit history from DBGET /api/v1/detections/stats- Real-time vehicle detection counts and active tracksWS /ws/detections- WebSocket stream for live bounding boxes, track IDs, and sightingsGET /recorded-detection- Pre-Recorded Video AI Detection Dashboard UIPOST /api/v1/recorded/upload- Multipart video upload (up to 2 GB) with OpenCV metadata extractionGET /api/v1/recorded/cameras- List active cameras for location associationPOST /api/v1/recorded/start- Start isolated background video analysis workerPOST /api/v1/recorded/pause/resume/stop- Execution controlsGET /api/v1/recorded/status/{job_id}- Query status, frame count, processing FPSWS /ws/recorded/{job_id}- Real-time video frame and bounding box WebSocket streamGET /api/v1/watchlist/vehicles- List & search vehicle targets (filter bycategory,status,plate_number,department_id)POST /api/v1/watchlist/vehicles- Add new vehicle target (with Indian plate format validation & duplicate checks)GET /api/v1/watchlist/vehicles/{id}- Get single watchlist target detailPATCH /api/v1/watchlist/vehicles/{id}- Update target case status (active/resolved) or detailsDELETE /api/v1/watchlist/vehicles/{id}- Delete watchlist target and cascade associated alertsGET /detection-image/{file_path}- Authenticated serving of vehicle/plate cropped detection imagesGET /face-detection- Surveillance Video Face Detection & Watchlist Alerting Dashboard UIGET /api/v1/face-detection/active-jobs- List all ongoing and ready face processing jobsPOST /api/v1/face-detection/upload- Upload surveillance footage (up to 2 GB) with OpenCV metadata probingPOST /api/v1/face-detection/start- Start background face detection & watchlist matching worker (1x, 2x, max speed)POST /api/v1/face-detection/pause/resume/stop- Execution controls for face analysis workerGET /api/v1/face-detection/status/{job_id}- Query face processing status, detected face counts, and watchlist hitsGET /api/v1/face-detection/alerts- Paginated person watchlist match alerts with confidence scores and distance metricsGET /api/v1/face-detection/crops/{filename}- Authenticated serving of detected face match crop thumbnailsWS /api/v1/face-detection/ws/{job_id}- Real-time WebSocket channel streaming frames, face bounding boxes, and instant watchlist match alertsGET /api/v1/watchlist/persons- List & filter person targets (filter bycategory,status,name)POST /api/v1/watchlist/persons- Register person target with 5-gate AI quality validation (YuNet + solvePnP 3D pose), 10 MB photo limit, and 512-d InceptionResnetV1 embedding inpgvectorGET /api/v1/watchlist/persons/{id}- Get single person watchlist target detailPATCH /api/v1/watchlist/persons/{id}- Update person details or toggle status (active/resolved)DELETE /api/v1/watchlist/persons/{id}- Remove person target and disk reference photoGET /api/v1/watchlist/persons/photos/{photo_filename}- Authenticated serving of reference face portrait
See Project_Context.md for full architectural background, rationale, and design principles. For Model 1 specifically, docs/model1/README.md is the authoritative reference - Project_Context.md is our working spec and may run ahead of or behind what's actually implemented.