vibe-live docs

Choosing and swapping engines

vibe-live runs with one of three media engines. The app, its accounts, channels, stream keys, chat, federation and settings are the same with any of them; what changes is what carries the video, and a few things only some engines can do.

What each gives

Built-in OvenMediaEngine LiveKit
Image ffmpeg-<version> <version> (the default) livekit-<version>, or compose.livekit.yaml
Latency in the browser seconds (HLS); sub-second with WebRTC turned on sub-second (WebRTC, LL-HLS) sub-second (WebRTC)
Go live from the browser with WebRTC turned on yes yes
OBS and other encoders RTMP (WHIP where the Go Live page offers it) RTMP and WHIP RTMP
Chromecast yes yes yes, with Egress
Seeking through a live stream, from its start (admin can turn off) yes -- a copy of the source yes -- the largest HLS rendition OvenMediaEngine makes, copied by the app yes, with Egress -- one encode per live channel (details)
Past broadcasts (admin allows, streamer opts in) yes -- the source as sent, copied yes -- the largest HLS rendition OvenMediaEngine makes, copied by the app yes, with Egress -- one encode per recorded channel
Qualities (VIBE_LIVE_RENDITIONS) yes, each encoded only while watched yes in the image; a separate OvenMediaEngine needs vibe-live ome-vhost yes, with Egress
Heaviest part ffmpeg in the app OvenMediaEngine Egress
Extra configuration none; VIBE_LIVE_WEBRTC_UDP_PORT for WebRTC none in the image a key pair
Runs as root uid 10001 since 0.16.0 -- /data must be its (upgrading) root

The ports are the same for all three: 80 and 443 for the site, 1936 for RTMP, 10000/udp and 3478/tcp for WebRTC. Changing engine never changes the router.

The app also listens on 1937/tcp, never published: the forwarder the engine pushes a multistream (Twitch, YouTube) through, re-published by the app over RTMPS (VIBE_LIVE_FORWARD_LISTEN_ADDR, VIBE_LIVE_FORWARD_URL, loopback by default). OvenMediaEngine pushes it only with a Push publisher and AAC in its bypass profile, which the bundled configuration has (engine v0.7.0); an OvenMediaEngine run with its own VHost.xml needs both -- the 0.45.1 changelog entry says what to add.

flowchart LR
  EN["Encoders"] -->|"RTMP 1936, WHIP 443"| INST
  BR["Browsers"] -->|"site, HLS, thumbnails: 443"| INST
  subgraph INST["Your instance: the same ports whatever the engine"]
    APP["vibe-live<br/>accounts, keys, chat, federation, settings"] --> SEL{"VIBE_LIVE_ENGINE"}
    SEL --> BI["builtin<br/>ffmpeg in the app"]
    SEL --> OME["ome<br/>OvenMediaEngine"]
    SEL --> LK["livekit<br/>LiveKit, Ingress, Egress"]
  end
  INST -.->|"WebRTC media<br/>10000/udp or 3478/tcp"| BR

Only the engine changes in a swap; everything in the vibe-live box stays exactly as it is.

Rules of thumb: the built-in engine for the smallest footprint and the fewest moving parts, OvenMediaEngine for the lowest latency with the least setup, LiveKit if you already run it or want its ecosystem.

Choosing

VIBE_LIVE_ENGINE names it: builtin, ome or livekit. Left unset, the app infers it from what is configured -- any LiveKit setting means livekit (and half of LiveKit's settings is refused at start, naming what is missing), OvenMediaEngine backend URLs mean ome, neither with ffmpeg present means builtin -- which is what lets each image work with no extra setting. Set it explicitly anyway once you have chosen: an explicit engine refuses to start with a second engine's settings beside it, instead of quietly picking one.

Swapping

A swap is a restart, never a switch under a live stream: the engine holds every publisher and viewer connection.

  1. Pick a quiet moment. Live streams end at the restart; streamers reconnect afterwards, viewers' players retry on their own.
  2. Keep the data. The database (/data, or MariaDB) and every secret stay exactly as they are -- nothing about accounts, keys or federation depends on the engine.
  3. Change the image (or compose file) to the engine's, from the table above. With compose: compose.yaml is OvenMediaEngine, compose.livekit.yaml is LiveKit; for the built-in engine use the ffmpeg- image in place of the default one.
  4. Change the engine's settings: set VIBE_LIVE_ENGINE to the new one, and remove the old engine's variables -- VIBE_LIVE_OME_* when leaving OvenMediaEngine, VIBE_LIVE_LIVEKIT_* when leaving LiveKit. Leaving them is what an explicit engine refuses to start over. Add the new engine's (see its page: built-in, LiveKit, OvenMediaEngine).
  5. Start it and check: the Media engine section of the admin page shows the new engine and what it can do, and scripts/validate-setup.sh https://your.instance checks the path end to end.

Streamers keep their stream key and server address -- RTMP is always the app's port 1936. The only visible difference to them is Go Live from the browser, which some engine setups do not offer.

Federation between different engines

Instances on different engines federate normally. A viewer here watching a stream from an instance on another engine is handed that instance's own playback (a LiveKit token only it can mint, for instance), so every combination works.

Diagrams drawn by Mermaid (MIT license).