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.
- Pick a quiet moment. Live streams end at the restart; streamers reconnect afterwards, viewers' players retry on their own.
- 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. - Change the image (or compose file) to the engine's, from the table
above. With compose:
compose.yamlis OvenMediaEngine,compose.livekit.yamlis LiveKit; for the built-in engine use theffmpeg-image in place of the default one. - Change the engine's settings: set
VIBE_LIVE_ENGINEto 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). - 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.instancechecks 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).