Skip to content

Commit e364c36

Browse files
author
Raylan LIN
committed
feat(music): add --model flag, --output-format url, apiDocs, improve --help
- Add --model flag to music generate (override default model) - Add --output-format url (24h expiry) to music generate - Add --model flag to music cover - Add apiDocs field to Command interface (in command.ts) - Improve --help descriptions: list all 14 lyrics structure tags, note length limits, clarify instrumental model behavior - Add URL output and music-2.5+ instrumental examples
1 parent f9a3ecb commit e364c36

2 files changed

Lines changed: 30 additions & 12 deletions

File tree

src/commands/music/cover.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ import { musicCoverModel } from './models';
1313

1414
export default defineCommand({
1515
name: 'music cover',
16-
description: 'Generate a cover version of a song based on reference audio (music-cover-free)',
16+
description: 'Generate a cover version of a song based on reference audio (music-cover / music-cover-free)',
17+
apiDocs: 'https://platform.minimax.io/docs/api-reference/music-generation',
1718
usage: 'mmx music cover --prompt <text> (--audio <url> | --audio-file <path>) [--lyrics <text>] [--out <path>] [flags]',
1819
options: [
20+
{ flag: '--model <model>', description: 'Model: music-cover (Token Plan), music-cover-free (Pay-as-you-go, default). Override only if needed.' },
1921
{ flag: '--prompt <text>', description: 'Target cover style, e.g. "Indie folk, acoustic guitar, warm male vocal"' },
2022
{ flag: '--audio <url>', description: 'URL of the reference audio (mp3, wav, flac, etc. — 6s to 6min, max 50MB)' },
2123
{ flag: '--audio-file <path>', description: 'Local reference audio file (auto base64-encoded)' },
@@ -66,7 +68,7 @@ export default defineCommand({
6668
const outPath = (flags.out as string | undefined) ?? `cover_${ts}.${ext}`;
6769
const format = detectOutputFormat(config.output);
6870

69-
const model = musicCoverModel(config);
71+
const model = (flags.model as string) || musicCoverModel(config);
7072
const body: MusicRequest = {
7173
model,
7274
prompt,

src/commands/music/generate.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,29 @@ import { musicGenerateModel } from './models';
1313

1414
export default defineCommand({
1515
name: 'music generate',
16-
description: 'Generate a song (music-2.6-free)',
16+
description: 'Generate a song (music-2.6 / music-2.6-free / music-2.5+ / music-2.5)',
17+
apiDocs: 'https://platform.minimax.io/docs/api-reference/music-generation',
1718
usage: 'mmx music generate --prompt <text> (--lyrics <text> | --instrumental | --lyrics-optimizer) [--out <path>] [flags]',
1819
options: [
19-
{ flag: '--prompt <text>', description: 'Music style description (can be detailed — see examples)' },
20-
{ flag: '--lyrics <text>', description: 'Song lyrics with structure tags. Required unless --instrumental or --lyrics-optimizer is used.' },
21-
{ flag: '--lyrics-file <path>', description: 'Read lyrics from file (use - for stdin)' },
20+
{ flag: '--prompt <text>', description: 'Music style description (e.g. "cinematic orchestral, building tension"). Max 2000 chars when combined with structured flags.' },
21+
{ flag: '--lyrics <text>', description: 'Song lyrics with structure tags (newline separated). Supported: [Intro], [Verse], [Pre Chorus], [Chorus], [Interlude], [Bridge], [Outro], [Post Chorus], [Transition], [Break], [Hook], [Build Up], [Inst], [Solo]. Tags must be clean — no descriptions inside brackets (they will be sung). Max 3500 chars.' },
22+
{ flag: '--lyrics-file <path>', description: 'Read lyrics from file (use - for stdin). Same tag rules as --lyrics.' },
2223
{ flag: '--lyrics-optimizer', description: 'Auto-generate lyrics from prompt (cannot be used with --lyrics or --instrumental)' },
23-
{ flag: '--instrumental', description: 'Generate instrumental music (no vocals). Cannot be used with --lyrics.' },
24+
{ flag: '--instrumental', description: 'Generate instrumental music (no vocals). music-2.6/music-2.5+: native is_instrumental flag; music-2.5: lyrics workaround. Cannot be used with --lyrics.' },
2425
{ flag: '--vocals <text>', description: 'Vocal style, e.g. "warm male baritone", "bright female soprano", "duet with harmonies"' },
25-
{ flag: '--genre <text>', description: 'Music genre, e.g. folk, pop, jazz' },
26+
{ flag: '--genre <text>', description: 'Music genre, e.g. folk, pop, jazz, electronic' },
2627
{ flag: '--mood <text>', description: 'Mood or emotion, e.g. warm, melancholic, uplifting' },
27-
{ flag: '--instruments <text>', description: 'Instruments to feature, e.g. "acoustic guitar, piano"' },
28+
{ flag: '--instruments <text>', description: 'Instruments to feature, e.g. "acoustic guitar, piano, strings"' },
2829
{ flag: '--tempo <text>', description: 'Tempo description, e.g. fast, slow, moderate' },
2930
{ flag: '--bpm <number>', description: 'Exact tempo in beats per minute', type: 'number' },
3031
{ flag: '--key <text>', description: 'Musical key, e.g. C major, A minor, G sharp' },
3132
{ flag: '--avoid <text>', description: 'Elements to avoid in the generated music' },
3233
{ flag: '--use-case <text>', description: 'Use case context, e.g. "background music for video", "theme song"' },
3334
{ flag: '--structure <text>', description: 'Song structure, e.g. "verse-chorus-verse-bridge-chorus"' },
34-
{ flag: '--references <text>', description: 'Reference tracks or artists, e.g. "similar to Ed Sheeran, Taylor Swift"' },
35+
{ flag: '--references <text>', description: 'Reference tracks or artists, e.g. "similar to Ed Sheeran"' },
3536
{ flag: '--extra <text>', description: 'Additional fine-grained requirements not covered above' },
37+
{ flag: '--model <model>', description: 'Model: music-2.6 (recommended), music-2.6-free (default, unlimited), music-2.5+, or music-2.5.' },
38+
{ flag: '--output-format <fmt>', description: 'Return format: hex (default, saved to file) or url (24h expiry, download promptly). When --stream, only hex.' },
3639
{ flag: '--aigc-watermark', description: 'Embed AI-generated content watermark in audio for content provenance' },
3740
{ flag: '--format <fmt>', description: 'Audio format (default: mp3)' },
3841
{ flag: '--sample-rate <hz>', description: 'Sample rate (default: 44100)', type: 'number' },
@@ -47,6 +50,10 @@ export default defineCommand({
4750
'mmx music generate --prompt "Upbeat pop about summer" --lyrics-optimizer --out summer.mp3',
4851
'# Instrumental:',
4952
'mmx music generate --prompt "Cinematic orchestral, building tension" --instrumental --out bgm.mp3',
53+
'# URL output (24h expiry — download promptly):',
54+
'mmx music generate --prompt "Upbeat pop" --lyrics "La la la..." --output-format url',
55+
'# Instrumental with music-2.5+:',
56+
'mmx music generate --prompt "Cinematic orchestral" --model "music-2.5+" --instrumental --out bgm.mp3',
5057
'# Detailed prompt with vocal characteristics:',
5158
'mmx music generate --prompt "Warm morning folk" --vocals "male and female duet, harmonies in chorus" --instruments "acoustic guitar, piano" --bpm 95 --lyrics-file song.txt --out duet.mp3',
5259
],
@@ -117,7 +124,8 @@ export default defineCommand({
117124
const outPath = (flags.out as string | undefined) ?? `music_${ts}.${ext}`;
118125
const format = detectOutputFormat(config.output);
119126

120-
const model = musicGenerateModel(config);
127+
const model = (flags.model as string) || musicGenerateModel(config);
128+
const outFormat = (flags.outputFormat as string) || 'hex';
121129
const body: MusicRequest = {
122130
model,
123131
prompt,
@@ -129,7 +137,7 @@ export default defineCommand({
129137
sample_rate: (flags.sampleRate as number) ?? 44100,
130138
bitrate: (flags.bitrate as number) ?? 256000,
131139
},
132-
output_format: 'hex',
140+
output_format: (flags.stream === true ? 'hex' : outFormat) as 'hex' | 'url',
133141
stream: flags.stream === true,
134142
};
135143

@@ -162,6 +170,14 @@ export default defineCommand({
162170
});
163171

164172
if (!config.quiet) process.stderr.write(`[Model: ${model}]\n`);
173+
if (outFormat === 'url' && response.data?.audio_url) {
174+
if (config.quiet) {
175+
process.stdout.write(response.data.audio_url);
176+
} else {
177+
process.stdout.write(formatOutput({ audio_url: response.data.audio_url }, format));
178+
}
179+
return;
180+
}
165181
saveAudioOutput(response, outPath, format, config.quiet);
166182
},
167183
});

0 commit comments

Comments
 (0)