feat: implement Opus decoder runtime checks and add tests for decoder functionality

This commit is contained in:
MythEclipse
2026-05-13 18:56:44 +07:00
parent 4dadcf3871
commit 220c3b93d2
4 changed files with 77 additions and 7 deletions
+38 -3
View File
@@ -1,6 +1,34 @@
import { createRequire } from "node:module";
import prism from "prism-media";
import { config } from "../config";
const require = createRequire(import.meta.url);
interface OpusDecoderRuntime {
isBun: boolean;
canLoadNativeOpus: boolean;
}
export function shouldEnableDefaultOpusDecoder(
runtime: OpusDecoderRuntime,
): boolean {
return !runtime.isBun || runtime.canLoadNativeOpus;
}
function canLoadNativeOpus(): boolean {
try {
require("@discordjs/opus");
return true;
} catch {
return false;
}
}
const defaultDecoderEnabled = shouldEnableDefaultOpusDecoder({
isBun: Boolean(process.versions.bun),
canLoadNativeOpus: canLoadNativeOpus(),
});
export interface OpusDecoderOptions {
cooldownMs: number;
rotateMs: number;
@@ -23,8 +51,14 @@ export class OpusDecoder {
this.onData = options.onData;
this.createDecoderFn =
options.createDecoder ??
(() =>
new prism.opus.Decoder({
(() => {
if (!defaultDecoderEnabled) {
throw new Error(
"Native @discordjs/opus is unavailable under Bun; web PCM decode disabled to avoid opusscript aborts",
);
}
return new prism.opus.Decoder({
frameSize: config.OPUS_FRAME_SIZE,
channels: config.AUDIO_CHANNELS as 1 | 2,
rate: config.AUDIO_SAMPLE_RATE as
@@ -33,7 +67,8 @@ export class OpusDecoder {
| 16000
| 24000
| 48000,
}));
});
});
}
rotateIfNeeded(): void {
+6 -2
View File
@@ -57,8 +57,12 @@ export function startWebserver(
const wss = new WebSocketServer({ server, path: wsPath });
wsLogger.info({ port, wsPath }, "WebSocket server listening");
// Security headers
app.use(helmet());
// Security headers. CSP disabled because the current static UI uses inline scripts/styles.
app.use(
helmet({
contentSecurityPolicy: false,
}),
);
// HTTP request logging
app.use(pinoHttp({ logger }));