Path 1: Detection + Optional Push (no ES)
Use ZoneMinder’s EventStartCommand to run ML detection directly — no Event Server needed.
Requires ZM 1.38.1 or above.
Push notifications are supported directly from zm_detect — no ES required.
Configure the push section in objectconfig.yml (see push_config).
Requires ZM 1.39.2+ (which adds the Notifications REST API for token storage).
If you also want WebSocket notifications, MQTT, notification rules/muting, or the ES control interface, see Path 2: Full Event Server.
Important
The installer now creates a shared Python virtual environment at
/opt/zoneminder/venv instead of installing globally with
pip install --break-system-packages.
Why the change:
Modern Linux distributions (Debian 12+, Ubuntu 23.04+, Fedora 38+) mark the system Python as externally managed (PEP 668) and actively block global pip installs.
--break-system-packagesbypasses that protection but can break OS tools that depend on the system Python.Multiple ZoneMinder components (pyzmNg, hook helpers) need to share a single Python environment — a dedicated venv gives them isolation from the OS while still sharing packages with each other.
Step 1: Run the installer
Important
Prerequisites
The installer needs pip3 and — on Debian/Ubuntu — the python3-venv
package to build the shared virtual environment. Install them before
running install.sh:
Debian/Ubuntu:
sudo apt install python3-pip python3-venvFedora/RHEL:
sudo dnf install python3-pipopenSUSE:
sudo zypper install python3-pipArch:
sudo pacman -S python-pip
Without python3-venv, python3 -m venv still creates the directory but
never bootstraps pip into it — you’ll end up with python/python3 in
/opt/zoneminder/venv/bin but no pip, and Step 2 will fail. If that
already happened, install the package above and run
sudo /opt/zoneminder/venv/bin/python -m ensurepip --upgrade (or delete the
venv and re-run the installer).
git clone https://github.com/ZoneMinder/zmeventnotificationNg
cd zmeventnotificationNg
sudo -H ./install.sh # say No to ES, Yes to hooks, Yes to hook config
Or, to run non-interactively:
sudo -H ./install.sh --no-install-es --install-hook --install-hook-config --no-interactive
This handles everything:
Creates a Python virtual environment at
/opt/zoneminder/venv(customizable with--venv-path).Installs pyzmNg and the hook helpers into the venv.
Downloads ML models (YOLOv4, YOLOv11, YOLOv26 by default).
Installs hook scripts, creates the directory structure, and installs config files.
Both pyzmNg and the hook helpers live in the venv, keeping your system Python clean.
Note
The installer pulls in core pyzmNg automatically. If you need additional pyzmNg extras (remote ML server, training UI, etc.) or want to install a local development version of pyzmNg, see the pyzmNg installation guide.
To use a custom venv path:
sudo -H ./install.sh --venv-path /usr/local/zm/venv
Model flags — to control which models are downloaded, pass environment variables:
# Example: only YOLOv26, skip YOLOv4
sudo -H INSTALL_YOLOV4=no INSTALL_TINYYOLOV4=no ./install.sh
Available flags (default in parentheses): INSTALL_YOLOV11 (yes), INSTALL_YOLOV26 (yes),
INSTALL_YOLOV4 (yes), INSTALL_TINYYOLOV4 (yes), INSTALL_YOLOV3 (no),
INSTALL_TINYYOLOV3 (no), INSTALL_CORAL_EDGETPU (no), INSTALL_BIRDNET (no).
You can also use the CLI flag --install-birdnet to install BirdNET audio detection.
Step 2: OpenCV
The install script does not install OpenCV for you, because you may want GPU support or a specific version.
Important
ONNX models (YOLOv11, YOLOv26) require OpenCV 4.13+.
Quick install (no GPU):
/opt/zoneminder/venv/bin/pip install opencv-contrib-python
For GPU support, compile from source with CUDA enabled. See the official OpenCV build guide. Here is an example gist with instructions for compiling OpenCV from source on Ubuntu 24 that worked for me (not authoritative — adapt as needed for your setup).
The venv is created with --system-site-packages, so a system-wide OpenCV
built from source is automatically visible inside the venv.
Note
If you already had OpenCV installed (from source or a system package)
before running the installer, the install script registers an
opencv-python compatibility shim so that pip does not overwrite your
build. This is specifically needed because pyzm[train] depends on
ultralytics, which unconditionally pulls opencv-python from PyPI
and will overwrite custom OpenCV builds (e.g. CUDA or Metal-accelerated).
If your OpenCV is nevertheless replaced, you can restore it:
/opt/zoneminder/venv/bin/pip uninstall opencv-python opencv-python-headless
# Rebuild / reinstall your custom OpenCV
Verify it works:
/opt/zoneminder/venv/bin/python -c "import cv2; print(cv2.__version__)"
Step 3: Configure
Edit /etc/zm/objectconfig.yml — at minimum, fill in the general section with your
ZM portal URL, username, and password (or point them to secrets.yml).
Note
If you also want to run the remote ML detection server (pyzm.serve)
on this same machine, install the serve extra:
/opt/zoneminder/venv/bin/pip install "pyzm[serve]".
See Using the remote ML detection server (pyzm.serve) for details.
Step 4: Wire up ZoneMinder
For each monitor, go to Config -> Recording and set:
Event Start Command:
/var/lib/zmeventnotification/bin/zm_detect.py -e %EID% -m %MID% -r "%EC%" -n --pyzm-debug
-c defaults to /etc/zm/objectconfig.yml; pass it explicitly only if your config is elsewhere.
Step 5: Test manually
First, verify you have the right versions installed:
sudo -u www-data /var/lib/zmeventnotification/bin/zm_detect.py --version
You should see app:7.0.0 (or above) and pyzm:2.0.0 (or above). If either version is lower, update the corresponding package before continuing.
Then test detection (--config defaults to /etc/zm/objectconfig.yml):
# Test with a real ZM event
sudo -u www-data /var/lib/zmeventnotification/bin/zm_detect.py \
--eventid <eid> --monitorid <mid> --debug
# Or test with a local image (no ZM event needed)
wget https://upload.wikimedia.org/wikipedia/commons/c/c4/Anna%27s_hummingbird.jpg -O /tmp/bird.jpg
sudo -u www-data /var/lib/zmeventnotification/bin/zm_detect.py \
--file /tmp/bird.jpg --debug
Testing push notifications (Path 1 direct push):
If you have push.enabled: "yes" in objectconfig.yml and devices have registered
tokens via the ZM Notifications API, you can test push delivery from the command line.
Use --file with --eventid and --monitorid to trigger push without a live event.
The --fakeit flag overrides detection results so you don’t need an image that actually
matches your detection pattern:
sudo -u www-data /var/lib/zmeventnotification/bin/zm_detect.py \
--file /path/to/any/image.jpg --eventid <eid> --monitorid <mid> \
--debug --fakeit "person"
Replace <eid> with a real event ID (so the notification links to a viewable event)
and <mid> with the monitor ID. Registered devices should receive a push notification
within a few seconds. Check the debug output for push: log lines to verify delivery.
See push_config for push configuration details.
Optional: Face recognition
Only needed if you want to recognize who a face belongs to (not just detect faces). Takes a while and installs a lot of dependencies, which is why it is not included automatically.
Note
If you use Google Coral, you can do face detection (not recognition) via the Coral libraries and can skip this section.
sudo apt-get install libopenblas-dev liblapack-dev libblas-dev # not mandatory, but gives a good speed boost
/opt/zoneminder/venv/bin/pip install face_recognition # installs dlib automatically
If you installed face_recognition earlier without the BLAS libraries,
reinstall both dlib and face_recognition so dlib is built with OpenBLAS
support:
/opt/zoneminder/venv/bin/pip uninstall dlib face-recognition
sudo apt-get install libopenblas-dev liblapack-dev libblas-dev # the important part
/opt/zoneminder/venv/bin/pip install dlib --verbose --no-cache-dir # make sure it finds openblas
/opt/zoneminder/venv/bin/pip install face_recognition
Optional: Google Coral EdgeTPU
Follow the Coral setup guide first, then run the installer with:
sudo -H INSTALL_CORAL_EDGETPU=yes ./install.sh
Make sure the web user has device access: sudo usermod -a -G plugdev www-data (reboot required).
Warning
Google’s official pycoral packages only support Python 3.9 and below. If you are
running Python 3.10+, see pycoral#149
for community workarounds.
Post-install diagnostics
After installation, run the diagnostic tool to check your environment:
sudo -u www-data python3 tools/install_doctor.py \
--hook-config /etc/zm/objectconfig.yml \
--es-config /etc/zm/zmeventnotification.yml \
--web-owner www-data --web-group www-data \
--base-data /var/lib/zmeventnotification
(Run from the zmeventnotificationNg source directory.)
This checks GPU/CUDA availability, OpenCV version, model file paths, file permissions,
SSL certificates, MQTT/FCM Perl dependencies, and Python package versions. Fix any
issues it reports before proceeding. Note that install.sh runs this automatically
at the end of installation.
Troubleshooting
If something isn’t working, see Machine Learning Hooks FAQ for debugging steps and common issues.