T0ks1k24/secure-monitoring-system
GitHub: T0ks1k24/secure-monitoring-system
Stars: 0 | Forks: 0
# Secure Monitoring System
A production-grade AI-powered video surveillance platform built with a microservices architecture. The system captures live camera streams, applies real-time object detection and tracking, evaluates zone-based security rules, and pushes instant alerts to an Electron desktop application.
## Table of Contents
- [Overview](#overview)
- [Key Features](#key-features)
- [Architecture](#architecture)
- [Services](#services)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [API Reference](#api-reference)
- [Development](#development)
- [Project Structure](#project-structure)
## Overview
IP Cameras (RTSP)
│
▼
┌─────────────┐ WebRTC/HLS ┌──────────────────┐
│ MediaMTX │ ──────────────────► │ Electron Frontend│
│ (RTSP Hub) │ │ (React + Redux) │
└──────┬──────┘ └────────┬─────────┘
│ RTSP │ HTTP (zones / cameras)
▼ ▼
┌──────────────────┐ ┌─────────────────────┐
│ Frame Extractor │ │ Backend Service │
│ (Python/RTSP) │ │ (FastAPI + PG) │
└────────┬─────────┘ └──────────┬──────────┘
│ JPEG frames │ WebSocket (events)
▼ │ RabbitMQ (zones)
┌─────────────────┐ RabbitMQ │
│ AI Service │ ──────────────────────► │
│ YOLOv8 + Zones │ security.events │
└─────────────────┘ │
▼
┌─────────────┐
│ PostgreSQL │
└─────────────┘
## Key Features
| Feature | Details |
|---|---|
| **Real-time detection** | YOLOv8 object detection at configurable FPS |
| **Multi-object tracking** | Persistent track IDs across frames per camera |
| **Zone-based rules** | Restricted / Perimeter / Parking / Pedestrian / Counting zones |
| **Smart analytics** | Loitering, crowding, direction violation, abandoned object detection |
| **Live alerts** | Sub-second event delivery via WebSocket to all connected clients |
| **Evidence frames** | Annotated JPEG snapshots saved for every zone event |
| **Hot-reload zones** | Zone changes propagate to AI service without restart via RabbitMQ |
| **Role-based access** | Admin / Operator roles with JWT authentication |
| **Electron desktop app** | Kiosk mode, multi-window support, draggable camera grid |
| **Docker orchestration** | Full stack runs with a single `docker compose up` |
## Architecture
The system is split into two logical tiers:
### Cloud Tier
Runs on a server or VM. Handles AI processing, data persistence, and API.
| Service | Port | Technology | Role |
|---|---|---|---|
| `backend` | 8000 | FastAPI + PostgreSQL | REST API, auth, WebSocket, event storage |
| `ai_service` | 5000 | FastAPI + YOLOv8 | Object detection, tracking, zone analysis |
| `postgres` | 5432 | PostgreSQL 16 | Persistent storage for events, zones, users |
| `rabbitmq` | 5672 / 15672 | RabbitMQ 3 | Async messaging between AI → Backend and Backend → AI |
### Local Tier
Runs on-site, close to the cameras.
| Service | Port | Technology | Role |
|---|---|---|---|
| `frame_extractor` | 8100 | FastAPI + OpenCV | RTSP frame capture and forwarding to AI |
| `frontend` | 3000 / 80 | React + Electron | Desktop UI for monitoring and management |
| `mediamtx` | 8554 / 8888 / 8889 | MediaMTX | RTSP hub; serves WebRTC and HLS to the frontend |
### Data Flows
**Camera → Alert pipeline:**
ffmpeg (cam publisher)
→ MediaMTX :8554/cameraX [RTSP]
→ Frame Extractor [reads frames at DEFAULT_FPS]
→ AI Service POST /detect [JPEG + camera_id]
→ YOLO detection + tracking
→ Zone intersection
→ Risk engine + smart analytics
→ RabbitMQ "security.events" exchange [topic: events.{type}.{camera_id}]
→ Backend EventConsumer
→ PostgreSQL (persist)
→ WebSocket broadcast [to all connected frontend clients]
→ Frontend alert overlay
**Zone update pipeline:**
Frontend draw/edit zone
→ Backend PUT /api/zones/{id}
→ PostgreSQL (persist)
→ RabbitMQ "security.zones" exchange [routing: zones.updated.{camera_id}]
→ AI Service zone cache invalidation [hot-reload, no restart needed]
### RabbitMQ Topology
| Exchange | Type | Published by | Consumed by |
|---|---|---|---|
| `security.events` | topic | AI Service | Backend (binding `events.#`) |
| `security.zones` | topic | Backend | AI Service (exclusive queue) |
## Services
### Backend Service (`cloud/backend_service/`)
FastAPI application with clean architecture layers (presentation → application → domain → infrastructure).
**Responsibilities:**
- JWT authentication (access + refresh tokens, admin/operator roles)
- Zone CRUD (create, list, update, delete)
- Event ingestion from RabbitMQ and storage in PostgreSQL
- WebSocket broadcast of real-time events to the frontend
- Zone update notifications to AI service via RabbitMQ
**Default admin credentials** (created on first start):
- Username: `admin`
- Password: `admin` *(change in production!)*
### AI Model Service (`cloud/ai_model_service/`)
FastAPI application with a multi-step detection pipeline.
**Detection pipeline (per frame):**
1. **YOLOv8** — object detection (person, car, knife, etc.)
2. **Tracker** — assigns persistent `track_id` per camera
3. **Zone intersection** — checks which zones each track occupies
4. **Risk engine** — applies zone rules (e.g., person in restricted → HIGH)
5. **Smart analytics** — loitering, crowding, abandoned object, direction
6. **RabbitMQ publish** — `SecurityEvent` JSON to `security.events`
7. **Evidence storage** — saves annotated JPEG for zone-triggered events
**Zone types and default rules:**
| Zone Type | Trigger Condition | Risk Level |
|---|---|---|
| `restricted` | Any object enters | HIGH |
| `pedestrian` | Vehicle enters | HIGH |
| `parking` | Person (not vehicle) enters | MEDIUM |
| `entrance` | Any motion (after hours) | MEDIUM |
| `perimeter` | Any motion | MEDIUM |
| `counting_line` | Object crosses line | LOW |
| `safe_zone` | Risk accumulation reduced | — |
### Frame Extractor Service (`local/frame_extractor_service/`)
FastAPI application that manages a pool of camera workers.
**Responsibilities:**
- Maintains RTSP connections to MediaMTX for each camera
- Throttles frame extraction to `DEFAULT_FPS` (default: 2.0)
- Encodes frames as JPEG and forwards to AI Service
- Persists camera configurations in SQLite
- Rewrites `localhost` RTSP URLs to `mediamtx` for Docker networking
**Camera worker lifecycle:** `STOPPED → CONNECTING → RUNNING → ERROR → CONNECTING → …`
### Frontend Service (`local/frontend_service/`)
Electron + React desktop application.
**Pages:**
- **Monitoring** — live RTSP stream (WebRTC), zone drawing, real-time event feed
- **Cameras Grid** — multi-camera view with per-camera alert overlays
- **Analytics** — event statistics, risk distribution charts, heatmaps
- **Settings** — camera management, connection settings, display grid configuration, access control
**Key features:**
- Draws and edits detection zones directly on the video feed
- WebSocket connection to backend for real-time event streaming
- Kiosk mode for dedicated monitoring stations
- Multi-window support with isolated localStorage state
- Automatic token refresh (JWT)
## Quick Start
### Prerequisites
- Docker ≥ 24 and Docker Compose ≥ 2.20
- Two camera video files placed in `./video/cam1.mp4` and `./video/cam2.mp4`
*(optionally `cam3.mp4` for a third camera)*
### 1. Clone and start
git clone https://github.com/T0ks1k24/secure-monitoring-system.git
cd secure-monitoring-system
# Copy the video files (not tracked in git):
# cp /your/video.mp4 ./video/cam1.mp4
# cp /your/video2.mp4 ./video/cam2.mp4
# Start all services
docker compose up -d
# Or use the Makefile:
make docker-start-d
### 2. Wait for services to be ready
docker compose ps # all services should be "healthy"
docker compose logs -f # watch startup logs
Typical startup order: `postgres` → `rabbitmq` → `backend` → `ai_service` → `frame_extractor`
### 3. Open the frontend
The web frontend is available at **http://localhost:3000**
For the Electron desktop app, run locally:
cd local/frontend_service/frontend
npm install
npm run electron:dev
### 4. Log in
- **Username:** `admin`
- **Password:** `admin`
### 5. Add a camera
1. Go to **Settings → Camera Settings → Add Camera**
2. Enter RTSP URL: `rtsp://localhost:8554/camera1`
3. The frame extractor starts capturing; events appear within seconds
## Configuration
### Environment Variables
#### Backend Service (`cloud/backend_service/backend/.env`)
| Variable | Default | Description |
|---|---|---|
| `DATABASE_URL` | `sqlite:///./local.db` | PostgreSQL connection string |
| `RABBITMQ_URL` | `amqp://guest:guest@rabbitmq:5672/` | RabbitMQ AMQP URL |
| `JWT_SECRET` | `SUPER_SECRET_KEY` | **Change in production!** |
| `JWT_ALGORITHM` | `HS256` | JWT signing algorithm |
| `ACCESS_TOKEN_EXPIRE_MINUTES` | `15` | Access token lifetime |
| `REFRESH_TOKEN_EXPIRE_DAYS` | `30` | Refresh token lifetime |
| `EVENTS_EXCHANGE` | `security.events` | RabbitMQ events exchange name |
| `ZONES_EXCHANGE` | `security.zones` | RabbitMQ zones exchange name |
| `EVENTS_QUEUE` | `backend.events` | Durable queue for backend consumption |
#### AI Model Service (`cloud/ai_model_service/.env`)
| Variable | Default | Description |
|---|---|---|
| `BACKEND_API_URL` | `http://backend:8000` | URL to fetch zones from backend |
| `RABBITMQ_URL` | `amqp://guest:guest@rabbitmq:5672/` | RabbitMQ connection |
| `MODEL_PATH` | `yolo26s.pt` | Path to YOLO model weights |
| `DETECTION_CONFIDENCE` | `0.4` | Detection confidence threshold (0.0–1.0) |
| `DETECTION_IOU` | `0.45` | NMS IoU threshold |
| `INFERENCE_IMG_SIZE` | `640` | YOLO input size (320 / 640 / 1280) |
| `DEVICE` | `cpu` | Inference device: `cpu`, `cuda`, `mps` |
| `SAVE_PROCESSED_FRAMES` | `False` | Save annotated frames to disk |
| `EVIDENCE_PUBLIC_BASE_URL` | `http://localhost:5000` | Public URL for evidence image links |
| `ZONE_CACHE_TTL` | `30.0` | Zone cache TTL in seconds |
| `DEBUG_VISUALIZE` | `False` | Show cv2.imshow debug windows |
#### Frame Extractor Service (`local/frame_extractor_service/.env`)
| Variable | Default | Description |
|---|---|---|
| `AI_SERVICE_URL` | `http://localhost:5000/api/v1/detect` | AI service detect endpoint |
| `AI_REQUEST_TIMEOUT` | `5` | HTTP timeout for AI requests (seconds) |
| `DEFAULT_FPS` | `2.0` | Default frame extraction rate |
| `DEFAULT_RESIZE_WIDTH` | `1280` | Frame resize width before encoding |
| `DEFAULT_JPEG_QUALITY` | `95` | JPEG compression quality (1–100) |
| `DEFAULT_RECONNECT_DELAY` | `3` | Seconds to wait before RTSP reconnect |
| `RTSP_LOCALHOST_REWRITE_HOST` | `mediamtx` | Replace `localhost` in RTSP URLs (Docker) |
| `DATABASE_URL` | `sqlite:///./cameras.db` | SQLite path for camera config storage |
#### Frontend (`local/frontend_service/frontend/.env` or Docker build args)
| Variable | Default | Description |
|---|---|---|
| `VITE_API_URL` | `http://localhost:8000` | Backend API base URL |
| `VITE_FRAME_API_URL` | `http://localhost:8100` | Frame extractor API URL |
| `VITE_MEDIA_MTX_HLS_URL` | `http://localhost:8888` | MediaMTX HLS endpoint |
| `VITE_MEDIA_MTX_WEBRTC_URL` | `http://localhost:8889` | MediaMTX WebRTC endpoint |
| `VITE_WS_EVENTS_URL` | *(derived from API URL)* | WebSocket events endpoint |
## API Reference
See [docs/api-reference.md](docs/api-reference.md) for the full API reference.
**Interactive docs** (when running):
- Backend: http://localhost:8000/docs
- AI Service: http://localhost:5000/docs
- Frame Extractor: http://localhost:8100/docs
## Development
See [docs/development.md](docs/development.md) for the development guide.
### Makefile Commands
make docker-start-d # Start all services in background
make docker-stop # Stop all services
make docker-rebuild # Full rebuild (no cache)
make docker-clean # Stop + remove volumes
make docker-logs # Stream all logs
make docker-logs-backend # Stream backend logs only
make db-reset # Drop and recreate the database
make db-shell # Open psql shell
make backend-shell # Open shell in backend container
## Project Structure
secure_monitoring_system/
│
├── cloud/ # Cloud-side services
│ ├── backend_service/
│ │ └── backend/ # FastAPI backend
│ │ ├── core/ # JWT, config, WebSocket manager
│ │ ├── domain/ # Entities, enums, repository interfaces
│ │ ├── application/ # Services, DTOs
│ │ ├── infrastructure/ # SQLAlchemy models, repos, RabbitMQ
│ │ └── presentation/ # FastAPI routers (controllers)
│ │
│ └── ai_model_service/ # AI detection service
│ ├── models/ # YOLO model loader
│ ├── services/ # Pipeline, tracker, zone manager, risk engine
│ ├── schemas/ # Pydantic event/zone schemas
│ ├── config/ # Settings
│ └── api/ # FastAPI routes
│
├── local/ # On-site services
│ ├── frame_extractor_service/ # RTSP frame capture
│ │ ├── core/ # CameraManager, CameraWorker, factory, repository
│ │ ├── core/implementations/ # RTSPFrameSource, AIClientSink
│ │ ├── detection/ # Motion detector processor
│ │ ├── api/ # FastAPI cameras and system routes
│ │ └── schemas.py # Pydantic request/response models
│ │
│ └── frontend_service/
│ └── frontend/
│ ├── electron/ # Electron main process + preload
│ └── src/
│ ├── components/ # Reusable React components
│ ├── hooks/ # useEventStream, useKioskMode
│ ├── pages/ # Monitoring, CamerasGrid, Analytics, Settings
│ ├── services/ # RTK Query API slices (camerasApi, zonesApi, eventsApi)
│ │ └── auth/ # baseQueryWithRefresh, authSlice
│ ├── store/ # Redux store
│ └── utils/ # windowStorage
│
├── mediamtx/
│ └── mediamtx.yml # MediaMTX configuration
│
├── video/ # Camera test videos (not in git)
│ ├── cam1.mp4
│ ├── cam2.mp4
│ └── cam3.mp4
│
├── docker-compose.yml # Full stack (development + production)
├── docker-compose.local.yml # Local-only (frontend + frame_extractor)
├── docker-compose.cloud.yml # Cloud-only (backend + AI + infra)
├── Makefile # Convenience commands
└── docs/
├── architecture.md # Detailed architecture documentation
├── api-reference.md # Complete API reference
└── development.md # Developer guide
## License
This project was developed as a graduation thesis at Lutsk National Technical University (LNTU), specialty 126 — Information Systems and Technologies.