openvibers/openvibe.live SETUP.md

SETUP.md

main 9.4 KB · 181 lines · markdown

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 id live), RS256 JWTs, URL registry, notifications, and the network-wide OpenCoins wallet. Live calls the wallet server-to-server via OV_NETWORK_INTERNAL_URL with 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/thumbnails calls to it (server/media-client.js), 302-redirects file payloads to MEDIA_PUBLIC_URL, and receives vod.ready / clip.ready outcomes as OpenVibe.Events deliveries at POST /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 (mediasoup and node-media-server are 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 (default https://openvibe.network).
  • OV_NETWORK_INTERNAL_URL — internal Network base (default http://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 shared INTERNAL_API_KEY is retired).
  • OV_NETWORK_PUBLIC_KEY — path to the Network RS256 public key (offline JWT verification).
  • MEDIA_URL — internal Media API base (default http://127.0.0.1:4100).
  • MEDIA_PUBLIC_URL — public Media host (default https://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, audience openvibe.media, namespace live), which needs the media.object.read, media.object.list, media.object.upload and media.object.delete grants.
  • 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:

  1. the path in the OV_NETWORK_PUBLIC_KEY environment variable;
  2. <DATA_DIR>/keys/openvibe-tools-public.pem;
  3. /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 thumbnails
  • data/emotes, data/avatars, data/offline
  • data/media/cache — song-request (watch-party) downloads
  • data/keys

VOD/clip/paste files live in OpenVibe.Media's storage, not here.

Local development setup

  1. Start OpenVibe.Network locally (port 4000) and OpenVibe.Media (port 4100).
  2. 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
  1. Run npm run dev (without DATABASE_URL, Live migrates an embedded PGlite database under DATA_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_PASSWORD if no admin exists (dev defaults admin / 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/chunk are 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 (default turn: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.live in 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 (default ingest.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_MODE for Vibes cashout (Vibes stay Live-local).
  • LIVE_THUMBS_PATH for the live thumbnail directory.

Troubleshooting

  • Auth fails: OV_NETWORK_PUBLIC_KEY missing/invalid, or Network unreachable.
  • Invalid redirect_uri: local callback URIs not registered on the live OAuth client in Network.
  • VOD/clip/paste endpoints return 502: OpenVibe.Media is down, MEDIA_URL is wrong, or Live's service token lacks the media.object.* grants.
  • VODs never leave "processing": Live's Events subscriptions to media.* are missing or MEDIA_EVENTS_SECRET does not match them (Events shows the deliveries failing with 401).
  • OpenCoins balance always 0 / spends fail: OV_NETWORK_INTERNAL_URL/OV_OAUTH_CLIENT_SECRET wrong, or the user has no linked Network account.
  • CORS rejects browser traffic: BASE_URL set to localhost in production.
  • WebRTC fails: mediasoup could not initialize or TURN is not configured.
  • RTMP fails to start: port conflict on RTMP_PORT.
How to verify local startup
  1. Run npm run dev.
  2. Confirm the server logs show HTTP server and WebSocket endpoints.
  3. Confirm Effective BASE_URL and Effective OV_NETWORK_URL are correct.
  4. Confirm /api/ready reports the database check ok (the release migrated it at boot).
  5. curl http://localhost:3000/api/health returns {"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.