|
All checks were successful
Build Docker image and publish / docker (push) Successful in 7m56s
|
||
|---|---|---|
| .forgejo/workflows | ||
| assets/sounds | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| config.example.toml | ||
| Dockerfile | ||
| README.md | ||
VoiceBridge
Bidirectional voice bridge between a Discord voice channel and either a TeamSpeak server or a MatrixRTC room (Element Call / Matrix). When someone joins the configured backend channel/room, the bot joins Discord voice and relays audio in both directions.
A built-in web interface shows live status for both servers via SSE.
Backends
Two mutually exclusive cargo features select the backend:
| Feature | Backend | Trigger |
|---|---|---|
teamspeak (default) |
TeamSpeak 3 server | Users join the configured TS channel |
matrixrtc |
MatrixRTC / Element Call | Call members detected via Matrix /sync (org.matrix.msc3401.call.member state events) |
Requirements
- Rust (edition 2024)
- A Discord bot token
TeamSpeak backend
- A TeamSpeak 3 server
opusdevelopment libraries
MatrixRTC backend
- A Matrix homeserver with a bot account and access token
- A LiveKit JWT service (lk-jwt-service) — auto-discovered via MSC4143 or well-known
cmake,g++,clang(for buildingwebrtc-sys)
Discord Bot Setup
- Create an application at the Discord Developer Portal.
- Go to Bot and copy the bot token.
- Under Privileged Gateway Intents, enable:
- Server Members Intent — required for displaying user names instead of IDs.
- Message Content Intent — required for bridging text chat between Discord and the backend.
- Go to OAuth2 → URL Generator, select the
botscope with these permissions:- Connect — join voice channels
- Speak — send audio
- Use Voice Activity — receive audio without push-to-talk
- Send Messages — relay backend chat to the Discord voice channel
- Read Message History — read messages in the bridged channel
- Use the generated URL to invite the bot to your server.
- Enable Developer Mode in Discord settings (App Settings → Advanced) to copy guild and channel IDs by right-clicking.
Configuration
Copy the example config and fill in your values:
cp config.example.toml .credentials.toml
Common settings
| Key | Required | Description |
|---|---|---|
discord_token |
yes | Bot token from the Developer Portal |
discord_guild_id |
yes | Discord server (guild) ID |
discord_channel_id |
yes | Discord voice channel ID to bridge |
verbose |
no | Log level: 0=warn, 1=info, 2=debug (default), 3+=trace |
volume |
no | Volume multiplier for backend→Discord audio (default: 1.0) |
web_listen |
no | Address for the web status page (e.g. 0.0.0.0:8080) |
web_token |
no | Shared secret to protect the web interface |
TeamSpeak settings
| Key | Required | Description |
|---|---|---|
teamspeak_server |
yes | TeamSpeak address (host or host:port, default port 9987) |
teamspeak_identity |
no | Persistent TS identity string (printed on first run if omitted) |
teamspeak_name |
no | Bot display name on TeamSpeak (default: VoiceBridge) |
teamspeak_channel |
no | TS channel path to join (e.g. Default Channel/Bridge) |
teamspeak_channel_id |
no | TS channel ID to join (alternative to path) |
teamspeak_server_password |
no | TS server password |
teamspeak_channel_password |
no | TS channel password |
MatrixRTC settings
| Key | Required | Description |
|---|---|---|
matrix_homeserver_url |
yes | Matrix homeserver URL (e.g. https://matrix.example.com) |
matrix_access_token |
yes | Bot's Matrix access token |
matrix_room_id |
yes | Matrix room ID (e.g. !abc123:matrix.org) |
matrix_device_id |
no | Bot device ID (default: VOICEBRIDGE) |
livekit_service_url |
no | Override JWT service URL (auto-discovered via MSC4143/well-known) |
livekit_room_name |
no | Direct LiveKit room name (overrides MSC4195 derivation) |
livekit_identity |
no | Bot display name in LiveKit (default: VoiceBridge) |
livekit_slot_id |
no | MatrixRTC slot ID (default: m.call#ROOM) |
Build & Run
# TeamSpeak (default)
cargo clippy # build + lint
cargo run # run the bridge
# MatrixRTC
cargo clippy --features matrixrtc --no-default-features
cargo run --features matrixrtc --no-default-features
Docker
# TeamSpeak (default)
docker build -t voicebridge .
# MatrixRTC
docker build --build-arg FEATURES=matrixrtc -t teamcordvoice .
Web Interface
Set web_listen in your config to enable the status page. It shows a split-panel view:
- Left panel: Backend status — TeamSpeak channel tree or MatrixRTC room participants
- Right panel: Discord voice channels with users and mute/deaf/streaming indicators
The page updates in real time via Server-Sent Events.
How It Works
The Discord gateway connection and the backend task run permanently. The bot monitors the backend for occupancy:
- TeamSpeak: When someone joins the configured TS channel, the bot joins Discord voice and starts relaying audio. When the TS channel empties, it leaves Discord voice.
- MatrixRTC: The bot monitors the Matrix room via
/syncfororg.matrix.msc3401.call.memberstate events. When call members are present, it discovers the JWT service (MSC4143 or well-known), exchanges an OpenID token for a LiveKit JWT, sends its own membership state event, and connects to LiveKit. When all members leave, it clears its membership and disconnects.
Audio is bridged at 48 kHz stereo, 20 ms frames in both directions. Text messages in the configured Discord channel are forwarded to TeamSpeak channel chat (and vice versa); text bridging is not yet implemented for MatrixRTC.