Files
OwnCord/docs/livekit-setup.md
T
jevb ec5775910f docs: add public documentation for contributors and users
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.
2026-03-30 22:31:06 +02:00

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:

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:

  1. Config generation: OwnCord auto-generates data/livekit.yaml with the API key/secret, port 7880, and UDP range 50000-60000
  2. Process launch: livekit-server --config data/livekit.yaml
  3. Crash recovery: Exponential backoff restart (3s -> 6s -> 12s ... up to 60s), gives up after 10 consecutive rapid failures
  4. Health checks: GET http://localhost:7880/ verifies LiveKit is responding
  5. 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)
  • canPublish is derived from the SPEAK_VOICE permission
  • canSubscribe is 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_key from "devkey" to a random string
  • Change livekit_api_secret to a random 32+ character string
  • Open firewall ports: 7880/TCP, 50000-60000/UDP
  • If using ACME/manual TLS, ensure LiveKit proxy at /livekit is working
  • Test voice by joining a voice channel from two clients
  • Check /api/v1/livekit/health returns {"status": "ok"}