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:
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=demo → live-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).
Ingest options
Section titled “Ingest options”| 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.
Which protocol does each platform use?
Section titled “Which protocol does each platform use?”| 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.
Rules of thumb
Section titled “Rules of thumb”- 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/playURL. Sub-second, no per-camera relay process, no transcoding. - Mass playback / passive viewers / embeds → HLS (
/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.
Real endpoint shapes
Section titled “Real endpoint shapes”| 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) |