56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
/*
|
|||
|
|
Copyright 2026 Lotus Guild
|
||
|
|
|
||
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||
|
|
Please see LICENSE in the repository root for full details.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { describe, expect, test } from "vitest";
|
||
|
|
import { type AudioProcessorOptions } from "livekit-client";
|
||
|
|
|
||
|
|
import { LotusDenoiseProcessor } from "./lotusDenoiseProcessor";
|
||
|
|
|
||
|
|
function makeProcessor(): LotusDenoiseProcessor {
|
||
|
|
return new LotusDenoiseProcessor({
|
||
|
|
model: "rnnoise",
|
||
|
|
assetBase: "https://example.invalid/denoise/",
|
||
|
|
gate: false,
|
||
|
|
gateThreshold: -45,
|
||
|
|
floor: 0.15,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
describe("LotusDenoiseProcessor.restart", () => {
|
||
|
|
test("falls back to processedTrack = undefined (never the raw LiveKit track) when graph rebuild fails", async () => {
|
||
|
|
const processor = makeProcessor();
|
||
|
|
|
||
|
|
// Stub out the AudioContext/graph plumbing: pretend the context is fine
|
||
|
|
// but the graph rebuild (wasm load / worklet construction) throws, which
|
||
|
|
// is the path this test targets.
|
||
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
|
(processor as any).ensureContext = async (): Promise<void> => {
|
||
|
|
await Promise.resolve();
|
||
|
|
};
|
||
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
|
(processor as any).buildGraph = async (): Promise<never> => {
|
||
|
|
await Promise.resolve();
|
||
|
|
throw new Error("simulated graph build failure");
|
||
|
|
};
|
||
|
|
|
||
|
|
const rawTrack = {
|
||
|
|
stop: (): void => undefined,
|
||
|
|
} as unknown as MediaStreamTrack;
|
||
|
|
|
||
|
|
await processor.restart({
|
||
|
|
track: rawTrack,
|
||
|
|
} as unknown as AudioProcessorOptions);
|
||
|
|
|
||
|
|
// Must NOT be the raw, LiveKit-owned track: LiveKit's
|
||
|
|
// internalStopProcessor() calls `processor.processedTrack?.stop()` then
|
||
|
|
// re-publishes the same `_mediaStreamTrack` object, which would kill the
|
||
|
|
// live mic on the next stopProcessor()/teardown if we handed it back here.
|
||
|
|
expect(processor.processedTrack).toBeUndefined();
|
||
|
|
expect(processor.processedTrack).not.toBe(rawTrack);
|
||
|
|
});
|
||
|
|
});
|