openvibers/openvibe.live SETUP.md
SETUP.md
OpenVibe.Live Setup
This document describes the OpenVibe.Live runtime setup, local development, and its integration points with the other OpenVibe services.
Architecture at a glance
OpenVibe.Live (port 3000) is the streaming front — ingest (RTMP / WHIP / WebRTC / JSMPEG), chat, channels, monetization (Vibes), moderation, and the SPA. Two sibling services do heavy lifting:
- OpenVibe.Network (
openvibe.network, port 4000) — SSO/OAuth2 identity provider (client idlive), RS256 JWTs, URL registry, notifications, and the network-wide OpenCoins wallet. Live calls the wallet server-to-server viaOV_NETWORK_INTERNAL_URLwith its service token (client credentials). - OpenVibe.Media (
openvibe.media, port 4100) — owns VODs, clips, pastes, thumbnails, and file storage (Media API v1). Live records streams by pointing Media at its ingest (RTMP pull / RTP ports 12000-12199), proxies the SPA's/api/vods,/api/clips,/api/pastes,/api/thumbnailscalls to it (server/media-client.js), 302-redirects file payloads toMEDIA_PUBLIC_URL, and receivesvod.ready/clip.readyoutcomes as OpenVibe.Events deliveries atPOST /internal/media-events.
Live keeps locally, in its PostgreSQL database: users/streams/channel state, Vibes (PayPal tipping/cashout), channel points, comments, stream memories + AI state for Media-hosted vods/clips (vod_ai_state / clip_ai_state), ephemeral live thumbnails, and the song-request queue.
The shared package is a pinned OpenVibe.Shared release ("openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/vX.Y.Z" in package.json), installed into node_modules by npm ci (the host needs outbound HTTPS to codeload.github.com) and served at /shared/*. Change it in OpenVibe.Shared and bump the tag; never edit node_modules.
Prerequisites
- Node.js 18 or later, npm.
- FFmpeg (live thumbnails, frame extraction, AI jobs).
- A running OpenVibe.Network instance (auth + wallet).
- A running OpenVibe.Media instance (VODs/clips/pastes) — Live boots without it, but media features return 502 until it's up.
- Linux is recommended for production (
mediasoupandnode-media-serverare most reliable there).
Install dependencies
npm install
The shared package resolves from node_modules/openvibe-shared (the pinned release) — no external workspace layout needed.
Environment configuration
Copy the environment template into .env (production: /etc/openvibe/live.env, mode 0600):
cp .env.example .env
Required values
BASE_URL— public URL used by the browser client, e.g.http://localhost:3000.JWT_SECRET— app-specific secret for Live's own JWT operations.OV_NETWORK_URL— public SSO issuer (defaulthttps://openvibe.network).OV_NETWORK_INTERNAL_URL— internal Network base (defaulthttp://127.0.0.1:4000).OV_OAUTH_CLIENT_ID/OV_OAUTH_CLIENT_SECRET— OAuth client (live). The same client mints Live's service tokens for Network's/internal/*endpoints (client credentials; the sharedINTERNAL_API_KEYis retired).OV_NETWORK_PUBLIC_KEY— path to the Network RS256 public key (offline JWT verification).MEDIA_URL— internal Media API base (defaulthttp://127.0.0.1:4100).MEDIA_PUBLIC_URL— public Media host (defaulthttps://openvibe.media).MEDIA_APP_ID(live) — Live's Media tenant. Media calls authenticate with Live's service token (OV_OAUTH_CLIENT_ID/OV_OAUTH_CLIENT_SECRET, audienceopenvibe.media, namespacelive), which needs themedia.object.read,media.object.list,media.object.uploadandmedia.object.deletegrants.MEDIA_EVENTS_SECRET— the secret of Live's OpenVibe.Events subscriptions to Media's outcomes (scripts/subscribe-media-events.js).
Public key for token verification
OpenVibe.Live verifies RS256 tokens from OpenVibe.Network with openvibe-sdk/auth (createNetworkKeys), using the first
key file that exists:
- the path in the
OV_NETWORK_PUBLIC_KEYenvironment variable; <DATA_DIR>/keys/openvibe-tools-public.pem;/opt/openvibe/openvibe-tools/data/keys/public.pem.
With none of them, Live verifies against Network's JWKS (<OV_NETWORK_INTERNAL_URL>/api/.well-known/jwks), loaded at boot
and kept fresh, and follows a key rotation on the first token that names a new key. /api/ready reports the
network_key check either way. A key file pins one key: after Network rotates its key, replace the file.
Database
Live runs on PostgreSQL (since 2026-10-08). In production, OpenVibe.Host's data role creates the database and roles
(sudo ovhost data provision live) and writes DATABASE_URL (the pooled runtime role, through PgBouncer) and
DATABASE_DIRECT_URL (the owner, for migrations) into the env file; the release applies migrations/ at boot.
In development, leave DATABASE_URL unset: Live opens an embedded PGlite database under DATA_DIR and migrates it.
Nothing to initialize by hand.
Storage directories
The server writes Live-local state under data/:
data/live-thumbs— ephemeral live-stream thumbnailsdata/emotes,data/avatars,data/offlinedata/media/cache— song-request (watch-party) downloadsdata/keys
VOD/clip/paste files live in OpenVibe.Media's storage, not here.
Local development setup
- Start OpenVibe.Network locally (port 4000) and OpenVibe.Media (port 4100).
- Configure
.env:
PORT=3000
HOST=0.0.0.0
NODE_ENV=development
BASE_URL=http://localhost:3000
OV_NETWORK_URL=http://localhost:4000
OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000
OV_NETWORK_PUBLIC_KEY=./data/keys/openvibe-network-public.pem
MEDIA_URL=http://127.0.0.1:4100
MEDIA_PUBLIC_URL=http://127.0.0.1:4100
MEDIA_APP_ID=live
- Run
npm run dev(withoutDATABASE_URL, Live migrates an embedded PGlite database underDATA_DIR).
Network's local-dev bootstrap seeds the live OAuth client with http://localhost:3000/api/auth/callback.
Admin/bootstrap behavior
On startup, the server:
- refreshes URL registry values from OpenVibe.Network (needs
OV_NETWORK_INTERNAL_URL+OV_OAUTH_CLIENT_SECRET). - initializes the database and schema.
- seeds/refreshes built-in themes (default theme slug:
vibe). - creates an admin user from
ADMIN_USERNAME/ADMIN_PASSWORDif no admin exists (dev defaultsadmin/changeme123).
Protocol-specific notes
Recording (all protocols)
Server-side recording is delegated to OpenVibe.Media:
- RTMP — on publish, Live creates a VOD in Media and asks it to pull
rtmp://127.0.0.1:1935/live/<key>. - WebRTC/WHIP — Live creates a VOD, requests RTP ingest ports from Media (UDP 12000-12199), and points mediasoup PlainRtpTransports at them.
- Browser MediaRecorder — chunk uploads to
/api/vods/stream/:id/chunkare forwarded to Media's chunks endpoints. - JSMPEG — not recorded (no Media ingest for mpeg-ts push).
Completion arrives as media.vod.ready / media.clip.ready events over OpenVibe.Events.
WebRTC / mediasoup
MEDIASOUP_LISTEN_IP,MEDIASOUP_ANNOUNCED_IP,MEDIASOUP_MIN_PORT/MEDIASOUP_MAX_PORT,WEBRTC_PORT.TURN_URL/TURN_USERNAME/TURN_CREDENTIAL— required in production for reliable NAT traversal (defaultturn:turn.openvibe.live).- Viewer media is SFU-only (mediasoup); there is no peer-to-peer fallback.
WHIP
WHIP_PUBLIC_URL— public ingest URL for WHIP (https://whip.openvibe.livein production).WHIP_PUBLIC_URL_ENABLED— boolean to enable or disable WHIP.
RTMP
RTMP_PORT(1935),RTMP_CHUNK_SIZE.RTMP_HOST— public ingest hostname shown to streamers (defaultingest.openvibe.live→rtmp://ingest.openvibe.live/live).
JSMPEG
JSMPEG_VIDEO_PORT,JSMPEG_AUDIO_PORT,JSMPEG_PUBLIC_URL(TLS relay ports 9710-9789 via nginx stream in production).
Optional production settings
PAYPAL_CLIENT_ID,PAYPAL_CLIENT_SECRET,PAYPAL_MODEfor Vibes cashout (Vibes stay Live-local).LIVE_THUMBS_PATHfor the live thumbnail directory.
Troubleshooting
- Auth fails:
OV_NETWORK_PUBLIC_KEYmissing/invalid, or Network unreachable. - Invalid redirect_uri: local callback URIs not registered on the
liveOAuth client in Network. - VOD/clip/paste endpoints return 502: OpenVibe.Media is down,
MEDIA_URLis wrong, or Live's service token lacks themedia.object.*grants. - VODs never leave "processing": Live's Events subscriptions to
media.*are missing orMEDIA_EVENTS_SECRETdoes not match them (Events shows the deliveries failing with 401). - OpenCoins balance always 0 / spends fail:
OV_NETWORK_INTERNAL_URL/OV_OAUTH_CLIENT_SECRETwrong, or the user has no linked Network account. - CORS rejects browser traffic:
BASE_URLset to localhost in production. - WebRTC fails:
mediasoupcould not initialize or TURN is not configured. - RTMP fails to start: port conflict on
RTMP_PORT.
How to verify local startup
- Run
npm run dev. - Confirm the server logs show
HTTP serverand WebSocket endpoints. - Confirm
Effective BASE_URLandEffective OV_NETWORK_URLare correct. - Confirm
/api/readyreports the database checkok(the release migrated it at boot). curl http://localhost:3000/api/healthreturns{"status":"ok", ...}.
What this setup does not cover
- production Nginx / Cloudflare deployment (see
deploy/). - real TLS certificate configuration.
- the OpenVibe.Media / OpenVibe.Network services themselves.
For stream-specific guidance, see docs/broadcasting.md.