Documentation
Everything you need to install, configure, and run DBFComp.
Overview
DBFComp is a self-hosted facial-recognition system for NVR security cameras. When a camera detects motion, the NVR pushes an event to DBFComp, which pulls the frame over RTSP, detects and recognizes the face against your enrolled database, and posts a Discord alert with an enhanced close-up.
The recognition pipeline is pluggable: a MODEL_TIER selects the model stack, and
everything runs through ONNX Runtime so it's GPU-accelerated on Apple Silicon (CoreML) and
Windows + NVIDIA (CUDA).
Requirements
- Python 3.10–3.12
- ffmpeg on your
PATH(or setFFMPEG_PATH) - An NVR with ONVIF/RTSP enabled and an Event Push target pointed at this host
- A Discord bot token + a server to invite it to
- Optional GPU: Apple Silicon (CoreML, automatic) or NVIDIA (CUDA toolkit + cuDNN)
Install
# clone, then create a virtualenv python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -U pip pip install -r requirements.txt
On Windows + NVIDIA, swap onnxruntime for onnxruntime-gpu
(with a matching CUDA toolkit + cuDNN) and leave ONNX_PROVIDERS blank to auto-select CUDA.
First-time setup
python face_watch.py setup # interactive wizard → writes .env python face_watch.py doctor # verify env, ffmpeg, models, DB, Discord
doctor tells you exactly what's missing for your active tier — handy when bringing
up a second machine.
Model tiers
Set MODEL_TIER to choose the recognition stack:
| Tier | Recognizer | Detector | Notes |
|---|---|---|---|
lite | EdgeFace-S | YuNet | Tiny/fast, CPU-friendly (no InsightFace) |
standard | glintr100 | det_10g | Proven default; age/gender |
max | AdaFace IR-101 | det_10g | Strongest; needs a GPU |
lite and max recognizers are exported to ONNX once (PyTorch is only
needed for that step — the runtime stays torch-free):
python3 -m venv .venv-export .venv-export/bin/pip install -r scripts/requirements-export.txt .venv-export/bin/python scripts/export_onnx.py all # → models/recog/*.onnx python face_watch.py fetch-models # YuNet / GFPGAN / MiniFASNet
Switching the recognizer changes the embedding space, so re-embed your enrolled faces:
# set MODEL_TIER (or RECOG_MODEL) in .env, then:
python face_watch.py rebuild-db
GFPGAN restoration (RESTORE, on by default for standard/max) cleans up
the alert close-up into a sharp, aligned face.
Configuration
All settings live in .env (generated by setup). Highlights:
| Key | Meaning |
|---|---|
MODEL_TIER | lite / standard / max |
ALERT_MODE | unknown_only / known_and_unknown / all |
SIMILARITY_THRESHOLD | Cosine match threshold (glintr100; default 0.4) |
RECOG_THRESHOLD | Override threshold for EdgeFace/AdaFace |
RESTORE | GFPGAN restoration on/off |
LIVENESS | MiniFASNet anti-spoof annotation (experimental, off) |
ONNX_PROVIDERS | Blank = auto (CoreML on Mac, CUDA on Windows) |
FFMPEG_PATH | Blank = resolve from PATH |
DISCORD_* | Bot token, guild id, alert channels / users |
Discord setup
- Create a bot at the Developer Portal and copy its token.
- Invite it to your server with the
bot+applications.commandsscopes (a guild install — user-installs can't send alerts). - Enable Developer Mode in Discord, then copy your channel and user ids.
- Put them in
.env:DISCORD_BOT_TOKEN,DISCORD_GUILD_ID,DISCORD_ALERT_CHANNEL_IDS,DISCORD_ALERT_USER_IDS.
Slash commands (guild-synced on startup):
/review | Dashboard: today's faces + action buttons |
/people · /pending | List enrolled people / faces awaiting a name |
/enroll name <photo> | Enroll a person from an attached photo |
/name · /ignore | Name or skip a reviewed face |
/rename · /remove | Edit the database |
/rebuild_db · /test · /help | Re-embed after a tier switch · system check · help |
When a stranger recurs, DBFComp DMs you a montage with Name / Ignore buttons.
CLI commands
python face_watch.py setup # write .env python face_watch.py doctor # health check python face_watch.py fetch-models # download models for the active tier python face_watch.py list # enrolled people python face_watch.py watch # run the watcher (main loop) python face_watch.py rebuild-db # re-embed data/people/ into the active model
Plus enroll, remove, import, cluster,
label, folders, split, review, and
capture for managing the recognition database.
Enrolling people
python face_watch.py enroll --name "Dad" --photos ./photos/dad/ python face_watch.py enroll --name "Mom" --photo ./photos/mom.jpg python face_watch.py list
Or enroll straight from Discord with /enroll and a photo attachment. The watcher
hot-reloads the database, so new enrollments take effect without a restart.
Run as a service
macOS (launchd): copy com.facewatch.plist into
~/Library/LaunchAgents/ and load it:
cp com.facewatch.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/com.facewatch.plist
launchctl kickstart -k "gui/$(id -u)/com.facewatch" # restart after changes
Windows: run it on login with NSSM (a real service that restarts on crash) or Task Scheduler:
nssm install dbfcomp "C:\path\.venv\Scripts\python.exe" "C:\path\face_watch.py" watch nssm set dbfcomp AppDirectory "C:\path" nssm start dbfcomp
Troubleshooting
Start with doctor — it reports the active tier and flags anything missing
(model files, an empty DB after a tier switch, ffmpeg, providers, Discord config):
python face_watch.py doctor
- Slash commands don't respond → the watcher (and therefore the bot) isn't running. Start
watch. - Recognition broke after switching tiers → run
rebuild-db(each recognizer has its own embedding space). - No alert image / RTSP errors → check
FFMPEG_PATHand that ONVIF/RTSP is enabled on the NVR.
DBFComp · Database Facial Comparison — github.com/LAOUUUUU/face-watch