DVR recording¶
Sapsan's DVR is its own on-disk storage: a stream is written append-only into hourly files, per track, across several disks at once. Archive reads do not interfere with writes.
Storage¶
The global dvr section describes the whole storage:
dvr:
root: /storage # archive root
catalog: /storage/catalog # blob catalog (defaults to <root>/catalog)
disks:
- path: d1 # disks relative to root
- path: d2
- path: d3
Disk parameters:
| Parameter | Description |
|---|---|
path |
disk path relative to root |
mode |
Active (default) or Degraded — the disk is read but not written |
min_free_bytes |
minimum free space reserve |
check_mount verifies that the disk path is actually a mount point (protects against writing into an empty directory when a disk drops off).
Enabling recording for a stream¶
streams:
cam1:
inputs:
- rtsp:
url: rtsp://admin:password@10.0.0.5/stream0
dvr:
max_depth: 168 # archive depth, hours
max_bytes: 500000000000
dvr: {} enables recording with default settings.
Write distribution across disks¶
Sapsan balances recording across active disks on its own:
- consecutive hours of one stream alternate between disks;
- neighboring streams are spread evenly across disks;
- tracks of a multibitrate stream are written to different disks in parallel.
A disk in degraded mode keeps serving reads but receives no new data — this is how you decommission a disk without losing the archive.
Cleanup and retention¶
Cleanup runs once an hour (5 minutes after the hour boundary):
max_depthis hour-granular: only fully elapsed hours are deleted;max_bytesis counted from newest blobs to oldest: everything older than the first blob exceeding the limit is deleted;- when both limits are set, the tighter one wins;
- blobs with protected episodes are never deleted by retention;
- the blob of the current (actively written) hour is never deleted.
Disk-overflow protection works separately: when free space drops below min_free_bytes (default 1% of disk capacity), Sapsan deletes the oldest blobs regardless of retention until enough space is freed.
How storage works¶
The archive is laid out on disks as <disk>/<hash>/<stream>/<Y>/<M>/<D>/<hour>.mp4. Files are only appended, never rewritten; identical init segments are deduplicated within a blob.
A background indexer continuously reconciles the catalog with the disks and heals divergence without administrator involvement:
- blobs that appeared on disk behind the catalog's back (e.g. after moving disks from another server) are added to the catalog;
- records of missing files are removed;
- a corrupt blob sidecar index is rebuilt by scanning the blob itself;
- blob byte sizes and bloom filters are backfilled in the background (blobs younger than one hour are left alone).
Reads are failure-tolerant: if the catalog points at the wrong disk, the fragment is searched on all disks of that hour; orphaned catalog records are skipped without an error.
Observability¶
DVR reports statistics per disk (free/total space, read/write op and byte counters, blob counts, bytes used by the archive) and for the catalog — see the Admin API and monitoring.