Skip to content

Instantly share code, notes, and snippets.

@pliablepixels
Last active July 26, 2026 12:04
Show Gist options
  • Select an option

  • Save pliablepixels/7300734ac94e95356632ecfcbc8c1707 to your computer and use it in GitHub Desktop.

Select an option

Save pliablepixels/7300734ac94e95356632ecfcbc8c1707 to your computer and use it in GitHub Desktop.
pyzm remote

1. Install

a) Same box (ZM and gateway together) One install, with the serve extra:

sudo /opt/zoneminder/venv/bin/pip install --force-reinstall --no-deps \
  "pyzm[serve] @ git+https://github.com/ZoneMinder/pyzmNg.git@master"

b) Separate boxes ZM box — client only, no extra:

sudo /opt/zoneminder/venv/bin/pip install --force-reinstall --no-deps \
  "pyzm @ git+https://github.com/ZoneMinder/pyzmNg.git@master"

Gateway box — needs the serve extra. Use whatever env runs the server; if it's a fresh box:

python3 -m venv ~/pyzm-serve
~/pyzm-serve/bin/pip install "pyzm[serve] @ git+https://github.com/ZoneMinder/pyzmNg.git@master"

Substitute ~/pyzm-serve/bin/python for /opt/zoneminder/venv/bin/python everywhere below on that box.

Verify on each box:

/opt/zoneminder/venv/bin/python -c "import pyzm;print(pyzm.__version__)"    # 2.5.0

Gateway only:

grep -c '"/infer"' /opt/zoneminder/venv/lib/python3.12/site-packages/pyzm/serve/app.py   # 1

2. Run the gateway Model files must be on this box, under /var/lib/zmeventnotification/models or --base-path. Publish each model under the name your objectconfig.yml uses — that's what the client asks for:

/opt/zoneminder/venv/bin/python -m pyzm.serve \
  --models "YOLOv11 ONNX=yolo11s" --host 0.0.0.0 --port 5000 --debug

Or from a file:

# /etc/zm/pyzm-serve.yml
host: "0.0.0.0"
port: 5000
base_path: "/var/lib/zmeventnotification/models"
processor: cpu
models:
  - "YOLOv11 ONNX=yolo11s"
/opt/zoneminder/venv/bin/python -m pyzm.serve --config /etc/zm/pyzm-serve.yml --debug

Check it, from the ZM box (localhost if same box):

curl -s http://<gateway>:5000/health
curl -s http://<gateway>:5000/models | python3 -m json.tool
curl -s http://<gateway>:5000/openapi.json | python3 -c "import sys,json;print(list(json.load(sys.stdin)['paths']))"

/models must list the exact names your config uses. Paths must include /infer.

3. Configure the client

objectconfig.yml on the ZM box:

remote:
  ml_gateway: "http://<gateway-ip>:5000"
  ml_gateway_mode: "url"
  ml_fallback_local: "no"
  ml_timeout: 60

ml_fallback_local: "no" for testing only — a gateway problem then fails loudly instead of quietly running local. Restore "yes" after. url mode has the gateway pull frames from ZM, so check from the gateway box:

4. Test

sudo -u www-data /var/lib/zmeventnotification/bin/zm_detect.py \
  --config /etc/zm/objectconfig.yml --eventid <EID> --monitorid <MID> --debug

See logs on both sides (enable debug logs)

Then set ml_fallback_local: "yes" back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment