Skip to content

Architecture

Aliran has five peer-to-peer components. Transport, discovery, and replication are fully serverless (Hyperswarm DHT — the mechanics are in How peers find each other). The panel is the logical authority for accounts and catalog, and it is the only online dependency, and only for new logins.

flowchart LR
  subgraph Origin
    OBS[OBS / RTSP / HLS / file]
  end
  OBS -->|ingest| B[broadcaster
Linux, headless] B -->|encrypted feed
Hyperdrive| SW((Hyperswarm DHT)) B -->|register stream| P[panel
accounts + catalog + OPRF] R[repeater
keyless super-peer] <-->|mirror + serve
ciphertext| SW L[library
VOD titles] -->|encrypted VOD drives
seed| SW L -->|register type:'vod'| P P <-->|login / catalog / entitlement| C1[client APK] P <-->|login / catalog / entitlement| C2[client APK] SW <-->|replicate + re-seed| C1 SW <-->|replicate + re-seed| C2 C1 <-->|mesh re-seed| C2

Components

Broadcaster (Linux)

Ingests an existing stream (OBS RTMP push, or a pull from RTSP/HLS/file), transcodes it to live HLS, writes the encrypted segments into a Hyperdrive, and seeds it over Hyperswarm. It registers the stream and its metadata with the panel. Playback "live" is handled by HLS semantics — the P2P layer just moves bytes.

Client (Android phone + TV)

A React Native (react-native-tvos) app embedding Bare via react-native-bare-kit. Inside Bare: Hyperswarm, a Hyperdrive replica, and a localhost HTTP server with Range support. react-native-video plays http://127.0.0.1:<port>/index.m3u8. The client both downloads and re-seeds — distribution scales with viewers. (The same engine also ships as aliran-kit, a native Kotlin SDK for non-RN Android apps — one APK from Android 5.0, with the engine active on 10+; see the SDK guide.)

Panel (Linux/desktop)

A single-writer, panel-signed Hyperbee holding the account DB and stream catalog, plus an assets Hyperdrive (posters/art). It serves an OPRF login RPC (the brute-force choke point) and issues session and entitlement tokens. Today a deployment runs one panel node — viewers only need it online for new logins. Availability is handled operationally with a warm standby plus a failover runbook (backup & rotation).

Repeater (Linux, optional)

A keyless regional super-peer (repeater.md) — the Open-Connect analog. Configured with only the panel's public key and a channel selection, it mirrors chosen channels' live windows raw at the block level (the catalog's feedKey plus the panel-published blobsKey) and serves that ciphertext to viewers, absorbing fan-out so the origin broadcaster's per-channel egress drops to roughly one stream per repeater. It holds no grants and cannot watch what it serves.

Library (Linux, optional — VOD)

The standalone VOD service (VOD library): operator-registered video files become encrypted, P2P-seeded on-demand titles (type:'vod' + durationSec in the catalog, granted exactly like channels). It is deliberately separate from the broadcaster: ingest is a one-shot transcode burst and then a static seed — none of the live pipeline's lifecycle applies, and it runs on whatever box has the disk and spare CPU. One Corestore plus one Hyperswarm carry every title. A title keeps all its segments (seek uses HTTP Range over demand-paged P2P blocks), so disk use equals title size, reclaimed only by delete.

Key data flows

  • Login: client → panel OPRF RPC (blinded password, PoW) → derives a key → verifies against the signed DB → unwraps stream keys. See security-model.md.
  • Catalog: the panel appends signed metadata; clients bee.watch() for live updates.
  • Stream join: the client takes feedKey from the catalog and the encryptionKey it unsealed at login (not from the catalog), joins the feed swarm, replicates (decrypting), serves locally, and plays.
  • Redirect channels: a catalog entry can instead carry {redirect: true, url} — the client plays the operator's https HLS URL directly (no feed, no swarm join). See content-management.md.

Sequence diagrams

Login (OPRF — brute-force resistant)

sequenceDiagram
  participant C as Client
  participant P as Panel (OPRF + throttle)
  participant DB as Signed account DB (replicated)
  C->>C: solve proof-of-work, then blind(password)
  C->>P: login(username, blindedPassword, pow)
  P->>P: verify PoW, check lockout(username, peerKey)
  P-->>C: OPRF(oprfKey, blindedPassword)
  Note over P: never sees password or result
  C->>C: rwd = unblind(...), wrapKey = Argon2id(rwd, salt)
  C->>DB: read signed user/
  C->>C: verify against record, unwrap stream keys
  C->>C: seal session in Keystore (long TTL)

Stream join & playback

sequenceDiagram
  participant U as UI (RN)
  participant B as Bare backend
  participant SW as Hyperswarm
  participant V as react-native-video
  U->>B: play(streamId)
  B->>B: feedKey from catalog + encryptionKey unsealed at login
  B->>SW: join(feed topic) — server+client (re-seed)
  SW-->>B: replicate encrypted segments (from broadcaster + peers)
  B->>B: start localhost HTTP server (Range) over decrypting drive
  B-->>U: { port }
  U->>V: source = http://127.0.0.1:port/index.m3u8
  V->>B: GET /index.m3u8, /segN.ts (Range)
  B-->>V: decrypted HLS bytes → live playback