Pluggable async home security camera pipeline with detection, VLM analysis, and alerts.
Project description
HomeSec
HomeSec is a self-hosted, extensible video pipeline for home security cameras. You can connect cameras directly via RTSP, receive clips over FTP, or implement your own ClipSource. From there, the pipeline filters events with AI and sends smart notifications. Your footage stays private and off third-party clouds.
Design Principles
- Local-Only Data Processing: Video footage remains on the local network by default. Cloud usage (Storage, VLM/OpenAI) is strictly opt-in.
- Modular Architecture: All major components (sources, filters, analyzers, notifiers) are decoupled plugins defined by strict interfaces. If you want to use a different AI model or storage backend, you can swap it out with a few lines of Python.
- Resilience: The primary resilience feature is backing up clips to storage. The pipeline handles intermittent stream failures and network instability without crashing or stalling.
Pipeline at a glance
graph TD
%% Layout Wrapper for horizontal alignment
subgraph Wrapper [" "]
direction LR
style Wrapper fill:none,stroke:none
S[Clip Source]
subgraph Pipeline [Media Processing Pipeline]
direction TB
C(Clip File) --> U([Upload to Storage])
C --> F([Detect objects: YOLO])
F -->|Detected objects| AI{Trigger classes filter}
AI -->|Yes| V([VLM Analysis])
AI -->|No| D([Discard])
V -->|Risk level, detected objects| P{Alert Policy filter}
P -->|No| D
P -->|YES| N[Notifiers]
end
S -->|New Clip File| Pipeline
PG[(Postgres)]
Pipeline -.->|State & Events| PG
end
- Parallel Processing: Upload and filter run in parallel.
- Resilience: Upload failures do not block alerts; filter failures stop expensive VLM calls.
- State: Metadata is stored in Postgres (
clip_states+clip_events) for full observability.
Table of Contents
- Highlights
- Pipeline at a glance
- Quickstart
- Configuration
- Plugins
- Observability
- Development
- Contributing
- License
Highlights
- Multiple pluggable video clip sources: RTSP motion detection, FTP uploads, or a watched folder
- Parallel upload + filter (YOLO) with frame sampling and early exit
- OpenAI-compatible VLM analysis with structured output
- Policy-driven alerts with per-camera overrides
- Fan-out notifiers (MQTT for Home Assistant, SendGrid email)
- Postgres-backed state + events with graceful degradation
- Health endpoint plus optional Postgres telemetry logging
Quickstart
Docker
Use the included docker-compose.yml (HomeSec + Postgres, pulls leva/homesec:latest).
Configure your own config.yaml and .env files as described in Manual Setup.
Manual Setup
For standard production usage without Docker Compose:
-
Prerequisites:
- Python 3.10+
- ffmpeg
- PostgreSQL (running and accessible)
-
Install
pip install homesec
-
Configure
# Download example config & env curl -O https://raw.githubusercontent.com/lan17/homesec/main/config/example.yaml mv example.yaml config.yaml curl -O https://raw.githubusercontent.com/lan17/homesec/main/.env.example mv .env.example .env # Setup environment (DB_DSN is required) # Edit .env to set your secrets! export DB_DSN="postgresql://user:pass@localhost/homesec"
-
Run
homesec run --config config.yaml
Developer Setup
If you are contributing or running from source:
-
Install dependencies
uv sync -
Start Infrastructure
make db # Starts just Postgres in Docker
-
Run
uv run python -m homesec.cli run --config config/config.yaml
Configuration
Configuration is YAML-based and strictly validated. Secrets (API keys, passwords) should always be loaded from environment variables (_env suffix).
Configuration Examples
1. The "Power User" (Robust RTSP)
Best for real-world setups with flaky cameras.
cameras:
- name: driveway
source:
backend: rtsp
config:
rtsp_url_env: DRIVEWAY_RTSP_URL
output_dir: "./recordings"
stream:
# Critical for camera compatibility:
ffmpeg_flags: ["-rtsp_transport", "tcp", "-vsync", "0"]
reconnect:
backoff_s: 5
filter:
backend: yolo
config:
classes: ["person", "car"]
min_confidence: 0.6
In your .env:
DRIVEWAY_RTSP_URL="rtsp://user:pass@192.168.1.100:554/stream"
2. The "Cloud Storage" (Dropbox)
Uploads to Cloud but keeps analysis local.
storage:
backend: dropbox
config:
token_env: DROPBOX_TOKEN
root: "/SecurityCam"
notifiers:
- backend: sendgrid_email
config:
api_key_env: SENDGRID_API_KEY
to_emails: ["me@example.com"]
In your .env:
DROPBOX_TOKEN="sl.Al..."
SENDGRID_API_KEY="SG.xyz..."
See config/example.yaml for a complete reference of all options.
Tips
- Secrets: Never put secrets in YAML. Use env vars (
*_env) and set them in your shell or.env. - Notifiers: Notifiers are optional. With no enabled notifiers, alert decisions are still evaluated and recorded, but no external notifications are sent.
- YOLO Classes: Built-in classes include
person,car,truck,motorcycle,bicycle,dog,cat,bird,backpack,handbag,suitcase. - Preview storage:
preview.config.storage_diris scratch space for on-demand HLS live preview output from RTSP sources. Prefer tmpfs and keep it separate fromrecordings/and durable storage. Preview defaults torecording_policy: stop_on_recording;allow_during_recordingis best-effort and may consume an extra RTSP session. Seedocs/preview-deployment.md.
After installation, the homesec command is available:
homesec --help
Commands
Run the pipeline:
homesec run --config config.yaml
Validate config:
homesec validate --config config.yaml
Cleanup old clips (reanalyze and optionally delete empty clips):
homesec cleanup --config config.yaml --older_than_days 7 --dry_run=False
Use homesec <command> --help for detailed options on each command.
Plugins
Extensible by design
We designed HomeSec to be modular. Each major capability is an interface (ClipSource, StorageBackend, ObjectFilter, VLMAnalyzer, AlertPolicy, Notifier) defined in src/homesec/interfaces.py. This means you can swap out components (like replacing YOLO with a different detector) without changing the core pipeline.
HomeSec uses a plugin architecture where every component is discovered at runtime via entry points.
Built-in plugins
| Type | Plugins |
|---|---|
| Sources | rtsp, ftp, local_folder |
| Filters | yolo |
| Storage | dropbox, local |
| VLM analyzers | openai |
| Notifiers | mqtt, sendgrid_email |
| Alert policies | default, noop |
Plugin interfaces
All interfaces are defined in src/homesec/interfaces.py.
| Type | Interface | Decorator |
|---|---|---|
| Sources | ClipSource |
@source_plugin |
| Filters | ObjectFilter |
@filter_plugin |
| Storage | StorageBackend |
@storage_plugin |
| VLM analyzers | VLMAnalyzer |
@vlm_plugin |
| Notifiers | Notifier |
@notifier_plugin |
| Alert policies | AlertPolicy |
@alert_policy_plugin |
Writing a custom plugin
Extending HomeSec is designed to be easy. You can write custom sources, filters, storage backends, and more.
👉 See PLUGIN_DEVELOPMENT.md for a complete guide.
Observability
- Health endpoint:
GET /health(served by FastAPI onserver.host/server.port) - Telemetry logs to Postgres when
DB_DSNis set
Development
Setup
- Clone the repository
- Install uv for dependency management
uv syncto install dependenciesmake dbto start Postgres locally
Commands
- Run tests:
make test - Run type checking (strict):
make typecheck - Run both:
make check - Run the pipeline:
make run
Notes
- Tests must include Given/When/Then comments
- Architecture notes:
DESIGN.md
Contributing
Contributions are welcome! Here's how to get started:
- Fork and clone the repository
- Create a branch for your feature or fix:
git checkout -b my-feature - Install dependencies:
uv sync - Make your changes and ensure tests pass:
make check - Submit a pull request with a clear description of your changes
Guidelines
- All code must pass CI checks:
make check - Tests should include Given/When/Then comments explaining the test scenario
- New plugins should follow the existing patterns in
src/homesec/plugins/ - Keep PRs focused on a single change for easier review
Reporting Issues
Found a bug or have a feature request? Please open an issue with:
- A clear description of the problem or suggestion
- Steps to reproduce (for bugs)
- Your environment (OS, Python version, HomeSec version)
License
Apache 2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file homesec-1.9.0.tar.gz.
File metadata
- Download URL: homesec-1.9.0.tar.gz
- Upload date:
- Size: 864.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bdf07ef468b9a58fb3e0dd7fcd944fdde030a7ef8390a3f435e687141040788
|
|
| MD5 |
097a2b2693d10dbe701ee5547bd1dfef
|
|
| BLAKE2b-256 |
5db7faa00bd09a9896ce96f29ba67a762782a2af2943f1313cbb4aff3e552ede
|
Provenance
The following attestation bundles were made for homesec-1.9.0.tar.gz:
Publisher:
release.yaml on lan17/homesec
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
homesec-1.9.0.tar.gz -
Subject digest:
9bdf07ef468b9a58fb3e0dd7fcd944fdde030a7ef8390a3f435e687141040788 - Sigstore transparency entry: 1366985287
- Sigstore integration time:
-
Permalink:
lan17/homesec@6222c9ebe0b3ae1d6f776a0119cf6ebfcdaa4290 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lan17
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@6222c9ebe0b3ae1d6f776a0119cf6ebfcdaa4290 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file homesec-1.9.0-py3-none-any.whl.
File metadata
- Download URL: homesec-1.9.0-py3-none-any.whl
- Upload date:
- Size: 255.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5553ca3ebed60acf443923239cf2a91f4973399b80588b25b709e63a426fcd93
|
|
| MD5 |
72dd6552ecf696f4a3298f6d02252c04
|
|
| BLAKE2b-256 |
157de821d7953c33ea76413ab4a124f0693ca15a0a28168021029861cee04a5c
|
Provenance
The following attestation bundles were made for homesec-1.9.0-py3-none-any.whl:
Publisher:
release.yaml on lan17/homesec
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
homesec-1.9.0-py3-none-any.whl -
Subject digest:
5553ca3ebed60acf443923239cf2a91f4973399b80588b25b709e63a426fcd93 - Sigstore transparency entry: 1366985336
- Sigstore integration time:
-
Permalink:
lan17/homesec@6222c9ebe0b3ae1d6f776a0119cf6ebfcdaa4290 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lan17
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@6222c9ebe0b3ae1d6f776a0119cf6ebfcdaa4290 -
Trigger Event:
workflow_dispatch
-
Statement type: