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-packages bypasses 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-venv

  • Fedora/RHEL: sudo dnf install python3-pip

  • openSUSE: sudo zypper install python3-pip

  • Arch: 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.