Skip to content

Latest commit

 

History

56 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CCTVQL cover

CCTVQL logo

cctvQL

Ask your CCTV system anything in plain English.

License: MIT Python CI codecov PyPI Docker PRs Welcome CodeQL Sponsor

cctvQL is an open-source conversational query layer for CCTV and surveillance systems. It wraps any camera system — Frigate, ONVIF, Hikvision, Dahua and more — with a natural language interface powered by local or cloud LLMs.

Quick Start · Documentation · Adapters · Contributing · Sponsor


What It Does

you      > Was there anyone near the front door last night?

cctvQL   > Yes — 3 person detections on "Front Door" between 22:14 and 23:47.
           • 22:14 — person (96%) in zone: driveway
           • 23:02 — person (88%)
           • 23:47 — person (91%) in zone: porch

you      > Show me the clip from 23:47

cctvQL   > Clip from Front Door (23:47–23:49, 112s):
           http://192.168.1.100:5000/api/events/abc123/clip.mp4

No dashboards. No complex queries. Just ask.


Features

  • Natural language queries — ask about events, cameras, clips, and system health in plain English
  • Multi-turn conversations — context-aware follow-up questions backed by SQLite session persistence
  • Vendor-agnostic — adapter pattern supports any CCTV system; ships with Frigate, ONVIF, Hikvision, Dahua
  • Pluggable LLM backends — Ollama (local/private), OpenAI, Anthropic, or any OpenAI-compatible API
  • REST API — integrate with Home Assistant, Grafana, custom dashboards, or mobile apps
  • React Native mobile app — iOS + Android client with live feed, events, chat, PTZ, and push alerts
  • Face recognition — enroll known individuals and identify them across event snapshots (pip install cctvql[face])
  • AI event summaries — GET /events/{id}/summary combines VisionAnalyzer + face recognition into one structured response
  • Mobile push notifications — FCM integration; alerts land on registered iOS/Android devices (pip install cctvql[push])
  • PTZ control — pan, tilt, zoom and preset recall via REST API for supported cameras
  • Event export — download event history as CSV or JSON from /events/export
  • Alert rules — create rules to notify when specific labels appear on specific cameras in time windows
  • Multi-channel notifications — Telegram, Slack, ntfy, email, and webhook; all fire concurrently
  • WebSocket streaming — real-time event push to any connected client via ws://host/ws/events
  • Prometheus metrics — /metrics endpoint for Grafana, alerting, and observability
  • Camera health monitoring — background poller tracks per-camera online/offline status
  • Optional API key auth — protect your endpoint with CCTVQL_API_KEY env var
  • Multi-tenant support — JWT auth, per-user camera permissions, admin user management (CCTVQL_MULTI_TENANT=1)
  • Anomaly detection — statistical spike/silence detection per camera; ask "anything unusual today?"
  • Demo adapter — try cctvQL without any hardware; realistic mock data built-in
  • Interactive CLI — terminal-based conversational REPL
  • Real-time events — MQTT subscription for live alerts (Frigate)
  • Home Assistant integration — native custom integration with sensors, binary sensors (per-camera motion), PTZ and query services; installable via HACS
  • Docker-ready — running in under 5 minutes with persistent SQLite storage

Screenshots

Web UI — landing cctvQL landing screen showing camera sidebar and example query chips

Camera list query Response showing all 4 cameras with status and zones

Event history Recent motion events on the Front Door camera with timestamps and confidence scores

Alert rule creation Natural language alert setup — person detected after 10pm

Multi-turn conversation with vision AI Multi-turn conversation including a GPT-4o Vision analysis of an event snapshot


Quick Start

Try it now — no hardware needed

pip install cctvql
cctvql chat --adapter demo --llm ollama

The demo adapter ships with 4 cameras, 20 realistic events, and 5 clips — no Frigate or ONVIF device required. Use it to explore the query interface, build integrations, or write tests.

Docker (recommended — 5 minutes)

# 1. Clone and configure
git clone https://github.com/arunrajiah/cctvql.git
cd cctvql
cp config/example.yaml config/config.yaml

# 2. Edit config/config.yaml with your Frigate URL and LLM settings
nano config/config.yaml

# 3. Start
docker compose up -d

# 4. Try it
curl -X POST http://localhost:8000/query \
  -H "Content-Type: application/json" \
  -d '{"query": "Show me all cameras"}'

API docs: http://localhost:8000/docs

pip

pip install cctvql

# Interactive chat
cctvql chat --config config/config.yaml

# REST API server
cctvql serve --config config/config.yaml --port 8000

From source

git clone https://github.com/arunrajiah/cctvql.git
cd cctvql
pip install -e ".[dev,mqtt,onvif]"
cctvql chat

Documentation

Topic Link
Configuration reference docs/configuration.md
REST API reference docs/api.md
Notifications setup docs/notifications.md
Session & event persistence docs/persistence.md
Writing an adapter docs/adapters.md
LLM backend setup docs/llm-backends.md
Home Assistant integration docs/home-assistant.md
Docker deployment docs/docker.md
Frigate + cctvQL sidecar deploy/frigate-sidecar/
Troubleshooting docs/troubleshooting.md

Supported Systems

System Type Adapter Status
Frigate NVR NVR frigate ✅ Full support (REST + MQTT) — sidecar template
Any ONVIF camera/NVR Camera/NVR onvif ✅ Full support
Demo / Mock Built-in demo ✅ No hardware needed — try cctvQL now
Hikvision NVR/Camera hikvision ✅ Full support (ISAPI)
Dahua NVR/Camera dahua ✅ Full support (CGI)
Synology Surveillance Station NVR synology ✅ Full support (Web API)
Milestone XProtect Enterprise NVR milestone ✅ Full support (REST API)
Scrypted Smart home NVR scrypted ✅ Full support (Bearer token)
Your system Any — Write an adapter!

Writing an adapter takes ~100 lines. See the adapter guide.


Supported LLM Backends

Backend Privacy Cost Quality
Ollama (llama3, mistral, phi3…) 🔒 100% local Free ⭐⭐⭐⭐
OpenAI (gpt-4o-mini, gpt-4o) ☁️ Cloud Paid ⭐⭐⭐⭐⭐
Anthropic (claude-haiku, claude-sonnet) ☁️ Cloud Paid ⭐⭐⭐⭐⭐
LM Studio 🔒 Local Free ⭐⭐⭐⭐
Any OpenAI-compatible API Varies Varies Varies

Recommended for privacy: Ollama with llama3 or mistral. No data leaves your network.


Configuration

# config/config.yaml
llm:
  active: ollama
  backends:
    ollama:
      provider: ollama
      host: http://localhost:11434
      model: llama3

adapters:
  active: frigate
  systems:
    frigate:
      type: frigate
      host: http://192.168.1.100:5000
      mqtt_host: 192.168.1.100      # optional, for real-time events

# Optional: alert notifications (any combination of channels)
notifications:
  telegram:
    bot_token: "123456:ABC-DEF..."
    chat_id: "-1001234567890"
  slack:
    webhook_url: "https://hooks.slack.com/services/..."
  ntfy:
    topic: my-cctvql-alerts

Database path (conversation history + event log):

export CCTVQL_DB_PATH=/data/cctvql.db

See docs/configuration.md for the full reference.
Notification channels: docs/notifications.md.
Session persistence: docs/persistence.md.


REST API

# Natural language query (multi-turn, session history persisted to SQLite)
POST /query
{"query": "Did anyone come to the front door after midnight?", "session_id": "my-session"}

# List cameras
GET /cameras

# Get events with filters
GET /events?camera=driveway&label=person&limit=10

# Export events as CSV or JSON
GET /events/export
GET /events/export?fmt=json&camera=Front+Door&label=person

# PTZ control (pan/tilt/zoom)
POST /cameras/{camera_id}/ptz
{"action": "left", "speed": 50}

# PTZ presets
GET /cameras/{camera_id}/ptz/presets

# System health
GET /health

# Per-camera health status
GET /health/cameras

# Alert rules (CRUD)
GET    /alerts
POST   /alerts
GET    /alerts/{id}
PATCH  /alerts/{id}
DELETE /alerts/{id}

# Anomaly detection (statistical spike/silence analysis)
GET /anomalies
GET /anomalies?hours=6&camera=Front+Door&threshold=1.5

# Prometheus metrics (for Grafana / alerting)
GET /metrics

# Clear conversation session (also removes from database)
DELETE /sessions/{session_id}

Real-time event streaming via WebSocket:

ws://localhost:8000/ws/events

Optional API key auth — set CCTVQL_API_KEY env var to require X-API-Key header on all requests.

Interactive Swagger docs available at http://localhost:8000/docs.

See docs/api.md for full endpoint documentation.


Architecture

┌─────────────────────────────────────────────────────────┐
│                    User Interface                        │
│         CLI Chat  │  REST API  │  Home Assistant         │
└─────────────────────────┬───────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────┐
│                    NLP Engine                            │
│   Natural Language → QueryContext (intent + params)      │
└─────────────────────────┬───────────────────────────────┘
                          │
           ┌──────────────▼──────────────┐
           │        LLM Registry         │
           │  Ollama │ OpenAI │ Anthropic │
           └──────────────┬──────────────┘
                          │
┌─────────────────────────▼───────────────────────────────┐
│                   Query Router                           │
│   Routes intent to adapter → formats human response     │
└─────────────────────────┬───────────────────────────────┘
                          │
           ┌──────────────▼──────────────┐
           │      Adapter Registry       │
           │  Frigate │ ONVIF │ Your NVR │
           └──────────────┬──────────────┘
                          │
┌─────────────────────────▼───────────────────────────────┐
│                  Your CCTV System                        │
│         NVR / IP Cameras / Recording Storage             │
└─────────────────────────────────────────────────────────┘

Project Structure

cctvql/
├── cctvql/
│   ├── core/
│   │   ├── schema.py          # Vendor-agnostic data models
│   │   ├── nlp_engine.py      # Natural language → QueryContext
│   │   └── query_router.py    # QueryContext → adapter → response
│   ├── adapters/
│   │   ├── base.py            # BaseAdapter interface (implement to add a system)
│   │   ├── frigate.py         # Frigate NVR (REST + MQTT)
│   │   └── onvif.py           # Generic ONVIF adapter
│   ├── llm/
│   │   ├── base.py            # BaseLLM interface + LLMRegistry
│   │   ├── ollama_backend.py  # Local LLM via Ollama
│   │   ├── openai_backend.py  # OpenAI / compatible APIs
│   │   └── anthropic_backend.py
│   ├── interfaces/
│   │   ├── cli.py             # Interactive terminal chat
│   │   └── rest_api.py        # FastAPI REST server
│   ├── _bootstrap.py          # Config loader and wiring
│   └── __main__.py            # Entry point (cctvql chat / serve)
├── config/
│   └── example.yaml           # Annotated config reference
├── docs/                      # Full documentation
├── tests/
├── Dockerfile
├── docker-compose.yml
└── pyproject.toml

Contributing

Contributions are what make cctvQL useful for everyone. The single highest-impact contribution is writing an adapter for a CCTV system you already have.

git clone https://github.com/arunrajiah/cctvql.git
cd cctvql
pip install -e ".[dev,mqtt,onvif]"
pytest tests/   # all tests should pass

See CONTRIBUTING.md for the full guide.

# Common developer commands
make dev          # install with all extras + pre-commit hooks
make test         # run test suite
make coverage     # tests + coverage report
make lint         # ruff linter
make type-check   # mypy
make demo         # interactive demo (no real hardware needed)

Most wanted contributions:

  • Hikvision adapter
  • Dahua adapter
  • Synology Surveillance Station adapter
  • Vision-based event description (send snapshot to LLM)
  • Home Assistant custom integration

FAQ

Does my camera data leave my network? Only if you use a cloud LLM backend (OpenAI, Anthropic). With Ollama, everything — including the AI processing — stays on your local machine.

Which Frigate version is supported? Frigate 0.12+ is tested. Most features work with 0.9+.

Can I use this with any ONVIF camera? Yes. ONVIF Profile S is supported for live streaming and snapshots. Profile G adds recording/clip support.

Can I query multiple camera systems at once? Yes — use "multi": true in your query request to fan out across all registered adapters simultaneously.

Is there a Home Assistant integration? A native Home Assistant custom integration is planned. For now, use the REST API endpoint from HA automations.


Roadmap

  • Vision analysis — pass event snapshots to multimodal LLMs for rich descriptions
  • Hikvision adapter
  • Dahua adapter
  • Web UI (lightweight chat interface)
  • Multi-system queries (query across multiple NVRs simultaneously)
  • Alert rules via natural language ("notify me when a person enters Zone A after 10pm")
  • Voice interface (Whisper STT + TTS output)
  • Multi-channel notifications — Telegram, Slack, ntfy, email, webhook
  • PTZ control via REST API (pan, tilt, zoom, presets)
  • Session persistence — conversation history survives server restarts (SQLite)
  • Event log — every detection written to SQLite; exportable as CSV/JSON
  • Camera health monitoring — per-camera online/offline status with background polling
  • Prometheus metrics — cameras online/offline, alert rule count
  • Home Assistant custom integration — sensors, binary sensors, services, HACS-ready
  • ONVIF discovery — auto-detect cameras on the local network (cctvql discover CLI + GET /discover/onvif)
  • Event timeline UI — visual heatmap timeline at /timeline with camera rows, time buckets, tooltips, auto-refresh
  • Face recognition — enroll known individuals; auto-matched across event snapshots (/faces/*, pip install cctvql[face])
  • AI event summaries — GET /events/{id}/summary with LLM description + face matches in one call
  • Mobile push notifications — FCM alerts to iOS/Android devices (/push/*, pip install cctvql[push])
  • Anomaly detection — statistical spike/silence detection per camera with z-score baseline (GET /anomalies)
  • Multi-tenant support — JWT auth, per-user camera permissions, admin user management (CCTVQL_MULTI_TENANT=1)
  • Mobile app — React Native (Expo) iOS + Android client with live events, NLP chat, PTZ joystick, face enrolment
  • Face recognition NLP integration — "Was Alice home last night?" routes to search_faces intent, scans event snapshots for the named person
  • DeepFace backend option — pluggable BaseFaceBackend; ArcFace 512-d cosine, GPU support, select via CCTVQL_FACE_BACKEND=deepface
  • InsightFace backend option — ONNX Runtime ArcFace 512-d cosine, GPU/CPU auto-select, select via CCTVQL_FACE_BACKEND=insightface (pip install cctvql[insightface])
  • EAS mobile build pipeline — eas.json profiles, OTA update CI workflow, store submission workflow on mobile/v* tags
  • App Store / Play Store submission (requires Apple/Google developer credentials)

Sponsor

cctvQL is free and open-source. If it saves you time or powers something you care about, consider sponsoring — it helps keep the project maintained and moving forward.

Sponsor arunrajiah


License

MIT © 2026 arunrajiah

See LICENSE for the full text.


If cctvQL is useful to you, please ⭐ the repo — it helps others find it!

About

Conversational query layer for CCTV and surveillance systems — ask questions in plain English, get answers from Frigate, ONVIF, and more.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

8 stars

Watchers

3 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages