From f2f4cc52a3cb14873e1a4171242b56858c125371 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Mon, 18 May 2026 20:09:01 +0000 Subject: [PATCH 1/3] docs: refresh README landing page --- README.md | 455 ++++++++++++++++++++++++------------------------------ 1 file changed, 202 insertions(+), 253 deletions(-) diff --git a/README.md b/README.md index 9634f1c9..cd166ad1 100644 --- a/README.md +++ b/README.md @@ -4,324 +4,273 @@ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![Python: 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/) [![Typing: Typed](https://img.shields.io/badge/typing-typed-2b825b)](https://peps.python.org/pep-0561/) -[![codecov](https://codecov.io/gh/lan17/HomeSec/branch/main/graph/badge.svg)](https://codecov.io/gh/lan17/HomeSec) +[![codecov](https://codecov.io/gh/lan17/homesec/branch/main/graph/badge.svg)](https://codecov.io/gh/lan17/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. +**Local-first AI security cameras for people who want smarter alerts without handing their footage to a vendor cloud.** -## Design Principles +HomeSec is a self-hosted camera system and video intelligence pipeline. It can watch live RTSP feeds, capture motion events, filter noisy clips with object detection, ask an OpenAI-compatible vision model what happened, and send policy-driven alerts only when something matters. Footage stays local by default; cloud storage, VLM calls, and notifications are explicit opt-ins. -- **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. +> **Status:** HomeSec is an alpha-stage home-lab project. It is designed for trusted local networks, VPNs, and carefully managed self-hosted deployments. Enable API-key auth and put it behind your own access controls before exposing it outside your LAN. -## Pipeline at a glance +## Why HomeSec? +- **High-signal alerts** — YOLO filters boring motion before VLM analysis, then alert policy decides what deserves a notification. +- **Local-first privacy** — raw clips are written locally first; Dropbox, OpenAI-compatible VLMs, MQTT, and email are all configurable integrations. +- **Self-serve control plane** — a FastAPI backend serves a React UI for setup, live view, events, camera settings, health, stats, and backups. +- **Real camera support** — RTSP motion recording, FTP uploads, watched folders, ONVIF discovery/preflight, live HLS previews, and experimental push-to-talk paths. +- **Hackable by design** — sources, filters, storage, VLM analyzers, alert policies, and notifiers are plugins with typed config boundaries. +## What it does -```mermaid -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 -``` +| Area | Capabilities | +| --- | --- | +| Camera ingest | RTSP motion recording, FTP uploads, local folder watching | +| Live view | On-demand HLS previews for RTSP sources, with UI cards for each camera | +| Event intelligence | YOLO object filtering, VLM scene analysis, risk/activity classification | +| Alerts | Per-camera policy overrides, MQTT for Home Assistant/Node-RED, SendGrid email | +| Storage | Local filesystem or Dropbox, with clip/event state tracked in Postgres | +| Operations | React setup wizard, config validation, runtime reloads, health/stats APIs, Postgres backups | +| Advanced camera control | ONVIF setup/probing and push-to-talk support for compatible RTSP/Tapo cameras | -- **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](#highlights) -- [Pipeline at a glance](#pipeline-at-a-glance) -- [Quickstart](#quickstart) - - [30-Second Start (Docker)](#30-second-start-docker) - - [Manual Setup](#manual-setup) -- [Configuration](#configuration) - - [Commands](#commands) -- [Plugins](#plugins) - - [Built-in plugins](#built-in-plugins) - - [Plugin interfaces](#plugin-interfaces) - - [Writing a custom plugin](#writing-a-custom-plugin) -- [Observability](#observability) -- [Development](#development) -- [Contributing](#contributing) -- [License](#license) - -## Highlights - -- Multiple pluggable video clip sources: [RTSP](https://en.wikipedia.org/wiki/Real-Time_Streaming_Protocol) motion detection, [FTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol) uploads, or a watched folder -- Parallel upload + filter ([YOLO](https://en.wikipedia.org/wiki/You_Only_Look_Once)) 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 -- Push-to-talk for RTSP cameras with ONVIF audio backchannel support and a local - TP-Link Tapo talkback backend path - - - -## Quickstart - -### Docker -Use the included [docker-compose.yml](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: - -1. **Prerequisites**: - - Python 3.10+ - - ffmpeg - - PostgreSQL (running and accessible) - -2. **Install** - ```bash - pip install homesec - ``` - -3. **Configure** - ```bash - # 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" - ``` - -4. **Run** - ```bash - homesec run --config config.yaml - ``` - -### Developer Setup -If you are contributing or running from source: - -1. **Install dependencies** - ```bash - uv sync - ``` - -2. **Start Infrastructure** - ```bash - make db # Starts just Postgres in Docker - ``` - -3. **Run** - ```bash - uv run python -m homesec.cli run --config config/config.yaml - ``` +## Quickstart: Docker Compose +Docker Compose is the easiest way to run HomeSec with the bundled FastAPI server, React UI, and Postgres. -## Configuration +```bash +git clone https://github.com/lan17/homesec.git +cd homesec -Configuration is YAML-based and strictly validated. Secrets (API keys, passwords) should always be loaded from environment variables (`_env` suffix). +cp .env.example .env +cp config/example.yaml config/config.yaml -### Configuration Examples +# Edit at least one camera URL and any provider secrets. +$EDITOR .env +$EDITOR config/config.yaml -#### 1. The "Power User" (Robust RTSP) -Best for real-world setups with flaky cameras. +docker compose up -d --build +``` -```yaml -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 +Then open: -filter: - backend: yolo - config: - classes: ["person", "car"] - min_confidence: 0.6 +```text +http://localhost:8081 ``` -In your `.env`: +Useful follow-up commands: + ```bash -DRIVEWAY_RTSP_URL="rtsp://user:pass@192.168.1.100:554/stream" +docker compose logs -f homesec +docker compose down ``` -#### 2. The "Cloud Storage" (Dropbox) -Uploads to Cloud but keeps analysis local. +The example config includes RTSP, FTP, local folder, Dropbox, MQTT, SendGrid, YOLO, OpenAI-compatible VLM, preview, and backup settings. Disable anything you do not use; notifiers are optional. -```yaml -storage: - backend: dropbox - config: - token_env: DROPBOX_TOKEN - root: "/SecurityCam" +## Quickstart: Python package -notifiers: - - backend: sendgrid_email - config: - api_key_env: SENDGRID_API_KEY - to_emails: ["me@example.com"] -``` +The Docker image is the recommended path for the bundled web UI because it ships with built React assets. Direct package installs are useful for custom deployments, source development, or runtime/API-only packaging where you control `server.ui_dist_dir`. -In your `.env`: ```bash -DROPBOX_TOKEN="sl.Al..." -SENDGRID_API_KEY="SG.xyz..." +pip install homesec +curl -O https://raw.githubusercontent.com/lan17/homesec/main/config/example.yaml +curl -O https://raw.githubusercontent.com/lan17/homesec/main/.env.example +mkdir -p config +mv example.yaml config/config.yaml +mv .env.example .env + +# Set DB_DSN, camera URLs, and provider secrets in .env. +homesec validate --config config/config.yaml +homesec run --config config/config.yaml ``` -See [`config/example.yaml`](config/example.yaml) for a complete reference of all options. +If you run from a source checkout and want the web UI, build it first with `make ui-install && make ui-build` or set `server.ui_dist_dir` to an existing UI build. If the configured file is missing, `homesec run` starts the API/UI in bootstrap mode so you can use the setup wizard. -### Tips +## Web UI -- **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_dir` is scratch space for on-demand HLS live preview output from RTSP sources. Prefer tmpfs and keep it separate from `recordings/` and durable storage. Preview defaults to `recording_policy: stop_on_recording`; `allow_during_recording` is best-effort and may consume an extra RTSP session. See [`docs/preview-deployment.md`](docs/preview-deployment.md). -- **Push-to-talk**: Browser microphone to camera speaker support is auto-probed for RTSP cameras by default. HomeSec tries standards-based backends first; the bundled ONVIF backend supports `PCMU/8000` and `PCMA/8000`, and the bundled `tapo_local` backend implements a local TP-Link Tapo talkback path without TP-Link cloud calls at runtime. Use `cameras[].talk.backend: onvif_rtsp_backchannel` or `cameras[].talk.backend: tapo_local` for explicit selection. Tapo local talk defaults to username `admin`, can derive host and password material from the RTSP URL, and can use explicit backend env vars when credentials differ. Opt out cameras with `cameras[].talk.mode: disabled` when needed. Physical Tapo C120 compatibility still needs per-firmware validation. See [`docs/push-to-talk.md`](docs/push-to-talk.md). +The backend serves the built UI on the same port as the API. The UI is organized around the daily operator loop: -After installation, the `homesec` command is available: +- **Live** — watch configured cameras, start previews, use push-to-talk where supported, and jump to recent events. +- **Events** — browse clips, filter by camera/detection/alert state, and inspect VLM summaries and media. +- **Settings** — add or edit cameras, storage, detection, VLM, alert policy, and notifiers with secret-safe config handling. +- **System** — check health, daily stats, runtime uptime, camera status, and Postgres backup status. +- **Setup** — first-run wizard for cameras, storage, detection, notifications, review, and launch. -```bash -homesec --help -``` +UI development notes live in [`ui/README.md`](ui/README.md). -### Commands +## How the pipeline works -**Run the pipeline:** -```bash -homesec run --config config.yaml -``` +```mermaid +flowchart LR + subgraph Cameras + RTSP[RTSP camera] + FTP[FTP upload] + Folder[Watched folder] + end -**Validate config:** -```bash -homesec validate --config config.yaml + subgraph HomeSec + API[FastAPI + React UI] + Runtime[Runtime manager] + Clips[(Local clips)] + DB[(Postgres state + events)] + Filter[YOLO object filter] + VLM[VLM analysis] + Policy[Alert policy] + end + + subgraph Integrations + Storage[Local/Dropbox storage] + Notify[MQTT / SendGrid] + end + + RTSP --> Runtime + FTP --> Runtime + Folder --> Runtime + API <--> Runtime + API <--> DB + Runtime --> Clips + Runtime --> DB + Clips --> Storage + Clips --> Filter + Filter -->|trigger classes| VLM + Filter -->|no match| DB + VLM --> Policy + Policy -->|alert| Notify + Policy --> DB ``` -**Cleanup old clips** (reanalyze and optionally delete empty clips): -```bash -homesec cleanup --config config.yaml --older_than_days 7 --dry_run=False +A clip is written locally first, then upload and filtering run in parallel. If the filter sees a configured trigger class, HomeSec sends sampled frames to the VLM. The alert policy combines VLM risk/activity output with per-camera overrides before notifying. Postgres records clip state and events for the UI and operational visibility. + +## Configuration + +HomeSec configuration is YAML-based and validated with Pydantic. Secrets should be referenced via environment variables instead of committed to YAML. + +```yaml +cameras: + - name: front_door + source: + backend: rtsp + config: + rtsp_url_env: FRONT_DOOR_RTSP_URL + output_dir: ./recordings + +storage: + backend: local + config: + root: ./storage + +notifiers: + - backend: mqtt + config: + host: localhost + topic_template: homecam/alerts/{camera_name} + +filter: + backend: yolo + config: + classes: [person, car, dog, cat] + min_confidence: 0.5 + +vlm: + backend: openai + trigger_classes: [person] + run_mode: trigger_only + config: + api_key_env: OPENAI_API_KEY + model: gpt-4o + +alert_policy: + backend: default + config: + min_risk_level: medium + notify_on_activity_types: [person_at_door, delivery, suspicious] ``` -Use `homesec --help` for detailed options on each command. +See [`config/example.yaml`](config/example.yaml) for the full reference example and [`docs/preview-deployment.md`](docs/preview-deployment.md), [`docs/postgres-backups.md`](docs/postgres-backups.md), and [`docs/push-to-talk.md`](docs/push-to-talk.md) for deployment-specific notes. -## Plugins +### Security and privacy notes -### Extensible by design +- Keep camera credentials and API tokens in `.env`, then reference them with `*_env` fields. +- HomeSec binds to `0.0.0.0:8081` by default so Docker/LAN access works. Treat that as a trusted-network service unless you add your own perimeter controls. +- API-key auth is available with: -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. + ```yaml + server: + auth_enabled: true + api_key_env: HOMESEC_API_KEY + ``` -### Built-in plugins +- VLM analysis sends selected frames to the configured OpenAI-compatible endpoint only when `vlm.run_mode` and `trigger_classes` allow it. +- Push-to-talk microphone audio is streamed for the active talk session and is not intentionally persisted; camera compatibility still varies by model/firmware. -| Type | Plugins | -|------|---------| +## Built-in integrations + +| Type | Built-ins | +| --- | --- | | Sources | [`rtsp`](src/homesec/sources/rtsp/core.py), [`ftp`](src/homesec/sources/ftp.py), [`local_folder`](src/homesec/sources/local_folder.py) | | Filters | [`yolo`](src/homesec/plugins/filters/yolo.py) | -| Storage | [`dropbox`](src/homesec/plugins/storage/dropbox.py), [`local`](src/homesec/plugins/storage/local.py) | +| Storage | [`local`](src/homesec/plugins/storage/local.py), [`dropbox`](src/homesec/plugins/storage/dropbox.py) | | VLM analyzers | [`openai`](src/homesec/plugins/analyzers/openai.py) | | Notifiers | [`mqtt`](src/homesec/plugins/notifiers/mqtt.py), [`sendgrid_email`](src/homesec/plugins/notifiers/sendgrid_email.py) | | Alert policies | [`default`](src/homesec/plugins/alert_policies/default.py), [`noop`](src/homesec/plugins/alert_policies/noop.py) | -### Plugin interfaces - -All interfaces are defined in [`src/homesec/interfaces.py`](src/homesec/interfaces.py). +## Extending HomeSec -| 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` | +HomeSec is built around strict interfaces and runtime plugin discovery. Each major capability is replaceable: -### Writing a custom plugin +- `ClipSource` for new camera/event sources +- `ObjectFilter` for different detectors +- `StorageBackend` for S3, NAS, or custom retention behavior +- `VLMAnalyzer` for local or hosted multimodal models +- `AlertPolicy` for custom notification rules +- `Notifier` for chat, paging, automations, or smart-home integrations -Extending HomeSec is designed to be easy. You can write custom sources, filters, storage backends, and more. +See [`PLUGIN_DEVELOPMENT.md`](PLUGIN_DEVELOPMENT.md) for the complete plugin guide. -👉 **See [PLUGIN_DEVELOPMENT.md](PLUGIN_DEVELOPMENT.md) for a complete guide.** +## CLI reference -## Observability - -- Health endpoint: `GET /health` (served by FastAPI on `server.host`/`server.port`) -- Telemetry logs to Postgres when `DB_DSN` is set +```bash +homesec --help +homesec validate --config config/config.yaml +homesec run --config config/config.yaml +homesec cleanup --config config/config.yaml --older_than_days 7 --dry_run=False +``` ## Development -### Setup - -1. Clone the repository -2. Install [uv](https://docs.astral.sh/uv/) for dependency management -3. `uv sync` to install dependencies -4. `make db` to start Postgres locally +```bash +git clone https://github.com/lan17/homesec.git +cd homesec +uv sync +make ui-install +make ui-build +make db +make run +``` -### Commands +Common checks: -- Run tests: `make test` -- Run type checking (strict): `make typecheck` -- Run both: `make check` -- Run the pipeline: `make run` +```bash +make test +make typecheck +make lint +make ui-check +make check +``` -### Notes +The UI uses Vite + React + TypeScript and lives under [`ui/`](ui/). API client types are generated from the FastAPI OpenAPI contract. -- Tests must include Given/When/Then comments -- Architecture notes: `DESIGN.md` +For architecture notes, see [`DESIGN.md`](DESIGN.md). Some sections are intentionally deeper than the README and may describe historical design context. ## Contributing -Contributions are welcome! Here's how to get started: - -1. **Fork and clone** the repository -2. **Create a branch** for your feature or fix: `git checkout -b my-feature` -3. **Install dependencies**: `uv sync` -4. **Make your changes** and ensure tests pass: `make check` -5. **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 +Contributions are welcome, especially around camera compatibility, storage/notifier plugins, local model integrations, UI polish, and deployment docs. -### Reporting Issues +1. Fork and clone the repository. +2. Create a focused branch. +3. Run the relevant tests/checks. +4. Open a pull request with the behavior change, validation, and any compatibility notes. -Found a bug or have a feature request? Please [open an issue](../../issues) with: -- A clear description of the problem or suggestion -- Steps to reproduce (for bugs) -- Your environment (OS, Python version, HomeSec version) +Found a bug or have a feature request? Please [open an issue](https://github.com/lan17/homesec/issues) with reproduction steps, environment details, and relevant logs. ## License -Apache 2.0. See `LICENSE`. +Apache 2.0. See [`LICENSE`](LICENSE). From 56c080f1642c155ca2623588b38e421576d97232 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Mon, 18 May 2026 21:03:07 +0000 Subject: [PATCH 2/3] docs: humanize README tone --- README.md | 76 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index cd166ad1..7308fb97 100644 --- a/README.md +++ b/README.md @@ -6,35 +6,37 @@ [![Typing: Typed](https://img.shields.io/badge/typing-typed-2b825b)](https://peps.python.org/pep-0561/) [![codecov](https://codecov.io/gh/lan17/homesec/branch/main/graph/badge.svg)](https://codecov.io/gh/lan17/homesec) -**Local-first AI security cameras for people who want smarter alerts without handing their footage to a vendor cloud.** +**HomeSec helps your cameras tell you when something actually matters.** -HomeSec is a self-hosted camera system and video intelligence pipeline. It can watch live RTSP feeds, capture motion events, filter noisy clips with object detection, ask an OpenAI-compatible vision model what happened, and send policy-driven alerts only when something matters. Footage stays local by default; cloud storage, VLM calls, and notifications are explicit opt-ins. +Most home camera setups have the same two problems: they either bury you in motion spam, or they make you send your footage through someone else's cloud. HomeSec is a self-hosted alternative. It watches your cameras, records motion events, filters out boring clips, asks a vision model what happened when needed, and only alerts when the event looks worth your attention. -> **Status:** HomeSec is an alpha-stage home-lab project. It is designed for trusted local networks, VPNs, and carefully managed self-hosted deployments. Enable API-key auth and put it behind your own access controls before exposing it outside your LAN. +Footage is written locally first. Cloud storage, vision-model calls, MQTT, and email alerts are all things you choose to turn on. + +> **Status:** HomeSec is still an alpha-stage home-lab project. It works best on trusted local networks or behind your own VPN/reverse proxy. If you expose it outside your LAN, enable API-key auth and put proper access controls in front of it. ## Why HomeSec? -- **High-signal alerts** — YOLO filters boring motion before VLM analysis, then alert policy decides what deserves a notification. -- **Local-first privacy** — raw clips are written locally first; Dropbox, OpenAI-compatible VLMs, MQTT, and email are all configurable integrations. -- **Self-serve control plane** — a FastAPI backend serves a React UI for setup, live view, events, camera settings, health, stats, and backups. -- **Real camera support** — RTSP motion recording, FTP uploads, watched folders, ONVIF discovery/preflight, live HLS previews, and experimental push-to-talk paths. -- **Hackable by design** — sources, filters, storage, VLM analyzers, alert policies, and notifiers are plugins with typed config boundaries. +- **Fewer useless alerts** — motion starts the pipeline, but YOLO and the alert policy decide whether a clip is actually interesting. +- **Your footage stays yours** — clips live locally by default, and cloud integrations are optional. +- **A web UI for the everyday loop** — check live feeds, review events, adjust settings, and see system health without SSHing into the box. +- **Works with normal IP-camera setups** — RTSP, FTP uploads, watched folders, ONVIF discovery/preflight, HLS preview, and experimental push-to-talk support. +- **Easy to tinker with** — swap in different sources, filters, storage backends, vision models, alert rules, or notification targets. ## What it does -| Area | Capabilities | +| Area | What you get | | --- | --- | -| Camera ingest | RTSP motion recording, FTP uploads, local folder watching | -| Live view | On-demand HLS previews for RTSP sources, with UI cards for each camera | -| Event intelligence | YOLO object filtering, VLM scene analysis, risk/activity classification | -| Alerts | Per-camera policy overrides, MQTT for Home Assistant/Node-RED, SendGrid email | -| Storage | Local filesystem or Dropbox, with clip/event state tracked in Postgres | -| Operations | React setup wizard, config validation, runtime reloads, health/stats APIs, Postgres backups | -| Advanced camera control | ONVIF setup/probing and push-to-talk support for compatible RTSP/Tapo cameras | +| Camera ingest | RTSP motion recording, FTP uploads, and local folder watching | +| Live view | On-demand HLS previews for RTSP cameras, shown as camera cards in the UI | +| Event review | A searchable event list with clips, detection results, VLM summaries, and alert decisions | +| Smarter alerts | Object filtering, vision-model analysis, per-camera policy overrides, MQTT, and SendGrid email | +| Storage | Local filesystem or Dropbox, with clip state and events tracked in Postgres | +| Day-to-day ops | Setup wizard, config validation, runtime reloads, health checks, stats, and Postgres backups | +| Camera extras | ONVIF setup/probing and push-to-talk paths for compatible RTSP/Tapo cameras | ## Quickstart: Docker Compose -Docker Compose is the easiest way to run HomeSec with the bundled FastAPI server, React UI, and Postgres. +Docker Compose is the simplest way to try HomeSec. It runs HomeSec, the web UI, and Postgres together. ```bash git clone https://github.com/lan17/homesec.git @@ -63,11 +65,11 @@ docker compose logs -f homesec docker compose down ``` -The example config includes RTSP, FTP, local folder, Dropbox, MQTT, SendGrid, YOLO, OpenAI-compatible VLM, preview, and backup settings. Disable anything you do not use; notifiers are optional. +The example config is intentionally broad: it shows RTSP, FTP, local folders, Dropbox, MQTT, SendGrid, YOLO, OpenAI-compatible VLMs, live preview, and backups. Start by disabling what you do not need. You can run HomeSec with no notifiers if you only want analysis and event history. ## Quickstart: Python package -The Docker image is the recommended path for the bundled web UI because it ships with built React assets. Direct package installs are useful for custom deployments, source development, or runtime/API-only packaging where you control `server.ui_dist_dir`. +The Docker image is the best path if you want the bundled web UI right away, because it already includes the built React assets. A direct package install is useful when you are building your own deployment, running from source, or controlling `server.ui_dist_dir` yourself. ```bash pip install homesec @@ -82,17 +84,17 @@ homesec validate --config config/config.yaml homesec run --config config/config.yaml ``` -If you run from a source checkout and want the web UI, build it first with `make ui-install && make ui-build` or set `server.ui_dist_dir` to an existing UI build. If the configured file is missing, `homesec run` starts the API/UI in bootstrap mode so you can use the setup wizard. +If you run from a source checkout and want the web UI, build it first with `make ui-install && make ui-build`, or point `server.ui_dist_dir` at an existing UI build. If the config file is missing, `homesec run` starts in bootstrap mode so you can use the setup wizard. ## Web UI -The backend serves the built UI on the same port as the API. The UI is organized around the daily operator loop: +The backend serves the built UI on the same port as the API. The main pages are: - **Live** — watch configured cameras, start previews, use push-to-talk where supported, and jump to recent events. -- **Events** — browse clips, filter by camera/detection/alert state, and inspect VLM summaries and media. -- **Settings** — add or edit cameras, storage, detection, VLM, alert policy, and notifiers with secret-safe config handling. +- **Events** — review clips, filter by camera/detection/alert state, and inspect the media and VLM summary. +- **Settings** — add or edit cameras, storage, detection, VLM, alert policy, and notifiers. - **System** — check health, daily stats, runtime uptime, camera status, and Postgres backup status. -- **Setup** — first-run wizard for cameras, storage, detection, notifications, review, and launch. +- **Setup** — walk through cameras, storage, detection, notifications, review, and launch on first run. UI development notes live in [`ui/README.md`](ui/README.md). @@ -137,11 +139,13 @@ flowchart LR Policy --> DB ``` -A clip is written locally first, then upload and filtering run in parallel. If the filter sees a configured trigger class, HomeSec sends sampled frames to the VLM. The alert policy combines VLM risk/activity output with per-camera overrides before notifying. Postgres records clip state and events for the UI and operational visibility. +A clip is saved locally first. Upload and object detection then run in parallel, so a storage hiccup does not stop detection and an empty clip does not waste a VLM call. If the detector sees one of your trigger classes, HomeSec samples frames for the vision model. The alert policy combines that result with your per-camera rules before sending notifications. + +Postgres keeps the event history and clip state that power the UI. The pipeline is designed to degrade gracefully: camera footage is still written locally even when an external service is unavailable. ## Configuration -HomeSec configuration is YAML-based and validated with Pydantic. Secrets should be referenced via environment variables instead of committed to YAML. +Configuration is YAML, validated with Pydantic. Put secrets in `.env`, then reference them from YAML with `*_env` fields. ```yaml cameras: @@ -184,12 +188,12 @@ alert_policy: notify_on_activity_types: [person_at_door, delivery, suspicious] ``` -See [`config/example.yaml`](config/example.yaml) for the full reference example and [`docs/preview-deployment.md`](docs/preview-deployment.md), [`docs/postgres-backups.md`](docs/postgres-backups.md), and [`docs/push-to-talk.md`](docs/push-to-talk.md) for deployment-specific notes. +See [`config/example.yaml`](config/example.yaml) for the full example. There are also focused notes for [`live preview`](docs/preview-deployment.md), [`Postgres backups`](docs/postgres-backups.md), and [`push-to-talk`](docs/push-to-talk.md). ### Security and privacy notes -- Keep camera credentials and API tokens in `.env`, then reference them with `*_env` fields. -- HomeSec binds to `0.0.0.0:8081` by default so Docker/LAN access works. Treat that as a trusted-network service unless you add your own perimeter controls. +- Keep camera credentials and API tokens in `.env`; do not commit them to YAML. +- HomeSec binds to `0.0.0.0:8081` by default so Docker and LAN access work. Treat it like a trusted-network service unless you add your own perimeter controls. - API-key auth is available with: ```yaml @@ -198,8 +202,8 @@ See [`config/example.yaml`](config/example.yaml) for the full reference example api_key_env: HOMESEC_API_KEY ``` -- VLM analysis sends selected frames to the configured OpenAI-compatible endpoint only when `vlm.run_mode` and `trigger_classes` allow it. -- Push-to-talk microphone audio is streamed for the active talk session and is not intentionally persisted; camera compatibility still varies by model/firmware. +- VLM analysis only sends selected frames to the configured OpenAI-compatible endpoint when `vlm.run_mode` and `trigger_classes` allow it. +- Push-to-talk microphone audio is streamed for the active talk session and is not intentionally persisted. Camera compatibility still varies by model and firmware. ## Built-in integrations @@ -214,7 +218,7 @@ See [`config/example.yaml`](config/example.yaml) for the full reference example ## Extending HomeSec -HomeSec is built around strict interfaces and runtime plugin discovery. Each major capability is replaceable: +HomeSec is meant to be changed. The core pipeline talks to interfaces, and plugins provide the concrete behavior: - `ClipSource` for new camera/event sources - `ObjectFilter` for different detectors @@ -223,7 +227,7 @@ HomeSec is built around strict interfaces and runtime plugin discovery. Each maj - `AlertPolicy` for custom notification rules - `Notifier` for chat, paging, automations, or smart-home integrations -See [`PLUGIN_DEVELOPMENT.md`](PLUGIN_DEVELOPMENT.md) for the complete plugin guide. +See [`PLUGIN_DEVELOPMENT.md`](PLUGIN_DEVELOPMENT.md) for the full plugin guide. ## CLI reference @@ -258,7 +262,7 @@ make check The UI uses Vite + React + TypeScript and lives under [`ui/`](ui/). API client types are generated from the FastAPI OpenAPI contract. -For architecture notes, see [`DESIGN.md`](DESIGN.md). Some sections are intentionally deeper than the README and may describe historical design context. +For architecture notes, see [`DESIGN.md`](DESIGN.md). It goes deeper than the README and includes some historical design context. ## Contributing @@ -266,8 +270,8 @@ Contributions are welcome, especially around camera compatibility, storage/notif 1. Fork and clone the repository. 2. Create a focused branch. -3. Run the relevant tests/checks. -4. Open a pull request with the behavior change, validation, and any compatibility notes. +3. Run the relevant checks. +4. Open a pull request with what changed, how you tested it, and any compatibility notes. Found a bug or have a feature request? Please [open an issue](https://github.com/lan17/homesec/issues) with reproduction steps, environment details, and relevant logs. From fed80052d0e2f72c20541aae671beab4a4641727 Mon Sep 17 00:00:00 2001 From: Lev Neiman Date: Tue, 19 May 2026 21:04:31 +0000 Subject: [PATCH 3/3] Simplify local getting started --- Makefile | 23 +++++++++++++++++++++- README.md | 48 ++++++++++++++++------------------------------ config/local.yaml | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 32 deletions(-) create mode 100644 config/local.yaml diff --git a/Makefile b/Makefile index 2bf15aa6..6179c38a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ SHELL := /bin/bash .SHELLFLAGS := -eu -o pipefail -c -.PHONY: help up down docker-build docker-push run db test coverage typecheck lint lock-check check db-migrate db-migration publish ui-% fake-camera +.PHONY: help up down docker-build docker-push local local-setup run db test coverage typecheck lint lock-check check db-migrate db-migration publish ui-% fake-camera help: @echo "Targets:" @@ -13,6 +13,8 @@ help: @echo " make docker-push Push to DockerHub" @echo "" @echo " Local dev:" + @echo " make local Set up local config, build UI, start Postgres, and run HomeSec" + @echo " make local-setup Copy starter config and create local data directories" @echo " make run Run HomeSec locally (requires Postgres)" @echo " make db Start just Postgres" @echo " make test Run tests with coverage" @@ -62,6 +64,25 @@ docker-push: docker-build docker push $(DOCKERHUB_USER)/$(DOCKER_IMAGE):latest # Local dev +local: local-setup db ui-install ui-build run + +local-setup: + @mkdir -p config recordings/inbox storage backups/postgres + @if [ ! -f .env ]; then \ + cp .env.example .env; \ + echo "Created .env from .env.example"; \ + else \ + echo ".env already exists; leaving it unchanged"; \ + fi + @if [ ! -f "$(HOMESEC_CONFIG)" ]; then \ + cp config/local.yaml "$(HOMESEC_CONFIG)"; \ + chmod 600 "$(HOMESEC_CONFIG)"; \ + echo "Created $(HOMESEC_CONFIG) from config/local.yaml"; \ + else \ + echo "$(HOMESEC_CONFIG) already exists; leaving it unchanged"; \ + fi + @echo "Local setup ready. Add clips to recordings/inbox or edit $(HOMESEC_CONFIG) for real cameras." + run: @echo "Running database migrations..." @$(UV_RUN) alembic -c alembic.ini upgrade head diff --git a/README.md b/README.md index 7308fb97..2fdf559c 100644 --- a/README.md +++ b/README.md @@ -34,22 +34,14 @@ Footage is written locally first. Cloud storage, vision-model calls, MQTT, and e | Day-to-day ops | Setup wizard, config validation, runtime reloads, health checks, stats, and Postgres backups | | Camera extras | ONVIF setup/probing and push-to-talk paths for compatible RTSP/Tapo cameras | -## Quickstart: Docker Compose +## Quickstart: local Makefile -Docker Compose is the simplest way to try HomeSec. It runs HomeSec, the web UI, and Postgres together. +The quickest path is local-only: local folder ingest, local clip storage, no notifications, and VLM analysis disabled until you add an API key. ```bash git clone https://github.com/lan17/homesec.git cd homesec - -cp .env.example .env -cp config/example.yaml config/config.yaml - -# Edit at least one camera URL and any provider secrets. -$EDITOR .env -$EDITOR config/config.yaml - -docker compose up -d --build +make local ``` Then open: @@ -58,33 +50,27 @@ Then open: http://localhost:8081 ``` -Useful follow-up commands: - -```bash -docker compose logs -f homesec -docker compose down -``` +`make local` does the boring setup for you: -The example config is intentionally broad: it shows RTSP, FTP, local folders, Dropbox, MQTT, SendGrid, YOLO, OpenAI-compatible VLMs, live preview, and backups. Start by disabling what you do not need. You can run HomeSec with no notifiers if you only want analysis and event history. +- copies `.env.example` to `.env` if needed +- copies `config/local.yaml` to `config/config.yaml` if needed +- creates `recordings/inbox`, `storage`, and backup directories +- starts Postgres with Docker Compose +- installs/builds the React UI +- runs HomeSec with `config/config.yaml` -## Quickstart: Python package +Drop a video file into `recordings/inbox` to exercise the pipeline, or edit `config/config.yaml` when you are ready to point HomeSec at a real RTSP/FTP camera. -The Docker image is the best path if you want the bundled web UI right away, because it already includes the built React assets. A direct package install is useful when you are building your own deployment, running from source, or controlling `server.ui_dist_dir` yourself. +Useful follow-up commands: ```bash -pip install homesec -curl -O https://raw.githubusercontent.com/lan17/homesec/main/config/example.yaml -curl -O https://raw.githubusercontent.com/lan17/homesec/main/.env.example -mkdir -p config -mv example.yaml config/config.yaml -mv .env.example .env - -# Set DB_DSN, camera URLs, and provider secrets in .env. -homesec validate --config config/config.yaml -homesec run --config config/config.yaml +make local-setup # create/update the local starter files without running +make db # start only Postgres +make run # run HomeSec against config/config.yaml +make down # stop Docker Compose services ``` -If you run from a source checkout and want the web UI, build it first with `make ui-install && make ui-build`, or point `server.ui_dist_dir` at an existing UI build. If the config file is missing, `homesec run` starts in bootstrap mode so you can use the setup wizard. +For a fuller deployment-style example, see [`config/example.yaml`](config/example.yaml). It shows RTSP, FTP, Dropbox, MQTT, SendGrid, OpenAI-compatible VLMs, live preview, push-to-talk, and backups. ## Web UI diff --git a/config/local.yaml b/config/local.yaml new file mode 100644 index 00000000..0ca26f23 --- /dev/null +++ b/config/local.yaml @@ -0,0 +1,49 @@ +# Local-only starter config for HomeSec. +# Copy with: make local-setup + +version: 1 + +cameras: + - name: local_folder + source: + backend: local_folder + config: + watch_dir: ./recordings/inbox + poll_interval: 1.0 + stability_threshold_s: 1.0 + +storage: + backend: local + config: + root: ./storage + +state_store: + dsn_env: DB_DSN + +# Start quiet: keep notifications off until you choose MQTT/email/etc. +notifiers: [] + +filter: + backend: yolo + config: + classes: [person, car, dog, cat] + min_confidence: 0.5 + +# Local getting-started should not require an OpenAI key. +# Switch run_mode to trigger_only and set OPENAI_API_KEY when you want VLM summaries. +vlm: + backend: openai + run_mode: never + trigger_classes: [person] + config: + api_key_env: OPENAI_API_KEY + model: gpt-4o + +alert_policy: + backend: default + enabled: true + config: + min_risk_level: high + +preview: + enabled: false