Skip to content

About

Universal hybrid P2P-CDN middleware for HLS live streaming: WebRTC/HTTP peer sharing, verified segments, and deadline-aware origin fallback.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

87 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenStreamGrid

License: MIT Latest release CI Node.js 22+ Docker images

Universal hybrid P2P-CDN middleware for standards-based live streaming.

English | 한국어

OpenStreamGrid adds peer-assisted delivery to HLS streams with MPEG-TS (.ts) or CMAF/fMP4 (.m4s) media segments; LL-HLS partial segments are a roadmap item. Peers share and SHA-256-verify media segments, while fMP4 init segments and playlists always load from your origin or CDN. Your origin continues to encode and publish media while OpenStreamGrid discovers peers, verifies segments, limits resource use, reports delivery metrics, and immediately falls back to the origin when P2P cannot meet the playback deadline.

OpenStreamGrid is delivery middleware, not a complete streaming platform. It integrates with your existing origin, CDN, and player stack.

Quick Start

With Docker Compose v2 installed, start the tracker, test origin, and two peers with one command:

git clone --branch v0.6.1 --depth 1 https://github.com/mytrashcan/OpenStreamGrid.git
cd OpenStreamGrid
docker compose up --build --detach
docker compose ps
Service Local URL
Monitoring dashboard http://localhost:7070/dashboard
Tracker health http://localhost:7070/health
Master HLS playlist http://localhost:8080/hls/stream.m3u8
Peer A / Peer B http://localhost:9091 / http://localhost:9092

The Compose stack generates a live test pattern with FFmpeg. Once healthy, the peers begin exchanging verified segments and fall back to the origin whenever a peer is unavailable or too slow. Stop the stack with docker compose down.

Release Status

OpenStreamGrid v0.6.1 is the current stable release. It is a patch release on top of v0.6.0's reproducible QoE benchmarks, pluggable scheduling policies, and deadline-aware P2P/Origin hedging: it hardens peer joins and WebSocket upgrades, fixes the WebSocket Origin allowlist for Node peers, corrects Helm image tags, and ships multi-architecture container images. Use the release tag for reproducible deployments and review the release notes before upgrading. See the changelog for the complete history.

Tagged container images are published to GHCR for production deployment:

Component Image
Tracker ghcr.io/mytrashcan/openstreamgrid-tracker:v0.6.1
Origin ghcr.io/mytrashcan/openstreamgrid-origin:v0.6.1
Node peer ghcr.io/mytrashcan/openstreamgrid-peer:v0.6.1

Images are built for linux/amd64 and linux/arm64 and tagged both vX.Y.Z and X.Y.Z (from v0.6.1; earlier releases are linux/amd64 with vX.Y.Z only). Use immutable version tags in deployments; latest is provided for evaluation. The browser SDK package is build- and publish-dry-run verified in CI but is not yet published to npm. Until the first registry release, consume it from a tagged source checkout and build it locally:

npm ci --prefix sdk
npm run build --prefix sdk

Use Cases

  • Live streaming platforms — reduce origin and CDN segment traffic while preserving reliable playback during peer churn.
  • Enterprise webinars and town halls — distribute simultaneous internal viewing load across participating clients.
  • E-learning and virtual classrooms — share live lecture segments among learners without replacing the existing HLS workflow.

The current prototype is best suited to evaluation and controlled deployments. Review Security and the release notes before planning a production rollout.

Architecture

                    HTTP behind TLS proxy / API key
  encoder ──► origin ─────────────────────────► tracker + SQLite WAL
     │          │                                  │  │
     │          ├── HLS renditions                 │  ├── REST + WebSocket
     │          └── SHA-256 sidecars               │  └── dashboard + SSE
     │                                             │
     │                   peer discovery / stats ───┘
     │
     └──────────────────────── CDN / origin fallback
                                      │
                           ┌───────────┴───────────┐
                           ▼                       ▼
                      Node peer A ◄──────────► Node peer B
                           │       HTTP/WebRTC     │
                           │       STUN/TURN       │
                           ▼                       ▼
                      segment cache          segment cache
                           │                       │
                           └──── Hls.js browser SDK┘

The tracker isolates state by broadcast ID, so multiple channels can share one deployment. The origin can generate multiple test channels and three HLS renditions per channel. Production media origins can register their own playlist URLs through the same API.

Scheduling

OpenStreamGrid uses the shared SegmentScheduler contract with runtime-specific default policies. Node peers use WeightedScoreScheduler, which combines latency, success rate, upload bandwidth, and trust from longer-lived peer observations. The browser SDK uses TrustLatencyProbeScheduler, which ranks the tracker snapshot by trust and then latency before probing up to three peers in parallel. The policies differ because browser playback sessions have less persistent peer-quality history than Node peers.

Applications can inject a custom scheduler through the Node fetcher or the browser SDK's scheduler option. Browser decisions are observable through the scheduler_decision SDK event. Regardless of policy, the delivery layer treats Origin/CDN fallback as authoritative whenever P2P is unavailable or a plan chooses Origin.

Features

  • Hybrid HTTP/WebRTC segment delivery with immediate origin fallback.
  • Admin API-key authentication plus short-lived, peer-scoped session tokens.
  • HTTPS-compatible clients; terminate TLS at a trusted reverse proxy.
  • Configurable STUN and TURN servers for WebRTC NAT traversal.
  • Multi-channel isolation and multi-rendition HLS generation.
  • Quality-based peer ranking, parallel downloads, and request coalescing.
  • SHA-256 verification, peer trust scoring, and integrity-failure exclusion.
  • TTL-aware LRU caching, upload bandwidth limiting, and connection limits.
  • Real-time dashboard, Prometheus metrics, SSE updates, and SQLite history.
  • Grafana dashboard and Prometheus Operator ServiceMonitor in the Helm chart.
  • Docker Compose, load-test scenarios, Kubernetes/Helm manifests, and CI.

Zero-install browser peers

The Hls.js SDK turns each viewer into a WebRTC peer automatically. It registers the viewer, caches verified segments, advertises availability, serves cached bytes through a rate-limited DataChannel, reports traffic, and unregisters on detach. Viewers do not install an executable or browser extension.

The following example assumes your bundler resolves the locally built @openstreamgrid/sdk package:

import Hls from "hls.js";
import { OpenStreamGridHlsPlugin } from "@openstreamgrid/sdk";

const hls = new Hls();
const plugin = new OpenStreamGridHlsPlugin({
  trackerUrl: "https://stream.example.com",
  broadcastId: "live",
  originBaseUrl: "https://stream.example.com/hls",
  maxUploadBitrate: 1_000_000,
  maxUploadConnections: 3,
  iceServers: [
    { urls: "stun:stun.example.com:3478" },
    {
      urls: "turns:turn.example.com:5349",
      username: "viewer",
      credential: "short-lived-credential",
    },
  ],
});
plugin.attach(hls);
hls.loadSource("https://stream.example.com/hls/stream.m3u8");
hls.attachMedia(document.querySelector("video")!);

Rather than embedding TURN credentials in viewer code, set TURN_URLS and TURN_SHARED_SECRET on the tracker. Each peer then receives short-lived TURN credentials with its session, the SDK adds them to iceServers, and they are renewed with the session.

Set peerParticipation: false for receive-only playback. A native agent or browser extension can still be useful as an optional dedicated seed in managed environments, but it is not part of the normal viewer path.

Browser peers automatically receive a short-lived, identity-scoped session when they register. Do not pass or embed TRACKER_API_KEY in viewer code; reserve the administrator credential for trusted origin and operations components.

Shaka Player

OpenStreamGridShakaPlugin provides the same delivery core for Shaka Player. It registers an HTTP(S) scheme plugin, so media segment requests go through the grid and every other request uses Shaka's fetch plugin:

import shaka from "shaka-player";
import { OpenStreamGridShakaPlugin } from "@openstreamgrid/sdk";

const plugin = new OpenStreamGridShakaPlugin({
  trackerUrl: "https://stream.example.com",
  broadcastId: "live",
  originBaseUrl: "https://stream.example.com/hls",
});
plugin.attach(shaka);
const player = new shaka.Player();
await player.attach(document.querySelector("video")!);
await player.load("https://stream.example.com/hls/stream.m3u8");

It takes the same options as the Hls.js plugin. Shaka scheme plugins are global, so attach one instance per page; detach() restores Shaka's fetch plugin. Shaka does not expose the playback position to network plugins, so the adapter derives a deadline from each request's retry and stall timeouts: peers get the first part of that budget, and the origin is used before Shaka would abort.

Tracker API

Tracker resources are under /api/v1. Administrators send X-API-Key: <key> or, for scrapers such as Prometheus, Authorization: Bearer <key>. Peer join returns a short-lived session token; peer REST calls use Authorization: Bearer <token> and WebSocket upgrades use ?sessionToken=<token>.

Method Path Purpose
GET /health Check tracker readiness
GET /dashboard Open the monitoring UI
GET /metrics Read Prometheus metrics
GET /ws Upgrade to WebSocket signaling
GET /api/v1/stats Read global traffic totals
GET /api/v1/stats/events Subscribe to monitoring SSE
POST /api/v1/broadcasts Register or update a broadcast
GET /api/v1/broadcasts List broadcasts
GET /api/v1/broadcasts/:id Read broadcast details and peers
DELETE /api/v1/broadcasts/:id Unregister a broadcast
GET /api/v1/broadcasts/:id/stats Read broadcast traffic totals
POST /api/v1/broadcasts/:id/peers Join a broadcast
GET /api/v1/broadcasts/:id/peers List peers; filter with ?segment=
DELETE /api/v1/broadcasts/:id/peers/:peerId Leave a broadcast
POST /api/v1/broadcasts/:id/peers/:peerId/segments Report cached segments
PUT /api/v1/broadcasts/:id/peers/:peerId/heartbeat Refresh peer health
POST /api/v1/broadcasts/:id/peers/:peerId/stats Report traffic totals
POST /api/v1/broadcasts/:id/peers/:peerId/reports Report a peer failure

See API_REFERENCE.md for schemas, signaling messages, status codes, and origin/peer endpoints.

Configuration

Tracker

Variable Default Description
PORT 7070 HTTP listen port
HOST 0.0.0.0 Listen address
STALE_PEER_MS 30000 Peer inactivity timeout
STORE_TYPE sqlite Persistence backend: sqlite or memory
DB_PATH ./data/tracker.db SQLite database path
TRACKER_API_KEY unset Admin credential for broadcast management, monitoring, and metrics
PEER_SESSION_SECRET random per process HMAC secret of at least 32 bytes; set explicitly in deployments
PEER_SESSION_TTL_MS 3600000 Peer session lifetime
RATE_LIMIT_RPS 100 Sustained requests per second per client
RATE_LIMIT_BURST 200 Token-bucket burst capacity per client
MAX_PEERS_PER_BROADCAST 500 Active-peer limit per broadcast
TRACKER_WS_ALLOWED_ORIGINS unset Comma-separated http(s) origins allowed to open /ws from a browser; other browser origins receive 403. Upgrades without an Origin header, such as Node peers, still require a valid peer session
TRACKER_WS_MAX_CONNECTIONS_PER_IP 20 Concurrent /ws connections per client address; raise it when many viewers share one NAT address
TRUST_PROXY_HOPS 0 Number of trusted reverse proxies in front of the tracker; per-client limits then use the client address they record in X-Forwarded-For. Set to 1 behind a single ingress or TLS proxy
TURN_URLS unset Comma-separated turn:/turns: URIs returned with short-lived credentials on peer join; browser and Node peers add them to their ICE servers
TURN_SHARED_SECRET unset TURN server shared secret (coturn static-auth-secret, at least 16 bytes); required with TURN_URLS

Origin

Variable Default Description
PORT 8080 Origin listen port
HOST 0.0.0.0 Listen address
TRACKER_URL http://tracker:7070 Tracker base URL
TRACKER_API_KEY unset API key used for tracker registration
BROADCAST_ID live Base broadcast/channel ID
MULTI_STREAM_COUNT 1 Generated test-channel count
PUBLIC_ORIGIN_URL http://origin:<PORT> URL advertised to clients
HLS_DIRECTORY /tmp/openstreamgrid-hls Generated HLS directory
SEGMENT_DURATION_SECONDS 2 HLS target duration
HLS_SEGMENT_TYPE mpegts mpegts for .ts segments or fmp4 for CMAF/fMP4 (.m4s plus a per-rendition init segment)
PLAYLIST_SIZE 8 Segments retained per media playlist
HASH_INTERVAL_MS 250 Sidecar hash discovery interval
FFMPEG_PATH ffmpeg on PATH FFmpeg executable override

Node Peer

Variable Default Description
TRACKER_URL http://tracker:7070 Tracker base URL
TRACKER_API_KEY unset Optional admin key; normal peer traffic uses the issued session token
BROADCAST_ID live Broadcast to join
ORIGIN_URL required Rendition directory or .m3u8 URL
PEER_ADDRESS required Advertised http://host:port address
PEER_ID hostname Stable peer identifier
UPLOAD_HOST 0.0.0.0 Upload server bind address
CACHE_SIZE 512MB Maximum segment-cache size
CACHE_TTL_MS 300000 Absolute cache-entry lifetime in milliseconds
MAX_UPLOAD_SPEED 1Mbps Token-bucket upload bit rate
MAX_CONNECTIONS 3 Concurrent peer uploads
MAX_PARALLEL_DOWNLOADS 3 Concurrent segment downloads
PLAYLIST_POLL_MS 500 HLS playlist poll interval
P2P_TIMEOUT_MS 2000 Peer request deadline
WEBRTC_ENABLED true Try WebRTC before HTTP
STUN_SERVER public Google STUN stun: or stuns: ICE server URL
TURN_SERVER unset turn: or turns: relay URL
TURN_USERNAME unset TURN username
TURN_CREDENTIAL unset TURN credential

Equivalent CLI flags are available for the primary peer options. Benchmark configuration is available through the following environment variables.

Browser SDK

Option Default Description
peerParticipation true Register and upload as a zero-install browser peer
iceServers public Google STUN STUN/TURN servers for WebRTC NAT traversal
maxUploadBitrate 1000000 Browser upload limit in bits per second
maxUploadConnections 3 Concurrent browser DataChannel uploads
peerTimeoutMs 3000 Peer request and negotiation deadline
maxCacheBytes 100 MB Browser segment-cache limit
hashUrlResolver adjacent .sha256 Override signed/query-aware sidecar URL resolution

Benchmark

Variable Default Description
PEER_COUNT 10 Number of virtual peers
DURATION_SECONDS 60 Measurement duration
RAMP_UP_SECONDS 5 Peer startup ramp
CHURN_RATE 0.15 Per-cycle churn probability
REPORT_INTERVAL_SECONDS 10 Console report interval
BENCHMARK_OUTPUT benchmark-results.json JSON output path
BENCHMARK_PROJECT_NAME openstreamgrid-benchmark Isolated Compose project name
TRACKER_URL http://127.0.0.1:7070 Host health-check URL
ORIGIN_URL http://127.0.0.1:8080 Host health-check URL

Performance Baseline

The reproducible local Docker baseline for the default 10-peer, 60-second scenario achieved 46.07% P2P efficiency and 47.44% CDN traffic reduction. These figures are regression data, not a production capacity claim. See the raw benchmark result and release notes for the full scenario and latency measurements. Run it locally with bash scripts/benchmark.sh.

Phase 3 scheduler policy lab: mixed-workload

Policy Deadline met Peer wins Origin wins Hedges started Completion p50 Completion p95
Node-legacy 85% 77.5% 22.5% 0% 860.54 ms 1,365.97 ms
Node-deadline-aware 100% 63.75% 36.25% 6.75% 769.12 ms 1,332.58 ms
Browser-legacy 84.5% 98.75% 1.25% 0% 801.72 ms 1,271.02 ms
Browser-deadline-aware 100% 81.5% 18.5% 0.75% 722.18 ms 1,265.83 ms

Fixed seed phase3-mixed-2026; 400 deterministic requests per policy. Controlled simulation using production schedulers—not a production capacity claim. See the scheduler lab.

Benchmark data is generated by running bash scripts/benchmark.sh --scenario benchmarks/scenarios/ci-smoke.json. See benchmark methodology for details.

Development

For local development, install Node.js 22+, npm, Docker Compose v2, and FFmpeg.

npm ci
npm ci --prefix sdk
npm run build
npm run typecheck
npm test
npm run lint

Repository layout: tracker/ owns discovery, persistence, signaling, and monitoring; origin/ owns test HLS generation and serving; peer/ is the Node peer; sdk/ is the browser/Hls.js package; common/ contains shared contracts; test/ and scripts/ contain integration and load tooling.

Tip

Want to contribute? Read CONTRIBUTING.md for setup, testing expectations, coding guidelines, and pull request requirements.

Community

Discord: coming soon GitHub stars License: MIT

The Discord community is not open yet. This badge will be linked to the official server once one is available.

Star History

Star History Chart

If OpenStreamGrid is useful to you, consider starring the repository.

Documentation

License

OpenStreamGrid is licensed under the MIT License.

About

Universal hybrid P2P-CDN middleware for HLS live streaming: WebRTC/HTTP peer sharing, verified segments, and deadline-aware origin fallback.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages