Skip to content

Technical architecture

Flussonic Sapsan is a server application written in Rust. All subsystems run inside a single sapsan process as tasks of the tokio asynchronous runtime and interact over typed message channels — with no shared mutable state between subsystems.

Components

Component Purpose
Manager configuration loading and validation, subsystem startup, network listener binding, hot reload, Admin API
Network listeners HTTP (HLS, DASH, MPEG-TS, WHIP/WHEP, API), RTSP, RTMP, WebRTC (UDP), per-stream SRT ports
Streams manager stream lifecycle: inputs and source switching (LSI), publishing, pushers, screenshots
Transcoder decoding and encoding (FFmpeg): H264/HEVC/AV1, AAC/Opus, the multibitrate ladder
Segmenter and live buffer slicing the stream into fMP4 fragments, the live-edge ring buffer
Content manager the unified content surface: merges the live buffer, the local archive, and remote archives; all delivery protocols read from it
DVR on-disk archive storage: hourly append-only blobs, a catalog on an embedded KV database, a background indexer (rebuild, metadata backfill, cleanup)
Cluster reading archives from remote Sapsan servers over the internal streaming-api
Sessions and authorization viewer/publisher session accounting, tokens, external auth backends
Peeklio gateway a reverse proxy for devices behind NAT: agent registration, tunnels
Telemetry structured logs, Prometheus metrics, OpenTelemetry traces

Data flows

sources                   processing                    delivery
───────                   ──────────                    ────────
RTSP / MPEG-TS ─┐
SRT / RTMP      ├─► LSI ─► [transcoder] ─► segmenter ─► live buffer ─┬─► HLS / LL-HLS
file / syntetic ┘   (source                             │            ├─► DASH
WHIP / publish ─────► selection)                        ▼            ├─► MPEG-TS, SRT, RTSP
                                                       DVR           ├─► WebRTC (WHEP)
remote servers ────► cluster ──┐                        │            └─► pushers (RTMP/SRT/UDP)
                               ▼                        ▼
                           content manager ◄────────────┘
                           (live + archive + remote)
  • Write path: the stream's active input (selected by LSI) delivers frames; they optionally pass the transcoder; the segmenter assembles fMP4 fragments, which enter the live buffer and are appended to the DVR in parallel.
  • Read path: a protocol module requests data from the content manager, which transparently picks the source — the live buffer, the local archive, or a remote server. Players never know where the data physically came from.
  • DVR read/write isolation: each stream's writes are serialized in its own task; reads bypass it and go straight to the blobs through a shared cache — readers do not contend with the writer.

Content addressing

The unit of storage and delivery is a fragment addressed by absolute UTC time (DTS + timescale). The same fragment name is valid in the live buffer, in the archive, and on every cluster server. This property underpins the seamless stitching of live to archive and the merging of archives across servers. The URL contract (routes, playlist URIs, fragment references) is defined in a single streaming-api module shared by the server and cluster clients.

Configuration lifecycle

  1. The configuration is read from sapsan.yaml and validated as a whole; an invalid configuration is not applied.
  2. On SIGHUP the configuration is re-read: streams, authorization, and DVR are reconfigured in place; listeners are rebound only when a port changes.
  3. With config_external enabled, the stream list is periodically fetched from an external server; partially invalid updates are applied without the broken streams, fully invalid ones are discarded keeping the working configuration.

Technology stack

Layer Technology
Language Rust
Async runtime tokio (network I/O, tasks), rayon (CPU parallelism)
Allocator jemalloc
Transcoding FFmpeg
DVR catalog embedded key-value database (LSM)
Observability OpenTelemetry (OTLP), Prometheus