Skip to content

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_depth is hour-granular: only fully elapsed hours are deleted;
  • max_bytes is 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.

Next steps