chore(services): update components based on recent changes

Changes:
 services/backend/src/ws/redis-bridge.ts                | 31 ++++++++++++++++++++-
 services/backend/src/ws/server.ts                      | 36 +++++++++++++++++++++++-
 services/frontend/src/App.tsx                          | 12 ++++----
 services/frontend/src/shared/hooks/useAudioPlayback.ts | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 services/frontend/src/shared/hooks/useAudioTransmit.ts | 21 +++++---------
 5 files changed, 169 insertions(+), 22 deletions(-)
This commit is contained in:
MythEclipse
2026-06-13 17:00:02 +07:00
parent 1d06de5ce5
commit 9bde518b71
5 changed files with 169 additions and 22 deletions
+30 -1
View File
@@ -25,7 +25,7 @@ import {
import { createChildLogger } from "@bete/shared/logger";
import Redis from "ioredis";
import { config } from "../shared/config/index.js";
import { broadcastEvent } from "./broadcast.js";
import { broadcastBinary, broadcastEvent } from "./broadcast.js";
const logger = createChildLogger("ws.redis-bridge");
@@ -96,6 +96,25 @@ function handleSubscriptionMessage(channel: string, message: string): void {
// We only want <actual payload>, not the full envelope.
const data = envelope.data !== undefined ? envelope.data : envelope;
// Voice PCM: decode base64 → binary broadcast instead of JSON
if (mapping.eventType === "voice_pcm_data") {
const pcmPayload = data as { userId?: string; pcm?: string };
if (pcmPayload?.pcm && pcmPayload?.userId) {
try {
const pcmBuffer = Buffer.from(pcmPayload.pcm, "base64");
// Prepend userId as 4-byte FNV-1a hash
const userIdHash = hashUserId(pcmPayload.userId);
const binary = Buffer.alloc(4 + pcmBuffer.length);
binary.writeUInt32LE(userIdHash, 0);
pcmBuffer.copy(binary, 4);
broadcastBinary(binary);
return;
} catch {
// fallback to JSON broadcast on error
}
}
}
logger.debug(
{ channel, eventType: mapping.eventType },
"Broadcasting Redis event",
@@ -103,6 +122,16 @@ function handleSubscriptionMessage(channel: string, message: string): void {
broadcastEvent(mapping.eventType, data);
}
/** Simple 32-bit FNV-1a hash for userId → 4-byte identifier */
function hashUserId(userId: string): number {
let hash = 0x811c9dc5;
for (let i = 0; i < userId.length; i++) {
hash ^= userId.charCodeAt(i);
hash = Math.imul(hash, 0x01000193);
}
return hash >>> 0;
}
export async function startRedisBridge(): Promise<void> {
if (!config.REDIS_URL) {
logger.info("Redis not configured, skipping Redis bridge");