openvibers/openvibe.live SETUP.md

SETUP.md

main 9.4 KB · 181 lines · markdown

1# OpenVibe.Live Setup
2
3This document describes the OpenVibe.Live runtime setup, local development, and its integration points with the other OpenVibe services.
4
5## Architecture at a glance
6
7OpenVibe.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:
8
9- **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).
10- **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`.
11
12Live 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.
13
14The 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`.
15
16## Prerequisites
17
18- Node.js 18 or later, npm.
19- FFmpeg (live thumbnails, frame extraction, AI jobs).
20- A running **OpenVibe.Network** instance (auth + wallet).
21- A running **OpenVibe.Media** instance (VODs/clips/pastes) — Live boots without it, but media features return 502 until it's up.
22- Linux is recommended for production (`mediasoup` and `node-media-server` are most reliable there).
23
24## Install dependencies
25
26```bash
27npm install
28```
29
30The shared package resolves from `node_modules/openvibe-shared` (the pinned release) — no external workspace layout needed.
31
32## Environment configuration
33
34Copy the environment template into `.env` (production: `/etc/openvibe/live.env`, mode 0600):
35
36```bash
37cp .env.example .env
38```
39
40### Required values
41
42- `BASE_URL` — public URL used by the browser client, e.g. `http://localhost:3000`.
43- `JWT_SECRET` — app-specific secret for Live's own JWT operations.
44- `OV_NETWORK_URL` — public SSO issuer (default `https://openvibe.network`).
45- `OV_NETWORK_INTERNAL_URL` — internal Network base (default `http://127.0.0.1:4000`).
46- `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).
47- `OV_NETWORK_PUBLIC_KEY` — path to the Network RS256 public key (offline JWT verification).
48- `MEDIA_URL` — internal Media API base (default `http://127.0.0.1:4100`).
49- `MEDIA_PUBLIC_URL` — public Media host (default `https://openvibe.media`).
50- `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.
51- `MEDIA_EVENTS_SECRET` — the secret of Live's OpenVibe.Events subscriptions to Media's outcomes (`scripts/subscribe-media-events.js`).
52
53#### Public key for token verification
54
55OpenVibe.Live verifies RS256 tokens from OpenVibe.Network with openvibe-sdk/auth (`createNetworkKeys`), using the first
56key file that exists:
57
581. the path in the `OV_NETWORK_PUBLIC_KEY` environment variable;
592. `<DATA_DIR>/keys/openvibe-tools-public.pem`;
603. `/opt/openvibe/openvibe-tools/data/keys/public.pem`.
61
62With none of them, Live verifies against Network's JWKS (`<OV_NETWORK_INTERNAL_URL>/api/.well-known/jwks`), loaded at boot
63and kept fresh, and follows a key rotation on the first token that names a new key. `/api/ready` reports the
64`network_key` check either way. A key file pins one key: after Network rotates its key, replace the file.
65
66## Database
67
68Live runs on PostgreSQL (since 2026-10-08). In production, OpenVibe.Host's data role creates the database and roles
69(`sudo ovhost data provision live`) and writes `DATABASE_URL` (the pooled runtime role, through PgBouncer) and
70`DATABASE_DIRECT_URL` (the owner, for migrations) into the env file; the release applies `migrations/` at boot.
71
72In development, leave `DATABASE_URL` unset: Live opens an embedded PGlite database under `DATA_DIR` and migrates it.
73Nothing to initialize by hand.
74
75## Storage directories
76
77The server writes Live-local state under `data/`:
78
79- `data/live-thumbs` — ephemeral live-stream thumbnails
80- `data/emotes`, `data/avatars`, `data/offline`
81- `data/media/cache` — song-request (watch-party) downloads
82- `data/keys`
83
84VOD/clip/paste **files** live in OpenVibe.Media's storage, not here.
85
86## Local development setup
87
881. Start OpenVibe.Network locally (port 4000) and OpenVibe.Media (port 4100).
892. Configure `.env`:
90
91```env
92PORT=3000
93HOST=0.0.0.0
94NODE_ENV=development
95BASE_URL=http://localhost:3000
96OV_NETWORK_URL=http://localhost:4000
97OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000
98OV_NETWORK_PUBLIC_KEY=./data/keys/openvibe-network-public.pem
99MEDIA_URL=http://127.0.0.1:4100
100MEDIA_PUBLIC_URL=http://127.0.0.1:4100
101MEDIA_APP_ID=live
102```
103
1043. Run `npm run dev` (without `DATABASE_URL`, Live migrates an embedded PGlite database under `DATA_DIR`).
105
106Network's `local-dev` bootstrap seeds the `live` OAuth client with `http://localhost:3000/api/auth/callback`.
107
108## Admin/bootstrap behavior
109
110On startup, the server:
111
112- refreshes URL registry values from OpenVibe.Network (needs `OV_NETWORK_INTERNAL_URL` + `OV_OAUTH_CLIENT_SECRET`).
113- initializes the database and schema.
114- seeds/refreshes built-in themes (default theme slug: `vibe`).
115- creates an admin user from `ADMIN_USERNAME` / `ADMIN_PASSWORD` if no admin exists (dev defaults `admin` / `changeme123`).
116
117## Protocol-specific notes
118
119### Recording (all protocols)
120
121Server-side recording is delegated to OpenVibe.Media:
122
123- **RTMP** — on publish, Live creates a VOD in Media and asks it to pull `rtmp://127.0.0.1:1935/live/<key>`.
124- **WebRTC/WHIP** — Live creates a VOD, requests RTP ingest ports from Media (UDP 12000-12199), and points mediasoup PlainRtpTransports at them.
125- **Browser MediaRecorder** — chunk uploads to `/api/vods/stream/:id/chunk` are forwarded to Media's chunks endpoints.
126- **JSMPEG** — not recorded (no Media ingest for mpeg-ts push).
127
128Completion arrives as `media.vod.ready` / `media.clip.ready` events over OpenVibe.Events.
129
130### WebRTC / mediasoup
131
132- `MEDIASOUP_LISTEN_IP`, `MEDIASOUP_ANNOUNCED_IP`, `MEDIASOUP_MIN_PORT` / `MEDIASOUP_MAX_PORT`, `WEBRTC_PORT`.
133- `TURN_URL` / `TURN_USERNAME` / `TURN_CREDENTIAL` — required in production for reliable NAT traversal (default `turn:turn.openvibe.live`).
134- Viewer media is SFU-only (mediasoup); there is no peer-to-peer fallback.
135
136### WHIP
137
138- `WHIP_PUBLIC_URL` — public ingest URL for WHIP (`https://whip.openvibe.live` in production).
139- `WHIP_PUBLIC_URL_ENABLED` — boolean to enable or disable WHIP.
140
141### RTMP
142
143- `RTMP_PORT` (1935), `RTMP_CHUNK_SIZE`.
144- `RTMP_HOST` — public ingest hostname shown to streamers (default `ingest.openvibe.live` → `rtmp://ingest.openvibe.live/live`).
145
146### JSMPEG
147
148- `JSMPEG_VIDEO_PORT`, `JSMPEG_AUDIO_PORT`, `JSMPEG_PUBLIC_URL` (TLS relay ports 9710-9789 via nginx stream in production).
149
150### Optional production settings
151
152- `PAYPAL_CLIENT_ID`, `PAYPAL_CLIENT_SECRET`, `PAYPAL_MODE` for Vibes cashout (Vibes stay Live-local).
153- `LIVE_THUMBS_PATH` for the live thumbnail directory.
154
155## Troubleshooting
156
157- **Auth fails**: `OV_NETWORK_PUBLIC_KEY` missing/invalid, or Network unreachable.
158- **Invalid redirect_uri**: local callback URIs not registered on the `live` OAuth client in Network.
159- **VOD/clip/paste endpoints return 502**: OpenVibe.Media is down, `MEDIA_URL` is wrong, or Live's service token lacks the `media.object.*` grants.
160- **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).
161- **OpenCoins balance always 0 / spends fail**: `OV_NETWORK_INTERNAL_URL`/`OV_OAUTH_CLIENT_SECRET` wrong, or the user has no linked Network account.
162- **CORS rejects browser traffic**: `BASE_URL` set to localhost in production.
163- **WebRTC fails**: `mediasoup` could not initialize or TURN is not configured.
164- **RTMP fails to start**: port conflict on `RTMP_PORT`.
165
166### How to verify local startup
167
1681. Run `npm run dev`.
1692. Confirm the server logs show `HTTP server` and WebSocket endpoints.
1703. Confirm `Effective BASE_URL` and `Effective OV_NETWORK_URL` are correct.
1714. Confirm `/api/ready` reports the database check `ok` (the release migrated it at boot).
1725. `curl http://localhost:3000/api/health` returns `{"status":"ok", ...}`.
173
174## What this setup does not cover
175
176- production Nginx / Cloudflare deployment (see `deploy/`).
177- real TLS certificate configuration.
178- the OpenVibe.Media / OpenVibe.Network services themselves.
179
180For stream-specific guidance, see `docs/broadcasting.md`.
181