




















@@ -1,4 +1,11 @@
11import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2+3+const runFfmpegMock = vi.hoisted(() => vi.fn());
4+5+vi.mock("openclaw/plugin-sdk/media-runtime", () => ({
6+runFfmpeg: runFfmpegMock,
7+}));
8+29import { buildMinimaxSpeechProvider } from "./speech-provider.js";
310411describe("buildMinimaxSpeechProvider", () => {
@@ -213,6 +220,7 @@ describe("buildMinimaxSpeechProvider", () => {
213220214221beforeEach(() => {
215222vi.stubGlobal("fetch", vi.fn());
223+runFfmpegMock.mockReset();
216224});
217225218226afterEach(() => {
@@ -240,7 +248,7 @@ describe("buildMinimaxSpeechProvider", () => {
240248241249expect(result.outputFormat).toBe("mp3");
242250expect(result.fileExtension).toBe(".mp3");
243-expect(result.voiceCompatible).toBe(true);
251+expect(result.voiceCompatible).toBe(false);
244252expect(result.audioBuffer.toString()).toBe("fake-audio-data");
245253246254expect(mockFetch).toHaveBeenCalledOnce();
@@ -250,6 +258,44 @@ describe("buildMinimaxSpeechProvider", () => {
250258expect(body.model).toBe("speech-2.8-hd");
251259expect(body.text).toBe("Hello world");
252260expect(body.voice_setting.voice_id).toBe("English_expressive_narrator");
261+expect(runFfmpegMock).not.toHaveBeenCalled();
262+});
263+264+it("transcodes MiniMax MP3 to Opus for voice-note targets", async () => {
265+const hexAudio = Buffer.from("fake-mp3-data").toString("hex");
266+const mockFetch = vi.mocked(globalThis.fetch);
267+mockFetch.mockResolvedValueOnce(
268+new Response(JSON.stringify({ data: { audio: hexAudio } }), {
269+status: 200,
270+headers: { "Content-Type": "application/json" },
271+}),
272+);
273+runFfmpegMock.mockImplementationOnce(async (args: string[]) => {
274+const outputPath = args.at(-1);
275+if (typeof outputPath !== "string") {
276+throw new Error("missing ffmpeg output path");
277+}
278+await import("node:fs/promises").then((fs) =>
279+fs.writeFile(outputPath, Buffer.from("fake-opus-data")),
280+);
281+});
282+283+const result = await provider.synthesize({
284+text: "Hello world",
285+cfg: {} as never,
286+providerConfig: { apiKey: "sk-test", baseUrl: "https://api.minimaxi.com" },
287+target: "voice-note",
288+timeoutMs: 30000,
289+});
290+291+expect(result.outputFormat).toBe("opus");
292+expect(result.fileExtension).toBe(".opus");
293+expect(result.voiceCompatible).toBe(true);
294+expect(result.audioBuffer.toString()).toBe("fake-opus-data");
295+expect(runFfmpegMock).toHaveBeenCalledWith(
296+expect.arrayContaining(["-c:a", "libopus", "-ar", "48000"]),
297+{ timeoutMs: 30000 },
298+);
253299});
254300255301it("applies overrides", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。