Created 12 public docs derived from internal vault: - Setup guides: quick-start, server-configuration, livekit-setup, deployment - Networking: port-forwarding, tailscale - References: api, protocol, schema, client-architecture - Community: contributing, security Updated .gitignore to only exclude docs/brain/ (internal vault), allowing docs/ to be tracked. Updated README with expanded quick start, voice/video setup, networking ports, and doc links.
5.8 KiB
LiveKit Setup Guide
LiveKit is an open-source SFU (Selective Forwarding Unit) that handles real-time voice and video. OwnCord uses it instead of rolling its own WebRTC stack -- LiveKit handles all the hard parts (DTLS, ICE, codec negotiation, simulcast) while OwnCord manages permissions, state, and room lifecycle.
1. Get the LiveKit Binary
Download livekit-server for Windows from one of:
- GitHub releases: https://github.com/livekit/livekit/releases
- Grab the
livekit-server_*_windows_amd64.zipasset
- Grab the
- LiveKit website: https://livekit.io/ (Docs > Self Hosting)
Extract the binary somewhere permanent (e.g. C:\livekit\livekit-server.exe).
2. Server Configuration
LiveKit settings live in the voice: section of config.yaml:
voice:
livekit_api_key: "devkey"
livekit_api_secret: "owncord-dev-secret-key-min-32chars"
livekit_url: "ws://localhost:7880"
livekit_binary: "C:/livekit/livekit-server.exe"
quality: "medium"
| Field | Purpose | Default |
|---|---|---|
livekit_api_key |
Shared API key between OwnCord and LiveKit | "devkey" |
livekit_api_secret |
Shared secret for JWT signing (min 32 chars) | "owncord-dev-secret-key-min-32chars" |
livekit_url |
LiveKit WebSocket URL | ws://localhost:7880 |
livekit_binary |
Path to livekit-server binary. Empty = assume externally managed |
"" (disabled) |
quality |
Default voice quality preset | "medium" |
Environment variable overrides use the OWNCORD_ prefix: OWNCORD_VOICE_LIVEKIT_API_KEY, OWNCORD_VOICE_LIVEKIT_API_SECRET, etc.
Warning
: The server logs a warning at startup if you use the default dev key/secret. Always change these for production.
3. Ports and Firewall
| Port | Protocol | Purpose |
|---|---|---|
| 7880 | TCP (HTTP/WS) | LiveKit signaling (WebSocket + REST API) |
| 7881 | TCP | LiveKit internal RTC (TURN/TCP fallback) |
| 50000-60000 | UDP | Media transport (RTP audio/video) |
For LAN-only setups, ensure these ports are open on Windows Firewall. For remote access, forward these through your router or use Tailscale.
4. How the Companion Process Works
When livekit_binary is set, OwnCord manages LiveKit as a companion process:
- Config generation: OwnCord auto-generates
data/livekit.yamlwith the API key/secret, port 7880, and UDP range 50000-60000 - Process launch:
livekit-server --config data/livekit.yaml - Crash recovery: Exponential backoff restart (3s -> 6s -> 12s ... up to 60s), gives up after 10 consecutive rapid failures
- Health checks:
GET http://localhost:7880/verifies LiveKit is responding - Graceful shutdown: Stops the process when OwnCord shuts down (5s timeout before kill)
If livekit_binary is empty, OwnCord assumes LiveKit is managed externally (e.g. Docker, systemd, or manual start).
5. Token Flow
How a client joins voice:
Client OwnCord Server LiveKit Server
| | |
|-- voice_join (channel_id)-->| |
| |-- check CONNECT_VOICE |
| |-- persist to voice_states |
| |-- GenerateToken() |
|<-- voice_token ------------| |
| { token, url, | |
| direct_url } | |
| | |
|-- connect with JWT --------|-------------------------->|
|<--- media streams ----------|--------------------------|
Token details:
- Room name:
"channel-{channelID}" - Identity:
"user-{userID}" - TTL: 24 hours (refresh at 23h)
canPublishis derived from theSPEAK_VOICEpermissioncanSubscribeis always true- Client can request refresh via
voice_token_refresh(rate limited to 1/60s)
Client connection paths:
- Proxy path (
/livekit): Client connects through OwnCord's HTTPS server. Avoids mixed-content issues. - Direct URL (
ws://localhost:7880): Used when the client is on localhost.
6. Webhook Integration
LiveKit sends webhooks to POST /api/v1/livekit/webhook. The endpoint verifies the JWT and handles participant_left to clean up ghost voice states when a user disconnects from LiveKit without sending a voice_leave message.
7. Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| "voice not configured" error | LiveKit client failed to initialize | Check livekit_api_key and livekit_api_secret are set and secret is >= 32 chars |
| "failed to generate voice token" | API key/secret mismatch | Ensure config.yaml key/secret match what LiveKit is using |
| Voice connects but no audio | Firewall blocking UDP 50000-60000 | Open UDP port range in Windows Firewall |
"backend unavailable" from /livekit proxy |
LiveKit not running on port 7880 | Check livekit_binary path or start LiveKit manually |
| "too many rapid failures, giving up" in logs | LiveKit binary crashes on startup | Run livekit-server --config data/livekit.yaml manually to see errors |
| Mixed content / insecure WS error | Client using direct URL over HTTPS page | Client should use the /livekit proxy path |
GET /api/v1/livekit/health returns degraded |
LiveKit server not reachable | Verify LiveKit is running: curl http://localhost:7880 |
8. Production Checklist
- Change
livekit_api_keyfrom"devkey"to a random string - Change
livekit_api_secretto a random 32+ character string - Open firewall ports: 7880/TCP, 50000-60000/UDP
- If using ACME/manual TLS, ensure LiveKit proxy at
/livekitis working - Test voice by joining a voice channel from two clients
- Check
/api/v1/livekit/healthreturns{"status": "ok"}