refactor(voice): optimize recording pipeline and improve performance
Refactor the voice recording and playback systems to improve efficiency, reduce latency, and enhance Docker build performance. - **Infrastructure**: Optimize Dockerfiles using build mounts for pnpm cache and reorder layers for better caching of dependencies and build tools. - **Backend/Gateway**: - Refactor `broadcast` module to use a generic event-based system instead of hardcoded functions. - Simplify voice recording logic by merging metadata and segment management into a unified `segment.ts`. - Optimize audio downsampling in `streamSetup.ts` using `Int16Array` views for better performance. - Implement `withFallback` utility for more robust Redis/Database command execution. - **Frontend**: - Optimize audio playback visualization using pre-computed level shapes and efficient RMS calculation. - Reduce latency in voice commands by prioritizing WebSocket communication over HTTP. - Improve base64 encoding efficiency in audio transmission. - **General**: - Add default value for `ADMIN_PASSWORD` in shared config. - Fix Docker healthcheck to use `127.0.0.1` instead of `localhost`.
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
COMMAND_VOICE_CHANNELS,
|
||||
COMMAND_VOICE_CONNECT,
|
||||
COMMAND_VOICE_DISCONNECT,
|
||||
CommandReply,
|
||||
VOICE_STATUS_KEY,
|
||||
} from "@bete/shared";
|
||||
import {
|
||||
@@ -41,6 +42,18 @@ export const DEFAULT_VOICE_STATUS: VoiceStatus = {
|
||||
activeChannelName: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps tryCommandThenFallback with a cleaner signature for use within this module.
|
||||
* Attempts a Redis command first; on failure, falls back to the provided function.
|
||||
*/
|
||||
async function withFallback<T>(
|
||||
commandFn: () => Promise<CommandReply<T> | null>,
|
||||
fallbackFn: () => Promise<T>,
|
||||
name: string,
|
||||
): Promise<T> {
|
||||
return tryCommandThenFallback(commandFn, fallbackFn, name);
|
||||
}
|
||||
|
||||
function readVoiceStatusFallback(): Promise<VoiceStatus> {
|
||||
return readRedisStatus(VOICE_STATUS_KEY).then(
|
||||
(cached) => (cached as unknown as VoiceStatus) ?? DEFAULT_VOICE_STATUS,
|
||||
@@ -53,7 +66,7 @@ function readVoiceStatusFallback(): Promise<VoiceStatus> {
|
||||
*/
|
||||
export async function getGuilds(): Promise<Guild[]> {
|
||||
logger.info("getGuilds called");
|
||||
return tryCommandThenFallback(
|
||||
return withFallback(
|
||||
() => publishCommand<Guild[]>(COMMAND_GUILDS_LIST, {}),
|
||||
async () => {
|
||||
const pool = getPool();
|
||||
@@ -76,7 +89,7 @@ export async function getGuilds(): Promise<Guild[]> {
|
||||
*/
|
||||
export async function getTextChannels(guildId: string): Promise<Channel[]> {
|
||||
logger.info({ guildId }, "getTextChannels called");
|
||||
return tryCommandThenFallback(
|
||||
return withFallback(
|
||||
() => publishCommand<Channel[]>(COMMAND_GUILDS_TEXT_CHANNELS, { guildId }),
|
||||
async () => {
|
||||
const pool = getPool();
|
||||
@@ -122,7 +135,7 @@ export async function connectVoice(
|
||||
channelId: string,
|
||||
): Promise<VoiceStatus> {
|
||||
logger.info({ guildId, channelId }, "connectVoice called");
|
||||
return tryCommandThenFallback(
|
||||
return withFallback(
|
||||
() =>
|
||||
publishCommand<VoiceStatus>(COMMAND_VOICE_CONNECT, {
|
||||
guildId,
|
||||
@@ -138,7 +151,7 @@ export async function connectVoice(
|
||||
*/
|
||||
export async function disconnectVoice(): Promise<VoiceStatus> {
|
||||
logger.info("disconnectVoice called");
|
||||
return tryCommandThenFallback(
|
||||
return withFallback(
|
||||
() => publishCommand<VoiceStatus>(COMMAND_VOICE_DISCONNECT, {}),
|
||||
() => readVoiceStatusFallback(),
|
||||
"disconnectVoice",
|
||||
|
||||
Reference in New Issue
Block a user