
























@@ -62,6 +62,14 @@ describe("ensureOggOpus", () => {
6262expect(stagedBase.endsWith(`-${path.basename(finalPath)}.part`)).toBe(true);
6363}
646465+function readSingleCommandArgs(mock: typeof runFfprobeMock | typeof runFfmpegMock): string[] {
66+const args = mock.mock.calls[0]?.[0];
67+if (!Array.isArray(args) || !args.every((arg): arg is string => typeof arg === "string")) {
68+throw new Error("missing command args");
69+}
70+return args;
71+}
72+6573it("rejects URL/protocol input paths", async () => {
6674await expect(ensureOggOpus("https://example.com/audio.ogg")).rejects.toThrow(
6775/local file path/i,
@@ -76,9 +84,18 @@ describe("ensureOggOpus", () => {
7684const result = await ensureOggOpus("/tmp/input.ogg");
77857886expect(result).toEqual({ path: "/tmp/input.ogg", cleanup: false });
79-expect(runFfprobeMock).toHaveBeenCalledWith(
80-expect.arrayContaining(["-show_entries", "stream=codec_name,sample_rate", "/tmp/input.ogg"]),
81-);
87+expect(runFfprobeMock).toHaveBeenCalledTimes(1);
88+expect(readSingleCommandArgs(runFfprobeMock)).toEqual([
89+"-v",
90+"error",
91+"-select_streams",
92+"a:0",
93+"-show_entries",
94+"stream=codec_name,sample_rate",
95+"-of",
96+"csv=p=0",
97+"/tmp/input.ogg",
98+]);
8299expect(runFfmpegMock).not.toHaveBeenCalled();
83100});
84101@@ -98,10 +115,25 @@ describe("ensureOggOpus", () => {
98115expect(result.cleanup).toBe(true);
99116expect(path.dirname(result.path)).toBe(path.normalize("/tmp"));
100117expect(path.basename(result.path)).toMatch(/^voice-.*\.ogg$/);
101-expect(runFfmpegMock).toHaveBeenCalledWith(
102-expect.arrayContaining(["-t", "1200", "-ar", "48000", "/tmp/input.ogg"]),
103-);
104-const ffmpegOutputPath = (runFfmpegMock.mock.calls[0]?.[0] as string[] | undefined)?.at(-1);
118+expect(runFfmpegMock).toHaveBeenCalledTimes(1);
119+const ffmpegArgs = readSingleCommandArgs(runFfmpegMock);
120+expect(ffmpegArgs.slice(0, -1)).toEqual([
121+"-y",
122+"-i",
123+"/tmp/input.ogg",
124+"-vn",
125+"-sn",
126+"-dn",
127+"-t",
128+"1200",
129+"-ar",
130+"48000",
131+"-c:a",
132+"libopus",
133+"-b:a",
134+"64k",
135+]);
136+const ffmpegOutputPath = ffmpegArgs.at(-1);
105137expectStagedFfmpegOutput(ffmpegOutputPath, result.path);
106138await expect(fs.readFile(result.path, "utf8")).resolves.toBe("ogg");
107139});
@@ -120,10 +152,25 @@ describe("ensureOggOpus", () => {
120152121153expect(result.cleanup).toBe(true);
122154expect(runFfprobeMock).not.toHaveBeenCalled();
123-expect(runFfmpegMock).toHaveBeenCalledWith(
124-expect.arrayContaining(["-vn", "-sn", "-dn", "/tmp/input.mp3"]),
125-);
126-const ffmpegOutputPath = (runFfmpegMock.mock.calls[0]?.[0] as string[] | undefined)?.at(-1);
155+expect(runFfmpegMock).toHaveBeenCalledTimes(1);
156+const ffmpegArgs = readSingleCommandArgs(runFfmpegMock);
157+expect(ffmpegArgs.slice(0, -1)).toEqual([
158+"-y",
159+"-i",
160+"/tmp/input.mp3",
161+"-vn",
162+"-sn",
163+"-dn",
164+"-t",
165+"1200",
166+"-ar",
167+"48000",
168+"-c:a",
169+"libopus",
170+"-b:a",
171+"64k",
172+]);
173+const ffmpegOutputPath = ffmpegArgs.at(-1);
127174expectStagedFfmpegOutput(ffmpegOutputPath, result.path);
128175await expect(fs.readFile(result.path, "utf8")).resolves.toBe("ogg");
129176});
@@ -215,13 +262,18 @@ describe("sendDiscordVoiceMessage", () => {
215262expect(uploadUrlRequests).toBe(2);
216263expect(fetchMock).toHaveBeenCalledTimes(4);
217264expect(post).toHaveBeenCalledWith("/channels/channel-1/messages", {
218-body: expect.objectContaining({
265+body: {
266+flags: 8192,
219267attachments: [
220-expect.objectContaining({
268+{
269+id: "0",
270+filename: "voice-message.ogg",
221271uploaded_filename: "uploaded-2.ogg",
222-}),
272+duration_secs: 1,
273+waveform: "waveform",
274+},
223275],
224-}),
276+},
225277});
226278});
227279此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。