Skip to content

Integrations overview

StreamHub is a management layer over a self-hosted LiveKit server, so the media plane is standard LiveKit/WebRTC, plus an RTMP ingress, a WHIP endpoint, an RTSP pull option, a direct WebSocket/MJPEG path for lightweight cameras, and HLS output for clients that can’t do WebRTC. This page is the map — pick a row, then follow its doc.

The one thing every WebRTC integration needs: a token

Section titled “The one thing every WebRTC integration needs: a token”

WebRTC clients (Android, iOS, native LiveKit, the browser SDK) connect with two values:

  • a wsUrl — the public LiveKit WebSocket, e.g. wss://media.example.com;
  • a token — a short-lived LiveKit join JWT.

You get both from one StreamHub call. Mint it server-side with your StreamHub API token — never ship the StreamHub Bearer token inside a mobile app or a device:

Terminal window
curl -s -X POST https://streamhub.example.com/api/v1/apps/live/tokens \
-H "Authorization: Bearer $STREAMHUB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"room":"demo","identity":"phone-42","canPublish":true,"canSubscribe":true,"ttl":"1h"}'
{
"data": {
"token": "<jwt>",
"app": "live",
"room": "live-demo",
"identity": "phone-42",
"wsUrl": "wss://media.example.com",
"playUrl": "https://streamhub.example.com/play/live/live-demo",
"embedUrl": "https://streamhub.example.com/embed/live/live-demo"
}
}

Your app then asks your own backend for { token, wsUrl } and feeds them to a LiveKit SDK. (room is namespaced under the app prefix: app live + room=demolive-demo.)

RTMP/HLS clients don’t need a token — they use the stream key returned by POST /apps/:app/ingress (push side) and a plain HLS URL (play side). ws-mjpeg clients use a wsk_ key (see ESP32-CAM ingest).

Method Direction Protocol Latency Best for
WebRTC publish push LiveKit SDK (browser/Android/iOS) or WHIP sub-second interactive publishing, calls, low-latency broadcast
RTMP push rtmp://<host>:1935/live/<streamKey> a few seconds OBS, drones, any RTMP-capable encoder, non-WebRTC devices
WHIP push WebRTC-over-HTTP ingest endpoint sub-second modern encoders/browsers that speak WHIP instead of a full SDK
RTSP pull pull StreamHub pulls from a reachable rtsp:// source a few seconds IP cameras already reachable from the server
WebSocket MJPEG push wss://…/ingest/ws, 1 JPEG frame per binary message sub-second, no relay ESP32-CAM and other microcontroller cameras — no H.264 encoder available

See the API reference for the full POST /apps/:app/ingress contract, and ESP32-CAM ingest for the WebSocket path.

Platform Publish (send) Play (receive) Protocol / SDK
Browser WebRTC WebRTC + HLS fallback streamhub-adaptor (built on livekit-client)
Android WebRTC WebRTC io.livekit:livekit-android (Kotlin)
iOS WebRTC WebRTC LiveKitClient via SPM (Swift)
C++ / native RTMP (recommended) or WebRTC FFI HLS ffmpeg/GStreamer → RTMP ingress; HLS for playback
ESP32-CAM direct WebSocket (wss://…/ingest/ws, one JPEG frame per message, no relay) MJPEG /live/<app>/<room>/mjpeg + /play (sub-second) wsk_ key + arduinoWebSockets
Any RTMP encoder (OBS, drones, etc.) RTMP rtmp://<host>:1935/live/<streamKey>
Any HLS player (Smart TV, VLC, video.js) HLS https://<domain>/hls/<app>/<room>/index.m3u8

See Mobile & native SDKs for Android/iOS/C++ details.

  • Real-time, two-way, low latency (calls, interactive publishing) → WebRTC SDK (Android/iOS/browser). Sub-second latency.
  • One-way push from a device/encoder that can’t do WebRTC (IP cameras, OBS, native C++) → RTMP ingress. A few seconds of latency.
  • Microcontroller cameras (ESP32-CAM / CCTV fleets) → direct WebSocket ingest (wss://…/ingest/ws, JPEG frames) with MJPEG playback on the same /play URL. Sub-second, no per-camera relay process, no transcoding.
  • Mass playback / passive viewers / embedsHLS (/hls/<app>/<room>/index.m3u8). Highest latency (roughly 3–15s depending on config) but works everywhere and scales behind a CDN.

A typical mixed setup: a camera or OBS pushes RTMP into a room, viewers watch over HLS, and a moderator joins the same room over WebRTC to talk back.

Thing Value
REST API base https://<domain>/api/v1
Mint a WebRTC token POST /apps/:app/tokens{ token, wsUrl, room, ... }
Create an RTMP/WHIP/URL ingress POST /apps/:app/ingress{ ingressId, url, streamKey, roomName }
RTMP publish URL rtmp://<media-host>:1935/live/<streamKey>
HLS playback https://<domain>/hls/<app>/<room>/index.m3u8
WS ingest key (ESP32) POST /apps/:app/ws-ingest{ streamKey: "wsk_…", wsUrl, mjpegUrl }
WS ingest publish (device) wss://<domain>/ingest/ws?app=<app>&room=<room> + Authorization: Bearer wsk_…
MJPEG playback (no transcode) https://<domain>/live/<app>/<room>/mjpeg (+ /frame.jpg for a single snapshot)