Cross-platform ONVIF IP camera configuration tool. Same feature scope as
the upstream ONVIF Device Manager — network configuration, device info,
user management, PTZ, live video preview — delivered as both a CLI
(onvifcfg) and a local browser UI (onvifcfg serve → localhost:3003).
The rewrite ships every reliability and compatibility fix identified in
the prior review of the legacy ODM source.
Status: Phase 1 (discovery + network configuration) shipped. Phases 2–7 (device info, users, imaging, video encoder, live preview, PTZ, events, certificates) tracked in docs/ROADMAP.md.
This repository is a rewrite of the original ONVIF Device Manager (ODM), a 2013-era C# / F# / C++ WPF application available at:
https://svn.code.sf.net/p/onvifdm/code/trunk onvifdm-code
The earlier commit history of this repository contained a fork of that SVN source tree plus a long series of attempts to get it to build on modern Visual Studio 2022. The legacy tooling chain (MarkupCompilePass + .NET Framework 4.x ReflectionOnly loading of transitively-unsigned assemblies) ultimately proved unreliable on current Windows SDKs. Rather than continue that port, this repo has been reset to a Python rewrite that delivers the functionality we actually cared about — the network-settings apply workflow — with every reliability and compatibility fix we identified during the code review baked in from day one.
- WS-Discovery to find ONVIF cameras on the local network
- Read full network configuration from a camera
- Apply network configuration changes with:
- Pre-apply validation (port ranges, lockout prevention, subnet sanity, IP-in-subnet gateway check)
- Safe apply order — NTP, DNS, gateway, hostname, discovery-mode first; protocols and IP last to avoid breaking the session mid-apply
SetHostnameFromDHCPpreferred overSetHostname("")(ONVIF 2.x)- IPv6 DNS / NTP entries correctly routed to
iPv6Addressfields - Round-trip of existing
SearchDomainlist onSetDNS - Capability-advisory guards around optional features
(
GetZeroConfiguration,GetDiscoveryMode) - Only-changed protocols sent via
SetNetworkProtocols - Bounded 30-second timeout on
SystemRebootbest-effort call - Post-reboot TCP reachability probe on the new IP
- Confirmation + diff preview before destructive apply
See docs/RELIABILITY_FIXES.md for the full catalogue of issues fixed relative to upstream ODM's behaviour.
Tracked in full in docs/ROADMAP.md. The headline items:
- Live preview in the web UI (Phase 4) — server-side ffmpeg→HLS transcode, with an MJPEG-via-snapshot fallback for low-bandwidth clients.
- PTZ control (Phase 5) — continuous / relative / absolute moves plus presets and a virtual joystick on the device page.
- Events, analytics, metadata (Phase 6) — pull-point subscription loop and event-type filtering.
- Certificates + 802.1X + IP filter (Phase 7) — TLS material upload and allow/deny list editing.
- Vendor adapters (Phase 8) — Hikvision ISAPI, Dahua CGI,
Axis VAPIX as additive backends behind ONVIF. First win:
reliable snapshots on HIK firmwares where ONVIF + HTTP share a
single TCP port and
GetSnapshotUriis unreliable. - Cross-subnet discovery — unicast Probe sweep + ARP-OUI sniff +
temporary secondary-IP helper, so cameras shipped on the default
192.168.1.0/24are findable from any subnet. - Multi-NIC / IPv6 UI, auth-scheme fallback ladder, and WSDL refresh carried from the upstream review.
# development install
uv sync
uv run onvifcfg --helpPer-platform packaged installs:
- Linux (Debian/Ubuntu .deb) — switch to branch
linux, runbash packaging/deb/build-deb.shon a Linux host withuvandnfpm - Windows (MSI) — switch to branch
windows-msi, runpwsh packaging/msi/build-msi.ps1on a Windows host withuvand the WiX v4 toolset
Pre-built installers are attached to every GitHub release:
onvifcfg-<version>.msi— classic Windows Installer (WiX).onvifcfg-<version>-setup.exe— Inno Setup alternative.
Windows will likely flag the first launch with "Microsoft Defender SmartScreen prevented an unrecognized app from starting". The installer is not malicious — it is simply not code-signed.
I am not a Windows developer and do not intend to pay Microsoft (nor any reseller) for a code-signing certificate just to ship a free tool that configures ONVIF cameras on a local network. The signing-certificate ecosystem is a rent extraction mechanism I am not interested in feeding.
Workarounds, in order of convenience:
-
Elevated one-liner (recommended — downloads via .NET
WebClient, which does not tag the file with the Mark-of-the-Web flag SmartScreen checks, so it never triggers the prompt):irm https://raw.githubusercontent.com/andrewhack/odm/main/packaging/msi/install.ps1 | iex
-
Click through the warning — on the SmartScreen dialog click More info → Run anyway. Same binary, one extra click.
-
Unblock the file manually — right-click the downloaded
.msi/.exe→ Properties → check Unblock → OK.
If your environment mandates signed binaries, build the MSI yourself from
source (pwsh packaging/msi/build-msi.ps1 on the windows-msi
branch) and sign it with your own certificate.
# discover cameras on the local subnet
onvifcfg discover
# show current network config
onvifcfg show 192.168.1.100 --user admin --password secret
# apply a new IP (prompts for confirmation, shows diff)
onvifcfg apply 192.168.1.100 --user admin --password secret \
--ip 192.168.1.200 --subnet 255.255.255.0 --gateway 192.168.1.1
# change only the RTSP port
onvifcfg apply 192.168.1.100 -u admin -p secret --rtsp 8554onvifcfg serve # binds 127.0.0.1:3003 by default
# then open http://localhost:3003/ in any browserThe web UI exposes the same discover / read / apply flow with a click- through confirmation page. Do not expose it on a network — it reconfigures cameras and has no built-in access control.
src/onvifcfg/
cli.py # typer entrypoint
discovery.py # WS-Discovery scan
session.py # authenticated ONVIF session
network.py # read + apply network settings
validation.py # pre-apply guards
reachability.py # post-reboot TCP probe
models.py # pydantic models
tests/ # pytest suite
docs/ # design notes and fix catalogue
This repo uses a multi-branch packaging model: main holds the source,
and linux / windows-msi / windows-exe each carry one platform's
installer recipe. Do not merge the packaging branches into main
(GitHub will keep offering). See docs/BRANCHES.md
for the full explanation.
The upstream ODM codebase was BSD-licensed; this rewrite uses the same terms. See LICENSE.