Skip to content

brainframe-onvif-tools

brainframe-onvif-tools finds IP cameras and network video recorders (NVRs) on your local network, retrieves their details through the ONVIF protocol, and checks that their RTSP video streams can be opened. The result is a config.csv inventory file that brainframe-apps can use to add all of the cameras to BrainFrame in one step.

It is designed for bulk setup on Linux. For adding a single camera by hand, see Connecting to IP Cameras.

Installation

pip install brainframe-onvif-tools

Requirements

  • Python 3.9 or newer (tested on Python 3.10).
  • ffprobe, which is part of FFmpeg, for the validate command. On Ubuntu, install it with sudo apt install ffmpeg.
  • The machine must be on the same network as the cameras.

Commands

Command Purpose
discover Find ONVIF devices on the network and write their addresses to config.csv.
scan Log in to each discovered device and read its manufacturer, model, serial number, and stream details.
validate Confirm that each RTSP stream opens, fill in the RTSP URL and credentials, and take a snapshot.
fix Apply per-model stream pipeline patches to config.csv.
update-ip Update camera IP addresses in a BrainFrame settings file after the cameras' addresses change.

All commands are run as brainframe-onvif-tools <command> [options]. To see the options of a command, run brainframe-onvif-tools <command> --help.

Typical Workflow

# 1. Find the cameras on the network
brainframe-onvif-tools discover --auto

# 2. Log in to each camera and read its details
brainframe-onvif-tools scan

# 3. Verify the RTSP streams and take snapshots
brainframe-onvif-tools validate

# 4. Add the cameras to BrainFrame
brainframe-apps add-stream --stream-urls config.csv

Run the commands from the same directory every time. They read and write config.csv, camera_onvif_info.json, and credentials.txt in the current directory by default. To use a different directory, set the APP_HOME environment variable.

discover

Finds ONVIF-capable devices and writes their addresses to config.csv.

brainframe-onvif-tools discover

When run without options, the command shows a menu of discovery methods and the network interfaces it found. Choose one or more, separated by commas. Press Enter to accept the default, WS-Discovery.

To run without prompts, use --auto. This runs WS-Discovery, SADP discovery for Hikvision cameras, and a scan of every local subnet:

brainframe-onvif-tools discover --auto

To also scan a specific subnet, for example one that is not directly attached to this machine:

brainframe-onvif-tools discover --subnet 192.168.20.0/24 --subnet 192.168.30.0/24
Option Description
--auto Run WS-Discovery, SADP discovery, and scan all local subnets, with no prompts.
--subnet CIDR Also scan this subnet, for example 192.168.1.0/24. Can be given more than once.
--output OUTPUT The file to write. Default: config.csv.

If config.csv already exists, it is renamed to config.csv.old before the new file is written. Any earlier config.csv.old is replaced. Keep a copy of the file if you need to retain more than one previous version.

You can edit config.csv after this step to remove devices that you do not want to scan or add to BrainFrame.

scan

Contacts each device in config.csv over ONVIF, trying the device's ports and a short list of credentials, and records what it finds.

brainframe-onvif-tools scan

For each device, the command tries the following, in order:

  1. The credentials listed in credentials.txt, one username,password pair per line.
  2. Anonymous access.

On first use, the command creates a credentials.txt file in the current directory. Edit it to list the credentials that your cameras use.

Warning

Keep credentials.txt short, with at most three entries. The scanner tries each entry in turn, and some cameras lock out an address after several failed logins.

If all of your cameras use the same login, you can supply it on the command line instead. In that case, only this login is tried:

brainframe-onvif-tools scan --user admin --password PASSWORD

To check a single camera and print everything the camera reports as JSON, without reading or changing config.csv:

brainframe-onvif-tools scan --host 192.168.1.10 --user admin --password PASSWORD
Option Description
--host HOST Scan one device, for example 192.168.1.10, and print the result. Does not use config.csv.
--user USER Use only this username, instead of the entries in credentials.txt.
--password PASSWORD The password for --user. Required when --user is given.
--input INPUT The device list to read and update. Default: config.csv.
--output OUTPUT The file to save detailed ONVIF information to. Default: camera_onvif_info.json.
--sort-by-serial-number Sort the results by serial number instead of IP address.
--debug Print detailed error messages.

The command updates each device's row in config.csv with its credentials, manufacturer, model, serial number, audio capabilities, video encoding settings, system time, and on-screen display (OSD) text. It also saves the full details of every device to camera_onvif_info.json.

validate

Confirms that each camera's RTSP streams can be opened, records the working RTSP URL in config.csv, and saves a snapshot of each camera.

brainframe-onvif-tools validate

validate reads camera_onvif_info.json, so run scan first. It uses the credentials found by scan. To use a different login for all cameras, use --user and --password.

Option Description
--input INPUT The config.csv file to update. Default: config.csv.
--json_file JSON_FILE The ONVIF inventory file to read and update. Default: camera_onvif_info.json.
--snapshot-dir SNAPSHOT_DIR The directory for snapshots. Default: snapshots.
--skip-snapshots Do not take snapshots.
--user USER Use this username instead of the credentials found by scan.
--password PASSWORD The password for --user. Required when --user is given.
--model-csv MODEL_CSV A table of known camera models and their RTSP URLs. Default: the file in the current directory, otherwise the one included with the package.
--override When a camera's manufacturer and model are in the model table, replace the RTSP URL in config.csv with the one from the table, even if a working URL was already found.

The validate command also updates the results in camera_onvif_info.json. After it finishes, config.csv contains the validated RTSP URL, with the credentials embedded, for each camera that passed.

fix

Some camera models need a custom video pipeline to stream reliably. The fix command applies these settings from a patch file to the matching cameras in config.csv. The settings are stored in the json column and are applied to the stream when brainframe-apps add-stream adds it.

brainframe-onvif-tools fix --dry-run
brainframe-onvif-tools fix

The patch file, onvif_patches.json by default, is a list of patches. Each patch matches cameras by manufacturer and model. In the pipeline, {url} is replaced by the camera's RTSP URL:

[
  {
    "manufacturer": "HIKVISION",
    "model": "DS-2CD2342WD-I",
    "onvif_patch": {
      "pipeline": "rtspsrc location=\"{url}\" latency=2000 protocols=tcp ! queue ! rtph264depay name=\"buffer_src\" ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw,format=BGR ! appsink name=\"main_sink\""
    }
  }
]
Option Description
--patch PATCH The patch file. Default: onvif_patches.json.
--input INPUT The config.csv file to update. Default: config.csv.
--dry-run Show which cameras would be updated, without changing the file.

update-ip

Cameras that get their address from DHCP can change IP address. After you run discover again, use update-ip to update the addresses in a BrainFrame settings file saved with brainframe-apps save-settings, so that the saved streams point to the cameras' new addresses.

brainframe-onvif-tools update-ip --dry-run
brainframe-onvif-tools update-ip

The command compares the new config.csv with the previous config.csv.old that discover created. Cameras are matched by serial number when it is known, and otherwise by unchanged IP address. The mapping is saved to ip_changes.json, and the addresses in the settings file are replaced.

For the best results, run scan and validate after each discover, so that serial numbers are available.

Option Description
--input INPUT The new device list. Default: config.csv.
--old OLD The previous device list. Default: the input file name with .old appended, for example config.csv.old.
--mapping MAPPING Where to save the IP address mapping. Default: ip_changes.json.
--settings SETTINGS The BrainFrame settings file to update. Default: settings.json.
--skip-compare Do not compare the lists. Use the existing mapping file.
--dry-run Show what would change, without changing the file.

The config.csv File

config.csv is a text file with one camera per line. The tags on the first and last lines tell brainframe-apps which actions to apply to the cameras:

<add_stream, load_settings, start_analyzing>
# ip:port,username,password,manufacturer,model,serial_number,audio_in,audio_out,auth_required,encoding,width,height,framerate,bitrate,system_datetime,rtsp_url,osd,json
192.168.1.10:80,admin,PASSWORD,HIKVISION,DS-2CD2342WD-I,ABC123456,yes,no,yes,h264,1920,1080,30,4096,,rtsp://admin:PASSWORD@192.168.1.10:554/Streaming/Channels/101,Front Door,
</>
Column Description
ip:port The camera's address and ONVIF port.
username, password The credentials found by scan.
manufacturer, model, serial_number Read from the camera.
audio_in, audio_out Whether the camera has an audio input or output.
auth_required Whether the camera requires a login.
encoding, width, height, framerate, bitrate The main stream's video settings.
system_datetime The camera's clock when it was scanned.
rtsp_url The RTSP URL, with credentials. Set by validate.
osd The camera's on-screen display text. brainframe-apps add-stream uses it as the stream name.
json Stream options, such as a custom pipeline. Set by fix, or edit it by hand.

Lines that start with # or < are ignored when streams are added.

Warning

config.csv, credentials.txt, and camera_onvif_info.json contain camera passwords in plain text. Restrict access to them and do not share them.

Troubleshooting

discover finds no devices. Run discover --auto and check that the machine is on the same network as the cameras. If the cameras are on another subnet, add it with --subnet. Some cameras have ONVIF turned off by default. Enable it in the camera's settings.

scan reports that no working ONVIF port was found. Check that ONVIF is enabled on the camera, and that the credentials are listed in credentials.txt or given with --user and --password. Some cameras need a separate ONVIF account. Run with --debug for more detail.

validate reports that ffprobe is not installed. Install FFmpeg, for example sudo apt install ffmpeg.

validate reports that a stream was rejected. Check the camera's password, and that the camera's RTSP service is enabled. Then run validate again. If the camera's manufacturer and model appear in the model table, try --override.