Files
unisonus-livekit/README.md
2026-03-29 22:08:39 -04:00

104 lines
3.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# unisonus-livekit
WebRTC audio infrastructure for **Unisonus** — a choir/music streaming application. Provides a LiveKit server and a custom choir audio mixer agent that subscribes to participant audio streams, mixes them, and publishes the combined output back to the room.
## Architecture
```
Participants (up to 6)
│ audio tracks
choir-mixer agent
├── subscribes to all participant audio
├── normalises RMS per stream (target: -20 dBFS)
├── noise-gates signals below -40 dBFS
├── sums all streams
├── soft-limits via tanh (no hard clipping)
└── publishes mixed audio track back to room
All room participants receive the mix
```
## Services
| Service | Image | Ports | Description |
|---------|-------|-------|-------------|
| `livekit` | `livekit/livekit-server:latest` | `7880` (HTTP/WS), `7881` (RTC TCP), `50000-50100/udp` | LiveKit WebRTC media server |
| `choir-mixer` | Built from `./choir-mixer/Dockerfile` | — | Python agent: subscribes, mixes, publishes |
## Audio Mixer Details
**File:** `choir-mixer/main.py` + `choir-mixer/mixer.py`
| Parameter | Value |
|-----------|-------|
| Sample rate | 48 kHz |
| Channels | Mono (1) |
| Frame duration | 20 ms (960 samples/frame) |
| Max simultaneous streams | 6 |
| Target loudness | -20 dBFS (RMS) |
| Noise gate | -40 dBFS (silence below this threshold) |
| Limiter | tanh soft-limit (smooth saturation, no hard clipping) |
| Stale frame timeout | 60 ms (frames older than this are discarded from mix) |
The mixer runs at ~50 Hz (every 20 ms). Each cycle it:
1. Collects the most recent frame from each active participant (discarding stale frames)
2. Normalises each stream to -20 dBFS
3. Noise-gates signals below -40 dBFS (suppresses background noise and keyboard clicks)
4. Sums all streams into one
5. Applies tanh soft limiting to prevent clipping
6. Publishes the result as a mono 48kHz audio track
## LiveKit Server Config
**File:** `livekit.yaml`
| Setting | Value |
|---------|-------|
| HTTP/WS port | 7880 |
| RTC TCP port | 7881 |
| RTC UDP range | 5000050100 |
| Node IP | 192.168.0.241 |
| External IP | Disabled (LAN only) |
| Room empty timeout | 300 s |
| Max participants | 50 |
| Log level | info |
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `LIVEKIT_API_KEY` | Yes | LiveKit API key (from `livekit.yaml` `keys:`) |
| `LIVEKIT_API_SECRET` | Yes | LiveKit API secret |
Copy `.env.example` to `.env` and fill in the values. The API key/secret pair must match what is configured in `livekit.yaml`.
## Running
```bash
docker compose up -d
```
To check mixer logs:
```bash
docker compose logs -f choir-mixer
```
## Dependencies
**Python** (choir-mixer):
- `livekit` — LiveKit Agents SDK
- `livekit-rtc` — RTC bindings
- `numpy` — audio processing
## Deployment
Runs on `192.168.0.241` (albert-MacBookPro Linux server).
| Endpoint | URL |
|----------|-----|
| LiveKit signaling | `ws://192.168.0.241:7880` |
| LiveKit RTC TCP | `192.168.0.241:7881` |
| LiveKit RTC UDP | `192.168.0.241:50000-50100` |