openvibers/openvibe.live .env.example
.env.example
| 1 | # OpenVibe.Live Configuration |
| 2 | # Copy this to .env and fill in your values. |
| 3 | # Production env file lives at /etc/openvibe/live.env (mode 0600). |
| 4 | |
| 5 | # Platform Admin — username of the site owner (applied on first setup only) |
| 6 | ADMIN_USERNAME=admin |
| 7 | ADMIN_PASSWORD=changeme123 |
| 8 | |
| 9 | # Home-page "Star of OpenVibe" spotlight — a username. The `star_streamer` site setting |
| 10 | # (admin settings API) overrides this. Non-English streamers get their bio auto-translated. |
| 11 | # STAR_STREAMER=JapaneseOldGuy |
| 12 | |
| 13 | # Multilingual whisper.cpp model for non-English streamers (chat + live captions + timeline). |
| 14 | # The default *.en models can only emit English. Download e.g. ggml-base.bin / ggml-small.bin |
| 15 | # (no ".en") into ~/whisper.cpp/models and point this at it. Without it, non-English |
| 16 | # channels keep using the English model and live captions stay hidden. |
| 17 | # WHISPER_MODEL_MULTI=/home/openvibe/whisper.cpp/models/ggml-small.bin |
| 18 | |
| 19 | # Speech-to-text engine for English and 24 other European languages: NVIDIA Parakeet TDT 0.6B v3 through |
| 20 | # whisper.cpp's parakeet-cli (more accurate than whisper base.en and fast enough for live on 4 cores). Used |
| 21 | # when both files exist; other languages, and any Parakeet failure, go to whisper. ASR_ENGINE=whisper forces whisper. |
| 22 | # Model: https://huggingface.co/ggml-org/parakeet-GGUF (ggml-parakeet-tdt-0.6b-v3-q8_0.bin). |
| 23 | # PARAKEET_BIN=/home/openvibe/whisper.cpp/build/bin/parakeet-cli |
| 24 | # PARAKEET_MODEL=/home/openvibe/whisper.cpp/models/ggml-parakeet-tdt-0.6b-v3-q8_0.bin |
| 25 | # ASR_ENGINE=whisper |
| 26 | |
| 27 | # OpenVibe.AI (roadmap Wave 13, WS-O task 2). Every AI call Live makes (chat AI, moments, paste/frame |
| 28 | # analysis, overviews, translation, recaps, slogans, arena, AI viewers) is a workflow run on the AI |
| 29 | # service, with a service token for audience openvibe.ai (grants ai.run.create, ai.run.read and |
| 30 | # ai.credential.manage for client `live`). Provider keys, a streamer's own included, live in the AI |
| 31 | # service; Live calls a provider only to test a key a streamer typed and has not saved yet. The admin |
| 32 | # ai_enabled switch and the local daily cap still apply to other AI workflows. Live stream transcription stays here. |
| 33 | # AI_SERVICE=off turns AI off entirely. |
| 34 | #AI_SERVICE=off |
| 35 | #OV_AI_INTERNAL_URL=http://127.0.0.1:4700 |
| 36 | # Finished VOD/clip analysis: local (current frame/whisper path) or ai (one media.analyze run). |
| 37 | #LIVE_MEDIA_ANALYSIS=local |
| 38 | # How long one call waits for media.analyze before re-joining the run 15 minutes later (ms). |
| 39 | #LIVE_MEDIA_ANALYSIS_WAIT_MS=60000 |
| 40 | |
| 41 | # Server |
| 42 | PORT=3000 |
| 43 | HOST=0.0.0.0 |
| 44 | NODE_ENV=development |
| 45 | BASE_URL=http://localhost:3000 |
| 46 | |
| 47 | # JWT Secret (generate a strong random string) |
| 48 | JWT_SECRET=change-me-to-a-random-secret-at-least-32-chars |
| 49 | |
| 50 | # Database |
| 51 | # Production requires both URLs. Development without DATABASE_URL uses PGlite under DATA_DIR. |
| 52 | # DATABASE_URL=postgres://live_runtime:password@localhost:5432/ov_live |
| 53 | # DATABASE_DIRECT_URL=postgres://live_owner:password@localhost:5432/ov_live |
| 54 | # Every file Live writes lives under one data directory (default ./data, relative to the working |
| 55 | # directory). The *_PATH variables below still move single locations (server/paths.js). |
| 56 | # DATA_DIR=./data |
| 57 | |
| 58 | # Restore-drill mode, set only by `ovhost drill live` (OpenVibe.Host docs/restore-drills.md): reads |
| 59 | # only from a restored copy; refuses to start unless DATA_DIR is outside the checkout, |
| 60 | # HOST is loopback and PORT is not 3000. Starts no jobs, sockets or listeners but its HTTP port and |
| 61 | # makes no outbound connection (server/drill.js). |
| 62 | # LIVE_DRILL=1 |
| 63 | |
| 64 | # ── OpenVibe.Network (SSO provider + OpenCoins wallet + URL registry) ───────── |
| 65 | # Public base of the identity provider (issuer for RS256 JWTs) |
| 66 | OV_NETWORK_URL=https://openvibe.network |
| 67 | # Internal (server-to-server) base — wallet API + /internal/* endpoints |
| 68 | OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000 |
| 69 | # OAuth client credentials (client id `live` is seeded in the Network DB) |
| 70 | OV_OAUTH_CLIENT_ID=live |
| 71 | OV_OAUTH_CLIENT_SECRET= |
| 72 | # OpenVibe.Events (durable events): stream lifecycle is published through Live's outbox with the |
| 73 | # OAuth client above (grant events.event.publish). Unset = off. EVENTS_PUBLISH=off also disables it. |
| 74 | #EVENTS_URL=http://127.0.0.1:4300 |
| 75 | # Go-live notifications come only from Network's live.stream.started consumer (compatibility register C-85). |
| 76 | |
| 77 | # OpenRestream (roadmap Wave 7): the ingest/restream authority. Unset = off, and every stream slot |
| 78 | # is ingested by Live exactly as before. When set, an admin can switch one slot at a time |
| 79 | # (PUT /api/admin/openre/managed/:id/ingest-authority); RTMP, WHIP and JSMPEG move with it. Live's service principal |
| 80 | # (the OAuth client above) needs openre.stream.read, openre.stream.write, openre.key.rotate and |
| 81 | # openre.session.read on audience openvibe.openre. |
| 82 | #OPENRE_URL=http://127.0.0.1:4500 |
| 83 | #OPENRE_PUBLIC_URL=https://openre.stream |
| 84 | # Secret of Live's OpenVibe.Events subscription to openre.session.* (endpoint |
| 85 | # http://127.0.0.1:3000/internal/openre-events); sessions are mirrored into `streams` from it. |
| 86 | #OPENRE_EVENTS_SECRET= |
| 87 | # Path to the Network's RS256 public key (offline JWT verification) |
| 88 | #OV_NETWORK_PUBLIC_KEY=./data/keys/openvibe-network-public.pem |
| 89 | |
| 90 | # ── Per-actor limits on API writes (server/net/actor-limits.js, roadmap WS-R task 4) ── |
| 91 | # Writes by a signed-in person or their hbt_ token, per minute and per hour; named routes (clips, pastes, follows, |
| 92 | # stream keys, uploads, comments, money, AI key tests) have tighter numbers of their own. Reads, signed-out writes |
| 93 | # and device traffic are not counted here (the per-address limits apply). |
| 94 | #LIVE_LIMITS_MINUTE=120 |
| 95 | #LIVE_LIMITS_HOUR=3000 |
| 96 | |
| 97 | # ── OpenVibe.Media (VODs / clips / pastes / thumbnails service) ─────────────── |
| 98 | # Internal API base (server-to-server, Bearer service token for openvibe.media) |
| 99 | MEDIA_URL=http://127.0.0.1:4100 |
| 100 | # Public serving base (playback/thumbnail/paste URLs handed to browsers) |
| 101 | MEDIA_PUBLIC_URL=https://openvibe.media |
| 102 | # Tenant id — the namespace Live's service token is scoped to |
| 103 | MEDIA_APP_ID=live |
| 104 | # Media (VOD/clip/paste) calls authenticate with Live's service token from |
| 105 | # OV_OAUTH_CLIENT_ID / OV_OAUTH_CLIENT_SECRET (audience openvibe.media, namespace live). |
| 106 | # Media outcomes (vod/clip ready or failed, storage alerts) arrive over OpenVibe.Events: the secret of |
| 107 | # Live's subscriptions to media.vod.* / media.clip.* / media.storage.* (endpoint |
| 108 | # http://127.0.0.1:3000/internal/media-events, created by scripts/subscribe-media-events.js; |
| 109 | # 32+ characters, openssl rand -hex 32). Without it Live receives no Media outcomes. |
| 110 | #MEDIA_EVENTS_SECRET= |
| 111 | |
| 112 | # ── RTMP ingest ─────────────────────────────────────────────────────────────── |
| 113 | RTMP_PORT=1935 |
| 114 | RTMP_CHUNK_SIZE=60000 |
| 115 | # Public ingest hostname shown to streamers (rtmp://<host>/live) |
| 116 | RTMP_HOST=ingest.openvibe.live |
| 117 | |
| 118 | # JSMPEG Relay |
| 119 | JSMPEG_VIDEO_PORT=9710 |
| 120 | JSMPEG_AUDIO_PORT=9711 |
| 121 | |
| 122 | # WebRTC / Mediasoup |
| 123 | MEDIASOUP_LISTEN_IP=0.0.0.0 |
| 124 | MEDIASOUP_ANNOUNCED_IP=127.0.0.1 |
| 125 | MEDIASOUP_MIN_PORT=10000 |
| 126 | MEDIASOUP_MAX_PORT=10100 |
| 127 | WEBRTC_PORT=4443 |
| 128 | |
| 129 | # TURN Server (coturn) — required for NAT traversal |
| 130 | TURN_URL=turn:turn.openvibe.live |
| 131 | TURN_USERNAME= |
| 132 | TURN_CREDENTIAL= |
| 133 | # Preferred: coturn `use-auth-secret` + `static-auth-secret=<this>` — every ICE list then carries a |
| 134 | # credential that expires after an hour instead of the static pair above. |
| 135 | TURN_AUTH_SECRET= |
| 136 | |
| 137 | # PayPal (for Vibes cashout — Vibes stay Live-local) |
| 138 | PAYPAL_CLIENT_ID= |
| 139 | PAYPAL_CLIENT_SECRET= |
| 140 | PAYPAL_MODE=sandbox |
| 141 | |
| 142 | # Vibes |
| 143 | MIN_CASHOUT_BUCKS=500 |
| 144 | ESCROW_HOLD_DAYS=14 |
| 145 | |
| 146 | # Live-local media state (VOD/clip/paste FILES live in OpenVibe.Media now) |
| 147 | # Ephemeral live-stream thumbnails |
| 148 | LIVE_THUMBS_PATH=./data/live-thumbs |
| 149 | # Song-request media cache (yt-dlp downloads for the watch-party queue) |
| 150 | # lives under ./data/media/cache — no env needed. |
| 151 | # Max size of a browser VOD upload forwarded to Media |
| 152 | MAX_VOD_SIZE_MB=2048 |
| 153 | |
| 154 | # Word Filter |
| 155 | UNSAFE_WORDS_PATH=./server/chat/unsafe-words.txt |
| 156 | |
| 157 | # Ops alerts (optional) — Discord-compatible webhook that receives storage alerts relayed |
| 158 | # from OpenVibe.Media (drain stalled / disk critical / recovered). Can also be set from the |
| 159 | # admin settings as `ops_alert_webhook_url`. |
| 160 | OPS_ALERT_WEBHOOK_URL= |
| 161 | |
| 162 | # Pastes are served by openvibe.community (Live 301s /p/:slug there and links straight to it) |
| 163 | OV_COMMUNITY_URL=https://openvibe.community |
| 164 | # Community's loopback API: pastes and VOD/clip comments, which are |
| 165 | # Community threads (server/comments-client.js; Live's service token needs community.comment.write |
| 166 | # and community.comment.moderate on openvibe.community) |
| 167 | OV_COMMUNITY_INTERNAL_URL=http://127.0.0.1:4200 |
| 168 | |
| 169 | # OpenVibe.Chat runs chat (/ws/chat and /api/chat|dm|tts|sounds; nginx sends them there). Live delivers its |
| 170 | # own chat producers (AI viewer lines, donations and alerts, relay and RobotStreamer chat, cards, moderation, |
| 171 | # cache hints, presence) through Chat's typed ingress /internal/chat/* and reads chat stats, queues and history |
| 172 | # from Chat (server/chat/chat-delivery.js, chat-reads.js; Live's principal needs chat.message.send, |
| 173 | # chat.event.publish, chat.moderation.write, chat.cache.invalidate, chat.presence.read and the chat.*.read |
| 174 | # capabilities for audience openvibe.chat). There is no switch: without OV_OAUTH_CLIENT_SECRET chat is inert. |
| 175 | OV_CHAT_INTERNAL_URL=http://127.0.0.1:4400 |
| 176 | # Bot panel embed (server/bot/): "1" lets a channel owner bind the channel to an OpenVibe.Bot robot |
| 177 | # (PUT /api/streams/channel/:username/bot) and adds bot_embed { enabled, robot_id, url } to the channel |
| 178 | # JSON; off, the route answers 404 and the JSON is unchanged. Live never calls Bot to bind: the robot |
| 179 | # owner's embed_public toggle in Bot decides what the embed shows. Turn-on order: Bot deployed with |
| 180 | # GET /panel/:id/embed and its BOT_EMBED_ORIGINS including this site's origins → set this → bind a channel. |
| 181 | #LIVE_BOT_EMBED=1 |
| 182 | # Bot's origin for the embed URL (<origin>/panel/<robot id>/embed): a bare https origin, or |
| 183 | # http://localhost* outside production; anything else falls back to the default with a warning. |
| 184 | #LIVE_BOT_URL=https://openvibe.bot |
| 185 | # Voice/video calls are OpenVibe.Chat's (no setting): nginx sends /ws/call and the call routes there, and Live |
| 186 | # creates/removes stream voice channels in Chat on go-live and stream end (server/streaming/calls-authority.js). |
| 187 | |
| 188 | # OpenVibe.Billing is the money ledger (since 2026-10-17; ADR-012): Live calls it for checkouts, donations, cashouts, |
| 189 | # recycling, subscriptions, balances and entitlements with its service token (audience openvibe.billing). There is no |
| 190 | # other mode (BILLING_AUTHORITY is no longer read). |
| 191 | OV_BILLING_INTERNAL_URL=http://127.0.0.1:4600 |
| 192 | OV_QUEST_INTERNAL_URL=http://127.0.0.1:4980 |
| 193 | OV_BILLING_PUBLIC_URL=https://billing.openvibe.network |
| 194 | |
| 195 | # Cosmetics live in OpenVibe.Inventory (ADR-054 §8): live.* items issued by service:live, Live's item ids as aliases. |
| 196 | # Live reads and writes them with its service token (audience openvibe.inventory) acting for the person. |
| 197 | #INVENTORY_URL=http://127.0.0.1:5030 |
| 198 | # OV_BILLING_TIMEOUT_MS=8000 |
| 199 | OV_BENCH_INTERNAL_URL=http://127.0.0.1:5230 |
| 200 | |
| 201 | # The Companion extension's side panel frames /embed/agent: set this to the Chrome Web Store id once the extension |
| 202 | # is published (exactly chrome-extension:// + 32 letters a-p; comma-separate several; anything else is ignored). |
| 203 | #AGENT_EMBED_EXTENSION_ORIGINS=chrome-extension://bjcjcfcecpkkmfndegkjekoipdmbgakd |
| 204 |