f1dbcd0f86
Adds the server side of scaling meetings past the ~5-peer mesh: - config.js: LIVEKIT_URL/API_KEY/API_SECRET + LIVEKIT_ENABLED flag. All optional; when unset the app keeps the built-in P2P mesh (fully additive, like push). - routes.js: GET /api/meetings/config (tells the client sfu on/off + wss url) and POST /api/meetings/token (mints a per-user, per-room LiveKit join token — hand-rolled HS256 JWT like the FCM/APNs tokens, no new dependency; secret stays server-side). - docker-compose.yml: optional livekit service (single-node, no Redis), keys injected via LIVEKIT_KEYS from the same .env; media over published UDP 50000-50100 + TCP 7881, signaling proxied by NPM. - livekit.yaml + .env.example documented. Client (mesh->LiveKit media swap, behind the flag) lands in phase 2. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
41 lines
1.9 KiB
JavaScript
41 lines
1.9 KiB
JavaScript
// Runtime config + filesystem paths. Reads process.env once at startup.
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const PUBLIC_DIR = path.join(__dirname, 'public');
|
|
const REC_DIR = path.join(__dirname, 'recordings');
|
|
const TRANS_DIR = path.join(__dirname, 'transcripts');
|
|
const UPLOADS_DIR = path.join(__dirname, 'uploads');
|
|
// Desktop installers + auto-update feed (latest.yml). Override with DOWNLOADS_DIR to point at a
|
|
// mounted volume in production; IT drops the electron-builder dist/ output here.
|
|
const DOWNLOADS_DIR = process.env.DOWNLOADS_DIR || path.join(__dirname, 'downloads');
|
|
try { fs.mkdirSync(REC_DIR, { recursive: true }); } catch (e) {}
|
|
try { fs.mkdirSync(TRANS_DIR, { recursive: true }); } catch (e) {}
|
|
try { fs.mkdirSync(UPLOADS_DIR, { recursive: true }); } catch (e) {}
|
|
try { fs.mkdirSync(DOWNLOADS_DIR, { recursive: true }); } catch (e) {}
|
|
|
|
// LiveKit SFU (scales meetings past the ~5-peer mesh ceiling). Entirely optional and config-gated:
|
|
// when LIVEKIT_URL/API_KEY/API_SECRET are all set the client uses LiveKit for meeting media; when
|
|
// they're unset the app falls back to the built-in P2P mesh, unchanged. The API secret is used
|
|
// ONLY server-side to mint per-user join tokens — it never reaches the browser.
|
|
const LIVEKIT_URL = process.env.LIVEKIT_URL || ''; // wss://livekit.bizgaze.com
|
|
const LIVEKIT_API_KEY = process.env.LIVEKIT_API_KEY || '';
|
|
const LIVEKIT_API_SECRET = process.env.LIVEKIT_API_SECRET || '';
|
|
const LIVEKIT_ENABLED = !!(LIVEKIT_URL && LIVEKIT_API_KEY && LIVEKIT_API_SECRET);
|
|
|
|
module.exports = {
|
|
PORT: process.env.PORT || 8090,
|
|
HTTPS_PORT: process.env.HTTPS_PORT || 8443,
|
|
LIVEKIT_URL,
|
|
LIVEKIT_API_KEY,
|
|
LIVEKIT_API_SECRET,
|
|
LIVEKIT_ENABLED,
|
|
PUBLIC_DIR,
|
|
REC_DIR,
|
|
TRANS_DIR,
|
|
UPLOADS_DIR,
|
|
DOWNLOADS_DIR,
|
|
SESSION_TTL: 1000 * 60 * 60 * 24, // 24h access-token / cookie lifetime
|
|
REFRESH_TTL: 1000 * 60 * 60 * 24 * 90, // 90d refresh-token lifetime (native clients)
|
|
};
|