@omni/voice-client and is wired into the Discord channel adapter — no external Node sidecar required.| Capability | Notes |
| Discord voice gateway v8 | UDP transport, libsodium-backed packet auth |
| DAVE E2EE | Discord Audio & Video End-to-End encryption — Omni participates as a full DAVE client (group key exchange, sender keys, key rotation) |
| Opus codec | Decode incoming Opus frames, optionally re-encode for outbound |
| Per-user streams | Audio is demuxed per Discord user ID so transcription/STT can target a single speaker |
| Session WebSocket | A local WebSocket (omni voice stream) emits audio frames + control events for downstream consumers |
12345678910111213141516omni voice join ──▶ Discord gateway handshake │ ▼ DAVE key exchange │ ▼ Voice UDP / SRTP established │ ▼ Per-user Opus streams demuxed │ ▼ omni voice stream <id> taps the bus │ ▼ omni voice leave
1234567891011121314151617# Join a Discord voice channel omni voice join --instance my-discord --guild <guild-id> --channel <voice-channel-id> # List active voice sessions omni voice sessions # Tap a session over WebSocket — opus by default, pcm for raw frames omni voice stream <session-id> --format pcm --save ./recordings # Filter to a single speaker omni voice stream <session-id> --user <discord-user-id> # Show only control events (joined/left/speaking) without audio stats omni voice stream <session-id> --events-only # Leave the session omni voice leave --instance my-discord
omni voice stream exits cleanly on Ctrl+C and is safe to pipe into transcription tooling.--save <dir> on omni voice stream if you need on-disk artefacts; otherwise the bus is in-memory only.voice.handshake_failed event. Check omni events list --type voice.handshake_failed --since 1h if voice goes dark in a DAVE-enabled guild.