Discord: fix captions silently stopping after encryption key changes #5

Merged
Khyretos merged 1 commit from claude/practical-darwin-vrjmvc into main 2026-09-25 02:21:17 +02:00
Khyretos commented 2026-09-25 02:21:13 +02:00 (Migrated from github.com)

Summary

Fixes Discord captions silently stopping (log: decode error … Invalid packet) until the service was restarted.

Cause: each speaker's Opus stream was piped into a prism Decoder stream. While Discord's end-to-end voice encryption (DAVE) changes keys (someone joins or leaves, the bot is moved), @discordjs/voice passes a few still-encrypted packets through. The first one made the decoder error out and destroyed it. The subscription stayed registered, so that speaker was never re-subscribed and their audio was dropped from then on. Reproduced locally: after one corrupt packet only 1 of the next 21 valid packets was decoded.

Fix:

  • Decode packet by packet (discord_bridge/audio.js: @discordjs/opus, opusscript fallback) and skip undecodable packets. The Opus stream is read in flowing mode, so it always ends after silence and the next utterance gets a fresh stream.
  • If audio stays undecodable for several seconds, rejoin the voice channel with a fresh connection (at most once per 30 s), shown as a warning in the app's log.
  • If the bot is dragged to another channel, it returns to the followed user's channel. The bot's own "left voice" event during a rejoin is ignored.
  • Decode errors are logged at most every 10 s per speaker.
  • Dockerfile copies all discord_bridge/*.js, including the new audio.js.
  • TROUBLESHOOTING entry for the symptom.

Testing

  • New test: corrupt packets don't stop a speaker's audio (all valid packets after them are still decoded). 158 tests pass.
  • Confirmed working by the repo owner on their server.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Hr7di2bGC8qCojX7XXQbGx


Generated by Claude Code

## Summary Fixes Discord captions silently stopping (log: `decode error … Invalid packet`) until the service was restarted. **Cause:** each speaker's Opus stream was piped into a prism `Decoder` stream. While Discord's end-to-end voice encryption (DAVE) changes keys (someone joins or leaves, the bot is moved), `@discordjs/voice` passes a few still-encrypted packets through. The first one made the decoder error out and destroyed it. The subscription stayed registered, so that speaker was never re-subscribed and their audio was dropped from then on. Reproduced locally: after one corrupt packet only 1 of the next 21 valid packets was decoded. **Fix:** - Decode packet by packet (`discord_bridge/audio.js`: `@discordjs/opus`, `opusscript` fallback) and skip undecodable packets. The Opus stream is read in flowing mode, so it always ends after silence and the next utterance gets a fresh stream. - If audio stays undecodable for several seconds, rejoin the voice channel with a fresh connection (at most once per 30 s), shown as a warning in the app's log. - If the bot is dragged to another channel, it returns to the followed user's channel. The bot's own "left voice" event during a rejoin is ignored. - Decode errors are logged at most every 10 s per speaker. - `Dockerfile` copies all `discord_bridge/*.js`, including the new `audio.js`. - TROUBLESHOOTING entry for the symptom. ## Testing - New test: corrupt packets don't stop a speaker's audio (all valid packets after them are still decoded). 158 tests pass. - Confirmed working by the repo owner on their server. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Hr7di2bGC8qCojX7XXQbGx --- _Generated by [Claude Code](https://claude.ai/code/session_01Hr7di2bGC8qCojX7XXQbGx)_
Sign in to join this conversation.
No description provided.