Universal self-hosted camera and surveillance platform
Turn USB cameras, computers, phones and IP cameras into one unified surveillance system. No cloud. No account. No subscription. Your footage never leaves your network.
VISIONMESH SERVER
Windows or Linux machine
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
WINDOWS AGENT LINUX AGENT IP CAMERAS
USB / built-in USB / built-in RTSP · ONVIF
│ │ │
└─────────────────────┼─────────────────────┘
│
▼
STREAM GATEWAY
│
┌─────────┴─────────┐
▼ ▼
WEB BROWSER PHONE
any device camera or viewer
│ │
└─────────┬─────────┘
│
▼
HOME ASSISTANT
cameras · sensors · automations
Install the server on one machine. Open the dashboard. Press Add camera. That is the whole product; everything else exists to support that.
Cameras from anywhere
- USB and built-in webcams, on the server or on any other computer running the agent
- Phones and tablets, with nothing to install — scan a code and the browser becomes the camera
- RTSP cameras, added by address
- ONVIF cameras, found automatically on the network
Built for people who are not surveillance engineers
- A five-step first-run wizard with working defaults
- Every advanced setting has a plain-language explanation behind a "What is this?" link
- A Fix camera button that checks the whole chain and says what is actually wrong
- A built-in help centre, written for a non-technical reader first
Real engineering underneath
- Cameras that produce MJPEG have their frames forwarded without being decoded or re-encoded
- Network cameras recording continuously are written with the stream copied, not transcoded, from the same connection that serves the live view
- Demand-driven capture: a camera nobody is watching and nothing is recording costs nothing
- Motion detection runs on 1/8-scale luma recovered from each JPEG without fully decoding it
Private by design
- No cloud, no telemetry, nothing phones home
- Privacy mode genuinely stops capture and recording, and says so to anyone who opens the camera
- Passwords hashed with PBKDF2, camera credentials encrypted at rest, device tokens stored hashed
- Pairing codes are single-use and expire in minutes
Home Assistant
- A proper custom integration: camera entities with live video, not copied RTSP URLs
- Online, motion and recording binary sensors; frame rate, bitrate, latency and storage sensors
- Privacy and recording switches, PTZ buttons on cameras that support them
- Optional MQTT discovery for state — video deliberately does not travel over MQTT
This is an honest account of what has been built and how far it has been verified. Nothing below is aspirational.
| Component | State | Verified how |
|---|---|---|
| Server (Windows, Linux) | Working | Runs, 84 automated tests, driven through a browser |
| Web dashboard | Working | Every page exercised in a real browser |
| Pairing, devices, camera CRUD | Working | End-to-end tests pair a device and add its camera |
| Live streaming (MJPEG) | Working | End-to-end tests read real frames off the stream endpoint |
| Windows agent — discovery and capture | Working | Ran against a real Logitech BRIO: 720p15 MJPEG forwarded without re-encoding |
| Privacy mode | Working | Verified on real hardware: camera released within a second, stream and snapshot refused |
| Linux agent | Working | Captured 300 frames from a real V4L2 device in CI, decoded back to 1280x720 |
| Browser camera — pairing and protocol | Working | A browser paired and connected as a real agent, advertising its camera |
| Browser camera — capture | Working | Chromium with a synthetic camera in CI: 199 frames reached the server, decoded back to 1280x720. Not yet run on a real phone |
| RTSP cameras | Working | Pulled a live RTSP H.264 stream: transcoded for viewing, stream-copied for recording |
| ONVIF discovery and PTZ | Built, not run against a real camera | ONVIF client is hand-written SOAP |
| Recording and playback | Working | The published 1.0.1 build recorded a webcam, was hard-killed mid-write, and the segment still decoded 947 frames |
| Motion detection | Working | Fired on a live camera and started a recording; decoder tested against real encoder output |
| Home Assistant integration | Working | Loaded into Home Assistant 2026.2.3 in CI: 40 tests over the config flow and entities, plus hassfest |
| MQTT discovery | Working | Against mosquitto in CI: 8 discovery entities, state, a command from outside, and the last will after a SIGKILL |
Deliberately not built yet
- WebRTC. Live viewing uses MJPEG over HTTP. It works in every browser and webview with no plugin, no signalling and no transcoding of already-JPEG sources. It costs more bandwidth than H.264 and carries no audio. WebRTC is the right long-term answer and is not implemented; the streaming layer is separated from the dashboard so it can be added behind the same API.
- Native Android and iOS apps. The browser camera covers the same ground today with nothing to install. The agent protocol is documented, so a native app is additive rather than a rewrite.
- Floor plans and drag-and-drop camera groups. Groups work; the visual editors do not exist.
wget https://raw.githubusercontent.com/unupunct/VISIONMESH/main/install.shRead it before you run it — you should read any script that asks for root.
chmod +x install.sh
sudo ./install.shThen open the address it prints, and follow the setup wizard.
Download the current release from Releases,
unzip it, and run VisionMesh.Server.exe. Open http://localhost:8088.
To run it in the background:
sc.exe create VisionMesh binPath= "C:\VisionMesh\VisionMesh.Server.exe" start= auto
sc.exe start VisionMeshgit clone https://github.com/unupunct/VISIONMESH.git
cd VISIONMESH
dotnet test
dotnet run --project server/VisionMesh.ServerA phone — Devices → Add device → point the phone's camera at the code → Start camera. Nothing to install.
A webcam on another computer — install the agent on that machine, then:
VisionMesh.Agent pair # asks for the server address and the pairing code
VisionMesh.Agent # run itA network camera — Add camera → IP camera. VisionMesh asks every camera on the network to identify itself, and lists the ones that answer.
VisionMesh needs ffmpeg for RTSP and ONVIF cameras, and for recording. USB cameras and phone cameras work without it.
sudo apt install ffmpeg # Debian, Ubuntu, Raspberry Pi OS
sudo dnf install ffmpeg # FedoraOn Windows, download a build and either put it on PATH or drop ffmpeg.exe next to
VisionMesh.Server.exe.
It is not bundled: its licensing and per-distribution builds make shipping it inside an installer a legal and packaging problem. When it is missing, the features that need it are switched off and labelled, rather than failing the moment somebody presses a button.
Do not forward a port to this server. Cameras exposed that way are found and probed within hours, and are one of the most common sources of leaked home footage.
Use a private network instead. With Tailscale or WireGuard, your phone joins the same private network and reaches VisionMesh exactly as it does at home, with nothing exposed to the internet. See docs/11-tailscale.md.
Copy homeassistant/custom_components/visionmesh into your Home Assistant
config/custom_components folder, restart, then add the VisionMesh integration and sign in with a
VisionMesh account.
Your cameras appear as camera entities with live video, plus sensors and switches for automations:
automation:
- alias: "Porch light on motion"
trigger:
platform: state
entity_id: binary_sensor.front_door_motion
to: "on"
action:
- service: light.turn_on
target: { entity_id: light.porch }
- service: notify.mobile_app
data:
message: "Movement at the front door"Full guide: docs/10-home-assistant.md.
The API is also documented live at /api/docs on a running server.
| Platform | Server | Camera agent | Viewer |
|---|---|---|---|
| Windows 10/11 | Supported | Supported | Any browser |
| Linux x64 | Supported | Supported | Any browser |
| Linux arm64 | Supported | Supported | Any browser |
| Android | — | Browser camera | Any browser |
| iOS / iPadOS | — | Browser camera | Any browser |
| RTSP cameras | Source | — | — |
| ONVIF cameras | Source, with PTZ | — | — |
"Browser camera" means a page that turns the device into a camera, with no app to install. It only runs while the page is open and the screen is on, because that is all a phone permits.
server/ The server: core, database, API, streaming, recording, Home Assistant
agents/ Windows and Linux camera agents, and the code they share
web/dashboard The dashboard and the browser camera. Plain HTML, CSS and ES modules; no build step
homeassistant Home Assistant custom integration
docs/ Guides, written for a non-technical reader first
scripts/ Build, verification and packaging scripts
tests/ Automated tests
See CONTRIBUTING.md. Bug reports that include what you expected, what happened, and the output of Fix camera are worth ten that do not.
See SECURITY.md for how to report a vulnerability, and docs/16-security.md for what VisionMesh does with your footage — and what it will never do.
MIT. See LICENSE.