Skip to content

Introduction

This content is for the 1.0 version. Switch to the latest version for up-to-date documentation.

StreamHub is a self-hosted, open-source media server built on LiveKit — a drop-in-style alternative to AntMedia. It wraps a LiveKit SFU (selective forwarding unit) with a management layer that gives you multi-tenant apps, RTMP/WHIP/RTSP ingest, WebRTC + HLS playback, one-command recording to per-app S3, an embeddable player, signed webhooks, a REST API, and a React dashboard — all behind one domain with automatic HTTPS.

LiveKit on its own is just the SFU: rooms, tokens, WebRTC fan-out. StreamHub is the layer that makes a plain LiveKit deployment behave like a product — tenancy, storage, an API, a UI, and operational tooling — the same relationship AntMedia has to a raw media engine.

Everything runs from one docker compose up.

StreamHub is a small set of independently-buildable projects in one repository (vision-media-server), each with its own package.json:

Path Stack Role
streamhub-core/ NestJS, TypeScript strict, better-sqlite3, BullMQ The brain: REST API /api/v1, serves the compiled SPA, HLS, and the browser SDK. Binds 127.0.0.1:3020.
streamhub-web/ React 19 + Vite + Tailwind 4 The dashboard SPA — built into the core image, not deployed separately.
streamhub-adaptor/ TypeScript + tsup The browser SDK: an AntMedia WebRTCAdaptor shim over livekit-client, served at /sdk/.
yolo-worker/ Python (ultralytics + opencv) A worker process spawned by the built-in yolo plugin.
deploy/ Dockerfile, Caddyfile, entrypoint, seed-token.js, systemd/nginx units Everything needed for both supported deploy shapes.
streamhub-docs/ Markdown Architecture, operations, API reference, and the testing catalogue.

LiveKit itself — the SFU, plus its ingress and egress companion services — is not part of this repository; StreamHub drives it entirely through the official livekit-server-sdk and its webhooks.

A single reverse proxy (Caddy in the Docker Compose quick-install, or nginx+certbot in the bare-metal/systemd deploy shape) terminates TLS on one domain and splits traffic by path:

https://streamhub.example.com
/rtc → livekit-server :7880 (wss signaling / WebRTC upgrade)
/api/v1/* → streamhub-core :3020 (REST API, Bearer sk_ / JWT)
/hls/* → streamhub-core :3020 (HLS playlists + segments)
/sdk/* → streamhub-core :3020 (streamhub-adaptor browser SDK)
/samples/* → streamhub-core :3020 (public per-app embed pages, auth-less)
/metrics → streamhub-core :3020 (Prometheus, optional token)
/* → streamhub-core :3020 (React SPA)

WebRTC media (7882/udp), RTMP (1935) and WHIP (8080) are not proxied — publishers and viewers hit those ports on the server’s IP directly, since a plain HTTP(S) reverse proxy can’t carry UDP media.

The multi-stage deploy/Dockerfile builds three things and combines them into a single runtime image:

  1. streamhub-web (the React SPA) → its dist/ is copied into the core image as ./web, served by NestJS’s ServeStaticModule.
  2. streamhub-adaptor (the browser SDK IIFE) → staged in the image; the container entrypoint copies it into <DATA_DIR>/sdk at boot, so core serves it live at /sdk/streamhub-adaptor.global.js.
  3. streamhub-core itself → compiled to dist/ with its production node_modules (including the native better-sqlite3 addon).

The result is one Node process on one port that serves the REST API, the dashboard, HLS playlists, the browser SDK, and per-app sample pages. There is no separate UI server — a SPA change ships by rebuilding the core image, not a standalone frontend deploy.

Install

The one-line installer, manual Docker Compose install, LiveKit configuration, and joining a cluster as an edge node. Installation →

Configure

The server .env, per-app config.yaml, ports, and known limitations. Configuration →

Build with the API

REST API /api/v1, auth planes, webhooks, and the drop-in browser SDK. API reference →

Extend with plugins

The plugin framework and every built-in plugin, with its configuration. Plugins →