fix(backend): handle voice PCM as JSON instead of binary
- Add discord:voice:pcm to SUBSCRIPTIONS as regular JSON channel
- Remove BINARY_CHANNELS and handleBinaryMessage function
- Discord-gateway sends PCM as JSON with base64, not raw binary
- This fixes PCM data not reaching browser via WebSocket
The issue was backend expected binary format but gateway sends:
{"type":"voice_pcm_data","data":{"userId":"...","pcm":"base64..."}}
Now backend correctly subscribes and broadcasts this to WebSocket clients.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e8e95f635c
commit
1c7b7e6398
@@ -26,11 +26,9 @@ const SUBSCRIPTIONS: ChannelMapping[] = [
|
|||||||
eventType: "analysis_queue_status",
|
eventType: "analysis_queue_status",
|
||||||
},
|
},
|
||||||
{ channel: "discord:voice:active_user", eventType: "voice_active_user" },
|
{ channel: "discord:voice:active_user", eventType: "voice_active_user" },
|
||||||
|
{ channel: "discord:voice:pcm", eventType: "voice_pcm_data" },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Binary channels that need special handling (messageBuffer event)
|
|
||||||
const BINARY_CHANNELS = ["discord:voice:pcm"];
|
|
||||||
|
|
||||||
let subscriber: Redis | null = null;
|
let subscriber: Redis | null = null;
|
||||||
|
|
||||||
function createSubscriber(): Redis {
|
function createSubscriber(): Redis {
|
||||||
@@ -94,41 +92,6 @@ function handleSubscriptionMessage(channel: string, message: string): void {
|
|||||||
broadcastRaw(mapping.eventType, data);
|
broadcastRaw(mapping.eventType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle binary messages from Redis (e.g. voice PCM data).
|
|
||||||
* Expected format: 4-byte userId hash + PCM buffer
|
|
||||||
*/
|
|
||||||
function handleBinaryMessage(channel: Buffer, message: Buffer): void {
|
|
||||||
const channelStr = channel.toString();
|
|
||||||
|
|
||||||
if (channelStr === "discord:voice:pcm") {
|
|
||||||
if (message.length < 4) {
|
|
||||||
logger.warn(
|
|
||||||
{ channel: channelStr, size: message.length },
|
|
||||||
"Received PCM message too short to contain userId",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First 4 bytes = userId hash, rest = PCM data
|
|
||||||
const userIdHash = message.readUInt32LE(0);
|
|
||||||
const pcmData = message.subarray(4);
|
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
{ channel: channelStr, userIdHash, pcmSize: pcmData.length },
|
|
||||||
"Broadcasting voice PCM data",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Broadcast as binary: userId (4 bytes) + PCM data
|
|
||||||
broadcastRaw("voice_pcm", message);
|
|
||||||
} else {
|
|
||||||
logger.warn(
|
|
||||||
{ channel: channelStr },
|
|
||||||
"Received binary message for unmapped channel",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function startRedisBridge(): Promise<void> {
|
export async function startRedisBridge(): Promise<void> {
|
||||||
if (!config.REDIS_URL && !config.REDIS_HOST) {
|
if (!config.REDIS_URL && !config.REDIS_HOST) {
|
||||||
logger.info("Redis not configured, skipping Redis bridge");
|
logger.info("Redis not configured, skipping Redis bridge");
|
||||||
@@ -155,7 +118,6 @@ export async function startRedisBridge(): Promise<void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
subscriber.on("message", handleSubscriptionMessage);
|
subscriber.on("message", handleSubscriptionMessage);
|
||||||
subscriber.on("messageBuffer", handleBinaryMessage);
|
|
||||||
|
|
||||||
await subscriber.ping();
|
await subscriber.ping();
|
||||||
logger.info("Redis ping OK");
|
logger.info("Redis ping OK");
|
||||||
@@ -164,11 +126,6 @@ export async function startRedisBridge(): Promise<void> {
|
|||||||
await subscriber.subscribe(...channels);
|
await subscriber.subscribe(...channels);
|
||||||
logger.info({ channels }, "Subscribed to Redis channels");
|
logger.info({ channels }, "Subscribed to Redis channels");
|
||||||
|
|
||||||
if (BINARY_CHANNELS.length > 0) {
|
|
||||||
await subscriber.subscribe(...BINARY_CHANNELS);
|
|
||||||
logger.info({ channels: BINARY_CHANNELS }, "Subscribed to binary Redis channels");
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("Redis bridge started");
|
logger.info("Redis bridge started");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error({ err }, "Failed to start Redis bridge");
|
logger.error({ err }, "Failed to start Redis bridge");
|
||||||
|
|||||||
Reference in New Issue
Block a user