Skip to content

Commit 65aed9c

Browse files
authored
Merge pull request #128 from MiniMax-AI/release/1.0.13
release: v1.0.13 — audio format validation & lint cleanup
2 parents 9282631 + 5ac960b commit 65aed9c

6 files changed

Lines changed: 75 additions & 7 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mmx-cli",
3-
"version": "1.0.12",
3+
"version": "1.0.13",
44
"description": "CLI for the MiniMax AI Platform",
55
"type": "module",
66
"engines": {

src/commands/speech/synthesize.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { detectOutputFormat, formatOutput, dryRun } from '../../output/formatter
88
import { saveAudioOutput } from '../../output/audio';
99
import { writeFileSync } from 'fs';
1010
import { readTextFromPathOrStdin } from '../../utils/fs';
11-
import { T2A_FORMATS, formatList, validateAudioFormat, validateT2AStreaming } from '../../utils/audio-formats';
11+
import { T2A_FORMATS, formatList, validateAudioFormat, validateT2AStreaming, t2aDefaultSampleRate } from '../../utils/audio-formats';
1212
import type { Config } from '../../config/schema';
1313
import type { GlobalFlags } from '../../types/flags';
1414
import type { SpeechRequest, SpeechResponse } from '../../types/api';
@@ -80,7 +80,7 @@ export default defineCommand({
8080
},
8181
audio_setting: {
8282
format: (flags.format as string) || 'mp3',
83-
sample_rate: (flags.sampleRate as number) ?? 32000,
83+
sample_rate: (flags.sampleRate as number) ?? t2aDefaultSampleRate(ext, 32000),
8484
bitrate: (flags.bitrate as number) ?? 128000,
8585
channel: (flags.channels as number) ?? 1,
8686
},

src/utils/audio-formats.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { CLIError } from '../errors/base';
22
import { ExitCode } from '../errors/codes';
33

44
export const T2A_FORMATS = ['mp3', 'pcm', 'flac', 'wav', 'pcmu_raw', 'pcmu_wav', 'opus'] as const;
5-
export const MUSIC_FORMATS = ['mp3', 'wav', 'pcm', 'flac'] as const;
5+
export const MUSIC_FORMATS = ['mp3', 'wav', 'pcm'] as const;
66

77
export type T2AFormat = (typeof T2A_FORMATS)[number];
88
export type MusicFormat = (typeof MUSIC_FORMATS)[number];
@@ -20,6 +20,16 @@ export function validateAudioFormat(format: string, formats: readonly string[]):
2020
}
2121
}
2222

23+
const T2A_SAMPLE_RATE: Partial<Record<T2AFormat, number>> = {
24+
opus: 24000,
25+
pcmu_raw: 8000,
26+
pcmu_wav: 8000,
27+
};
28+
29+
export function t2aDefaultSampleRate(format: string, fallback: number): number {
30+
return T2A_SAMPLE_RATE[format as T2AFormat] ?? fallback;
31+
}
32+
2333
export function validateT2AStreaming(format: string, stream: boolean): void {
2434
if (stream && format === 'wav') {
2535
throw new CLIError(

test/commands/music/generate.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ describe('music generate command', () => {
190190
).rejects.toThrow('Invalid audio format "opus"');
191191
});
192192

193-
it.each(['mp3', 'wav', 'pcm', 'flac'])(
193+
it.each(['mp3', 'wav', 'pcm'])(
194194
'accepts %s format in dry-run',
195195
async (fmt) => {
196196
const origLog = console.log;

test/commands/speech/synthesize.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,43 @@ describe('speech synthesize format validation', () => {
259259
synthesizeCommand.execute(config, { ...flags, format: 'wav', stream: true }),
260260
).rejects.toThrow('wav format is not supported in streaming');
261261
});
262+
263+
it('defaults opus sample rate to 24000', async () => {
264+
const originalLog = console.log;
265+
let output = '';
266+
console.log = (msg: string) => { output += msg; };
267+
try {
268+
await synthesizeCommand.execute(config, { ...flags, format: 'opus' });
269+
const parsed = JSON.parse(output);
270+
expect(parsed.request.audio_setting.sample_rate).toBe(24000);
271+
} finally {
272+
console.log = originalLog;
273+
}
274+
});
275+
276+
it('defaults pcmu_wav sample rate to 8000', async () => {
277+
const originalLog = console.log;
278+
let output = '';
279+
console.log = (msg: string) => { output += msg; };
280+
try {
281+
await synthesizeCommand.execute(config, { ...flags, format: 'pcmu_wav' });
282+
const parsed = JSON.parse(output);
283+
expect(parsed.request.audio_setting.sample_rate).toBe(8000);
284+
} finally {
285+
console.log = originalLog;
286+
}
287+
});
288+
289+
it('respects explicit --sample-rate even for opus', async () => {
290+
const originalLog = console.log;
291+
let output = '';
292+
console.log = (msg: string) => { output += msg; };
293+
try {
294+
await synthesizeCommand.execute(config, { ...flags, format: 'opus', sampleRate: 16000 });
295+
const parsed = JSON.parse(output);
296+
expect(parsed.request.audio_setting.sample_rate).toBe(16000);
297+
} finally {
298+
console.log = originalLog;
299+
}
300+
});
262301
});

test/utils/audio-formats.test.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
formatList,
66
validateAudioFormat,
77
validateT2AStreaming,
8+
t2aDefaultSampleRate,
89
} from '../../src/utils/audio-formats';
910

1011
describe('audio-formats', () => {
@@ -21,12 +22,12 @@ describe('audio-formats', () => {
2122
});
2223

2324
describe('MUSIC_FORMATS', () => {
24-
it.each(['mp3', 'wav', 'pcm', 'flac'] as const)(
25+
it.each(['mp3', 'wav', 'pcm'] as const)(
2526
'accepts %s',
2627
(fmt) => expect(() => validateAudioFormat(fmt, MUSIC_FORMATS)).not.toThrow(),
2728
);
2829

29-
it.each(['opus', 'pcmu_raw', 'pcmu_wav', 'aac'])(
30+
it.each(['opus', 'pcmu_raw', 'pcmu_wav', 'flac', 'aac'])(
3031
'rejects %s',
3132
(fmt) => expect(() => validateAudioFormat(fmt, MUSIC_FORMATS)).toThrow(/Invalid audio format/),
3233
);
@@ -52,4 +53,22 @@ describe('audio-formats', () => {
5253
expect(formatList(['a', 'b', 'c'])).toBe('a, b, c');
5354
});
5455
});
56+
57+
describe('t2aDefaultSampleRate', () => {
58+
it('returns 24000 for opus', () => {
59+
expect(t2aDefaultSampleRate('opus', 32000)).toBe(24000);
60+
});
61+
62+
it('returns 8000 for pcmu_raw', () => {
63+
expect(t2aDefaultSampleRate('pcmu_raw', 32000)).toBe(8000);
64+
});
65+
66+
it('returns 8000 for pcmu_wav', () => {
67+
expect(t2aDefaultSampleRate('pcmu_wav', 32000)).toBe(8000);
68+
});
69+
70+
it('returns fallback for mp3', () => {
71+
expect(t2aDefaultSampleRate('mp3', 32000)).toBe(32000);
72+
});
73+
});
5574
});

0 commit comments

Comments
 (0)