Configuration reference¶
Cang reads a single TOML file at startup. Pass the path via the CLI (see cangcang --help or cangjian --help).
[server]¶
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
output_dir |
string (path) | yes | — | Root directory for all cang output (snapshots, database). |
scan_interval |
integer | no | 300 |
Seconds between periodic re-scans of all camera roots. On NFS mounts, this is the only pickup mechanism; lower the value (e.g. 30) for faster response to new snapshots. Set to 0 to disable. |
retention_days |
integer | no | 30 |
How many days to keep motion snapshots before automatic deletion. |
background_retention_days |
integer | no | 14 |
How many days to keep background ([F] flag) snapshots before automatic deletion. |
preview_width |
integer | no | 640 |
Maximum width in pixels of the small preview renditions generated at ingest. Previews are only served when the quality toggle (see Web UI) is set to fast mode. |
preview_quality |
integer | no | 75 |
JPEG quality (1–95) of the preview renditions. |
Storage layout¶
Everything cang produces lives under output_dir:
output_dir/
cang.db # metadata database
<camera>/
snapshots/<YYYY-MM-DD>/<HH.MM.SS>-….jpg # camera snapshots
previews/<YYYY-MM-DD>/<HH.MM.SS>-….jpg # small preview renditions
Snapshots are moved out of the camera incoming folders on ingest, and emptied date/hour directories are pruned. Anything still present in an incoming folder is unprocessed.
Preview renditions¶
For every snapshot stored, the daemon also generates a small preview
rendition (default 640px wide, JPEG quality 75) under
<camera>/previews/<date>/, mirroring the snapshots tree. Previews are
regenerable derived data: they are never a replacement for the original,
they are only served when you switch the web UI to fast mode (useful on
slow connections such as a remote mobile link), and retention deletes
them together with their original. Snapshots stored before this feature
have no preview; in fast mode those simply fall back to the original
until they age out of the store.
Upgrading from earlier versions¶
On first startup cang migrates automatically: snapshots referenced by the
database move from the incoming folders into the store above. The migration
only ever deletes an incoming file after a verified copy exists in
output_dir; files not yet processed are untouched. The
delete_after_transcode option is gone — a warning is logged if the key is
still in your config.
Cleaning up after the video removal (2026.7.23+)¶
Cang no longer processes or stores video clips. Existing clip files and metadata from earlier versions are not automatically cleaned up. To reclaim disk space:
# Remove all legacy clip files (per-camera)
rm -rf <output_dir>/<camera>/clips/
# Remove the ffmpeg log (if present)
rm -f <output_dir>/ffmpeg.log
# Optionally drop the orphaned clips table
sqlite3 <output_dir>/cang.db "DROP TABLE IF EXISTS clips"
The clips table is harmless if left in place — it uses negligible space and does not affect operation. Only the on-disk files matter for disk usage.
[[camera]]¶
One [[camera]] block per camera. At least one is expected.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | yes | — | Human-readable label used in logs and the web UI. |
adapter |
string | yes | — | Folder-layout adapter. Currently only "dahua" is supported. |
root |
string (path) | yes | — | Root directory that the adapter scans for incoming snapshots. For the dahua adapter this must point directly at the camera's serial directory (e.g. /mnt/nvr/ABC123456); date subdirectories are expected immediately inside. |
[web]¶
All keys are optional. Omitting the section uses the defaults shown below.
| Key | Type | Default | Description |
|---|---|---|---|
host |
string | "0.0.0.0" |
Interface address for the HTTP server. |
port |
integer | 8080 |
TCP port for the HTTP server. |
username |
string | — | Login username. Must be set together with password. |
password |
string | — | Login password. Must be set together with username. |
If neither username nor password is set, the web UI is accessible without authentication.
[events]¶
Optional section controlling how per-camera motion events are chained into cross-camera journeys. All keys are optional; omitting the section uses the defaults shown below.
| Key | Type | Default | Description |
|---|---|---|---|
journey_gap_seconds |
integer | 180 |
Maximum gap in seconds between the end of one camera's event and the start of another's for both to join into a single journey. Overlap always joins. The window applies per hop, not to total journey duration. |
Time synchronisation¶
Cang prunes empty snapshot source directories once their calendar day has passed. This relies on the server clock agreeing with the cameras' clocks — the server must know when "midnight" is in the same timezone the cameras name their date directories with. If the server and cameras disagree about the current date, pruning may delete directories the camera is still writing to, or leave finished directories unpruned.
All cameras must be in the same timezone as the server, and all clocks must be
kept accurate with NTP (Network Time Protocol). Container users should set the
TZ environment variable to the camera timezone (e.g. TZ=Australia/Brisbane).
Example¶
[server]
output_dir = "/var/lib/cang/snapshots"
scan_interval = 300 # periodic re-scan every 5 minutes (default)
# on NFS mounts, lower this (e.g. 30) for
# faster pickup of new snapshots
retention_days = 30 # keep motion snapshots for 30 days (default)
background_retention_days = 14 # keep background snapshots for 14 days (default)
preview_width = 640 # preview rendition width in pixels (default)
preview_quality = 75 # preview JPEG quality (default)
[web]
host = "0.0.0.0"
port = 8080
username = "admin"
password = "s3cr3t"
[[camera]]
name = "front-door"
adapter = "dahua"
root = "/mnt/nvr/ABC123456" # serial directory — date folders sit directly inside
[[camera]]
name = "back-yard"
adapter = "dahua"
root = "/mnt/nvr/DEF789012"