StreamHub
In beta — try it free

Your self-hosted media server WebRTC + RTMP + HLS + recording, all self-hosted

StreamHub is a management layer on top of LiveKit: sub-second WebRTC, multi-protocol ingest, live HLS, recording to your own S3, and a lightweight drop-in JavaScript SDK to publish and subscribe over WebRTC. Multi-tenant, with signed webhooks and observability.

  • WebRTC
  • RTMP
  • WHIP
  • RTSP
  • HLS
Open source · self-hostable …or we host it for you
app.streamhub.studio
StreamHub dashboard: server status, CPU/memory/disk, active streams, apps and ingress/egress live
Features

A complete media server, self-hosted

WebRTC, RTMP, WHIP, RTSP and HLS; recording to your S3; realtime, multi-tenant, signed webhooks and a lightweight WebRTC SDK. Built on LiveKit, self-hosted.

Streaming

Multi-protocol ingest and output

Come in however you want, go out in low-latency WebRTC or embeddable HLS.

Low-latency WebRTC

sub-second

WebRTC player on LiveKit with sub-second latency for "watch live now" and video calls. Ephemeral per-room subscribe tokens.

RTMP ingest

RTMP · OBS

Push from OBS/ffmpeg to rtmp://…:1935/live/<key>. Stream key + optional password: StreamHub drops any push that wasn't validated first.

WHIP

WebRTC-HTTP

WHIP endpoint to publish over WebRTC straight from the browser or modern encoders, without going through RTMP.

RTSP relay

RTSP pull

Pull from a remote source (rtsp://camera/stream) and republish it into the room. Ideal for IP cameras and NVRs.

Live HLS

video.js

Segmented HLS egress served at /hls/<app>/<room>/index.m3u8 (video.js, open CORS). ~6-15s, embeddable anywhere.

Recording & output

Record to your own S3, restream anywhere

The media is yours: it lands in your bucket. Outputs go to YouTube, Twitch or your CDN.

Recording to YOUR S3

AWS · Wasabi · MinIO

MP4 egress uploaded to your own S3 bucket (AWS, Wasabi, MinIO). One bucket/prefix per app; keys never live in the YAML.

Ready-to-play VOD

VOD

Every recording lands as a VOD in your S3 with a snapshot, metadata (duration/resolution/codec) and a public or presigned URL.

Split MP4 by parts

split N min

Cut the recording every N minutes: each part is its own MP4 = its own VOD, indexed and with a recording_part_ready callback.

Periodic snapshots

JPEG every Ns

Capture a JPEG every N seconds during recording, uploaded to your S3. On-demand snapshots of any room too.

Webcam broadcast → RTMP

YouTube · Twitch

Forward a room to an external RTMP/RTMPS (YouTube/Twitch/custom) with the Broadcast widget: browser webcam → restream.

Realtime

Live interaction and events

Chat, reactions and viewers over data-channels; signed webhooks for everything that happens.

Live chat

data-channel

Chat over LiveKit data-channels (with emojis). The backend can inject messages and it fires the chat_message callback.

Reactions

reactions

Floating animated reactions on the reaction topic: real-time hearts and likes, with their reaction callback.

Viewer counter

live

Real subscriber count per live stream, excluding publishers and hidden/QC participants. Exported to Prometheus.

Signed webhooks

HMAC-SHA256

StreamHub posts a signed JSON (HMAC-SHA256) for EVERY event: room, participants, ingress/egress, recording, VOD and HLS.

Embeddable players

/play · /embed

Public /play and /embed pages + iframe snippet. WebRTC and HLS players without auth, with a chat/reactions/viewers panel included.

Scale

Multi-tenant, adaptive and observable

Isolated apps, adaptive transcoding with optional GPU and Prometheus metrics for everything.

Adaptive transcoding

720 / 480 / 240

Rendition ladder via LiveKit simulcast + multi-layer ingress for an adaptive player per app, with no extra config.

Optional GPU

NVENC · VAAPI

Per-node GPU detection (NVIDIA nvidia-smi / VAAPI /dev/dri) and auto/gpu/cpu hwaccel per app. Never fails when there's no GPU.

Isolated multi-tenant apps

apps

Each app is a tenant: namespaced rooms/streams, its own S3, its own VODs/DB, its own tokens and callbacks — fully isolated.

Teams, roles and quotas

RBAC · quotas

Teams isolated per tenant, roles/permissions and quotas: apps, concurrent streams, recording minutes and GB of egress per month.

Observability

Prometheus

Prometheus metrics at /metrics (streams, viewers, VODs, S3 uploads, callbacks, GPU…), health probe, stats and queryable logs.

Per-app SQLite

SQLite

Global streamhub.db registry + one vods.db per app. No heavy database to operate: SQLite per tenant and media in S3 per app.

Devs

API, drop-in SDK and open source

Everything over an API, everything self-hostable. Drop in the SDK and start publishing in a few lines.

Drop-in JS SDK

@streamhub/adaptor

A lightweight JavaScript SDK: pull in @streamhub/adaptor (npm or a <script> tag) and StreamHubAdaptor lets you publish and subscribe over WebRTC in a few lines.

REST API

/api/v1

API under /api/v1 with an { data, error } envelope. Apps, ingress, recording, VODs, tokens, broadcast and HLS: all over HTTP.

Auth + API tokens

JWT · sk_ tokens

Built-in auth (JWT signup/login, teams, superadmin) + sk_ API tokens for server-to-server. Bearer on every endpoint.

Radio / audio-only

audio-only

Audio-only rooms (Discord-style voice) + radio mode: one host publishes and listeners join hidden, subscribe-only, with a public listen-token.

Open source or hosted

self-host · hosted

Self-hostable end to end (Docker + LiveKit). In beta and free. Don't want to run it? We host it for you.

Take a look

Your backoffice, live

Real screenshots of the StreamHub backoffice. One place for your apps, streams, recordings, tokens and webhooks — running on LiveKit.

app.streamhub.studio live
Real-time dashboardSub-second live playerMulti-participant roomsMulti-protocol ingestAdaptive delivery per appIsolated, multi-tenant apps

Real-time dashboard

Core status at a glance: live CPU, memory and disk, active streams, registered apps and ingress/egress connections. With LiveKit health and uptime.

Live metricsLiveKit healthPrometheus
See it in the app

Light or dark, your call — the whole backoffice is themed.

Dashboard · light theme
Dashboard · light theme
Built-in auth · login
Built-in auth · login

How it works

From zero to on-air in three steps.

01

Create an app

Each app is an isolated tenant: its own room prefix, S3 bucket, tokens and quotas. Ready in seconds from the backoffice.

02

Publish

Push your feed over RTMP, WHIP, RTSP or straight from the webcam. Copy the URL and stream key into OBS and go live.

03

Watch, record and embed

Sub-second WebRTC or HLS, recording to your own S3 (VOD + snapshots) and embeddable players via public link or iframe.

Try it with your own streams

We're in beta and it's free. Open source and self-hostable — or we host it for you.

Documentation

Docs & API

A complete, self-hostable stack — documented end to end. A REST API (global and per-app), signed webhooks, per-app config, native integrations and a one-command deploy. Every route lives behind a single domain, with a live OpenAPI explorer.

Features

Per-feature deep-dives, from WebRTC to quotas.

  • WebRTC · ingest · HLS-live
  • Recording → S3 · VOD
  • Broadcast · transcoding/GPU
  • Chat · reactions · viewers

Global API

Server-wide REST surface, guarded by sk_ tokens.

  • GET /health · /stats
  • CRUD /apps
  • POST /tokens (mint sk_)
  • GET /logs
Open in Swagger →

Per-app API

Everything scoped to a single tenant app.

  • tokens · ingress · recording
  • vods · streams · snapshots
  • HLS start/stop
  • config · transcoding layers
Open in Swagger →

Webhooks & callbacks

Incoming LiveKit events and outbound signed POSTs.

  • HMAC-SHA256 signature
  • stream_started / _ended
  • vod_ready · recording_failed
  • chat_message · reaction

Config reference

The per-app config.yaml, secrets stripped.

  • recording · rtmp · webrtc
  • per-app S3 bucket
  • features block
  • callbacks url + secret

Integrations

Native and device clients, and the protocol each speaks.

  • Android (livekit-android)
  • iOS (LiveKitClient)
  • C++ (ffmpeg → RTMP)
  • ESP32-CAM → relay → RTMP

Self-hosting

One docker compose up, or systemd + nginx.

  • Compose + Caddy / nginx
  • every ENV var documented
  • runbook · backups · rollback
  • Prometheus + Grafana

Architecture

How it is built and where it is heading.

  • mono-Node core + LiveKit
  • per-app SQLite data model
  • origin + edge cluster
  • WebRTC vs HLS/CDN

The REST API in five calls

Authenticate with a sk_ token. Room names are namespaced under the app prefix (live + demolive-demo).

base ·https://streamhub.digitalhub.com.ar/api/v1
# Scaffold an isolated tenant: config, per-app SQLite, S3 prefix, samples
curl -s -X POST https://streamhub.digitalhub.com.ar/api/v1/apps \
  -H "Authorization: Bearer $STREAMHUB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"live","displayName":"Live","roomPrefix":"live"}'
Signed webhooks HMAC-SHA256
// Every callback is a signed POST. Verify the HMAC-SHA256 over the raw body.
import crypto from 'node:crypto';

app.post('/streamhub', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.header('X-StreamHub-Signature');                 // "sha256=<hex>"
  const expected =
    'sha256=' + crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
  if (!sig || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
    return res.status(401).end();

  const evt = JSON.parse(req.body.toString('utf8'));              // { event, app, data }
  switch (evt.event) {
    case 'stream_started':   /* a publisher/ingress went live */  break;
    case 'vod_ready':        /* recording uploaded to your S3 */  break;
    case 'recording_failed': /* upload failed, local file kept */ break;
  }
  res.status(200).end();
});
Self-host in one command docker compose
# Open source — self-host it, or let us host it for you.
git clone <vision-media-server>       # repo: vision-media-server
cp .env.example .env                  # LiveKit keys, per-app S3, PUBLIC_BASE_URL
docker compose up -d                  # core + LiveKit + ingress/egress, HTTPS via Caddy

# Swagger / OpenAPI:  /api/v1/docs      Metrics:  /metrics      Health:  /api/v1/health

This is a tour, not the whole map — the full reference covers architecture, operations, testing and every environment variable. Explore it live in the OpenAPI docs, or read the streamhub-docs in the repo.

streamhub-adaptor

A lightweight WebRTC SDK — publish and subscribe in a few lines

@streamhub/adaptor is a lightweight JavaScript SDK for publishing and subscribing over WebRTC, built on livekit-client. A tiny constructor, a handful of methods and simple string callbacks — put a camera on air or play a room in just a few lines.

one import
import { StreamHubAdaptor } from "@streamhub/adaptor";

// A lightweight WebRTC client, built on livekit-client.
const adaptor = new StreamHubAdaptor({ /* config below */ });
Install npm
npm install @streamhub/adaptor livekit-client
import { StreamHubAdaptor } from "@streamhub/adaptor";

const adaptor = new StreamHubAdaptor({
  // StreamHub mints the LiveKit token for you (prefer a pre-minted token + wsUrl in prod)
  streamhubApiUrl:   "https://streamhub.digitalhub.com.ar/api/v1",
  appName:           "live",
  streamhubApiToken: STREAMHUB_TOKEN,        // dev only — mint server-side for production
  mediaConstraints:  { video: true, audio: true },
  localVideoId:      "localVideo",           // <video id="localVideo"> preview element
  callback: (info, obj) => {
    if (info === "initialized")        adaptor.joinRoom("demo", "camera-1");
    else if (info === "joinedTheRoom") adaptor.publish(obj.streamId);   // send cam + mic
    else if (info === "publish_started") console.log("on air");
  },
  callbackError: (err, msg) => console.warn(err, msg),
});
No build step? Drop in one tag IIFE · CDN
<!-- No build step? Drop in one script tag and you're ready. -->
<script src="https://streamhub.digitalhub.com.ar/sdk/streamhub-adaptor.global.js"></script>
<script>
  const viewer = new StreamHubAdaptor({ isPlayMode: true, /* ...config */ });
</script>
Embeddable player <iframe>
<!-- The mint call returns a ready-to-paste embed. Public player, no SDK needed. -->
<iframe
  src="https://streamhub.digitalhub.com.ar/embed/live/live-demo"
  width="640" height="360" frameborder="0"
  allow="autoplay; fullscreen; camera; microphone"
  allowfullscreen>
</iframe>

String callbacks

initialized, publish_started, newStreamAvailable, roomInformation, data_received…

Methods

joinRoom, publish, play, sendData, switchVideoCameraCapture, enableStats…

Device & bitrate control

swap camera or mic on the fly and tune bitrate per sender, live

Data channels

chat and reactions ride LiveKit DataPackets; canPublishData is granted on every token

LiveKit handles simulcast and adaptive streaming natively. For production, mint tokens server-side and pass token + wsUrl so the management token never reaches the browser.

In beta — try it free

Get started today: open source or managed

StreamHub is 100% open source and self-hostable — or, if you'd rather not run it, we host it for you. We're in beta, so you can try it free while we keep polishing.

Open source

Self-host it

Clone the repo and run your own media server on LiveKit. Recording to your S3, your apps, your rules. No lock-in.

  • Your infra, your S3
  • Docker or systemd + nginx
  • Webhooks + SDK included
We host it

We run it for you

Don't want to operate the infra? We hand you StreamHub managed, updated and monitored. You focus on streaming.

  • Zero DevOps
  • Updates and monitoring
  • Guided onboarding

Let's talk about your stream

Tell us your use case — low-latency WebRTC, RTMP/WHIP/RTSP ingest, recording to your own S3, restreaming to YouTube/Twitch or multi-tenant. We'll help you get going, self-hosted or managed.

Write to us

Questions, a use case, or want us to host it? Tell us.

We reply within 1–2 business days.