@@ -7,7 +7,8 @@ import { ModelPartial } from "../types";
77import { SDKError } from "../../errors/base" ;
88import { ExitCode } from "../../errors/codes" ;
99import { toMerged } from "es-toolkit/object" ;
10- import { musicGenerateModel } from "../../commands/music/models" ;
10+ import { MUSIC_GENERATE_MODELS , musicGenerateModel } from "../../commands/music/models" ;
11+ import { decodeAudioStream } from "../../utils/audio-stream" ;
1112
1213function hexToBuffer ( hex : string ) : Buffer {
1314 if ( ! / ^ [ 0 - 9 a - f A - F ] * $ / . test ( hex ) ) {
@@ -64,20 +65,11 @@ export class MusicSDK extends Client {
6465 stream : true ,
6566 } ) ;
6667
67- const reader = res . body ?. getReader ( ) ;
68- if ( ! reader ) {
68+ if ( ! res . body ) {
6969 throw new SDKError ( 'No response body' , ExitCode . GENERAL ) ;
70- } ;
71-
72- try {
73- while ( true ) {
74- const { done, value } = await reader . read ( ) ;
75- if ( done ) break ;
76- yield value ;
77- }
78- } finally {
79- reader . releaseLock ( ) ;
8070 }
71+
72+ yield * decodeAudioStream ( res ) ;
8173 }
8274
8375 async generate ( request : ModelPartial < MusicGenerateRequest > & { stream : true } ) : Promise < AsyncGenerator < Uint8Array < ArrayBuffer > > > ;
@@ -140,16 +132,15 @@ export class MusicSDK extends Client {
140132 if ( request . bpm ) structuredParts . push ( `BPM: ${ request . bpm as number } ` ) ;
141133 if ( request . key ) structuredParts . push ( `Key: ${ request . key as string } ` ) ;
142134 if ( request . avoid ) structuredParts . push ( `Avoid: ${ request . avoid as string } ` ) ;
143- if ( request . useCase ) structuredParts . push ( `Use case: ${ request . useCase as string } ` ) ;
135+ const useCase = request . useCase || request . use_case ;
136+ if ( useCase ) structuredParts . push ( `Use case: ${ useCase } ` ) ;
144137 if ( request . structure ) structuredParts . push ( `Structure: ${ request . structure as string } ` ) ;
145138 if ( request . references ) structuredParts . push ( `References: ${ request . references as string } ` ) ;
146139 if ( request . extra ) structuredParts . push ( `Extra: ${ request . extra as string } ` ) ;
147140
148- let lyrics = request . lyrics ;
149141 let prompt = request . prompt ;
150142
151- if ( request . instrumental || ! lyrics || lyrics === '无歌词' || lyrics === 'no lyrics' ) {
152- lyrics = '[intro] [outro]' ;
143+ if ( request . is_instrumental || request . instrumental ) {
153144 structuredParts . push ( 'Style: instrumental, no vocals, pure music' ) ;
154145 }
155146
@@ -161,9 +152,43 @@ export class MusicSDK extends Client {
161152 }
162153
163154 private validateParams ( params : ModelPartial < MusicGenerateRequest > ) {
155+ const instrumental = params . instrumental ;
156+ const apiParams = { ...params } ;
157+ const sdkOnlyFields : Array < keyof MusicGenerateRequest > = [
158+ 'instrumental' ,
159+ 'vocals' ,
160+ 'genre' ,
161+ 'mood' ,
162+ 'instruments' ,
163+ 'tempo' ,
164+ 'bpm' ,
165+ 'key' ,
166+ 'avoid' ,
167+ 'use_case' ,
168+ 'useCase' ,
169+ 'structure' ,
170+ 'references' ,
171+ 'extra' ,
172+ ] ;
173+ for ( const field of sdkOnlyFields ) delete apiParams [ field ] ;
174+ if (
175+ instrumental !== undefined
176+ && params . is_instrumental !== undefined
177+ && instrumental !== params . is_instrumental
178+ ) {
179+ throw new SDKError (
180+ 'instrumental and is_instrumental must not conflict' ,
181+ ExitCode . USAGE ,
182+ ) ;
183+ }
184+
185+ const normalized : ModelPartial < MusicGenerateRequest > = {
186+ ...apiParams ,
187+ is_instrumental : params . is_instrumental ?? instrumental ,
188+ } ;
164189 const {
165190 model, output_format, stream, prompt, lyrics, is_instrumental, lyrics_optimizer,
166- } = params ;
191+ } = normalized ;
167192 if ( is_instrumental && lyrics ) {
168193 throw new SDKError ( 'Cannot use is_instrumental with lyrics' , ExitCode . USAGE ) ;
169194 }
@@ -176,14 +201,20 @@ export class MusicSDK extends Client {
176201 throw new SDKError ( 'At least one of prompt or lyrics or is_instrumental or lyrics_optimizer is required' , ExitCode . USAGE ) ;
177202 }
178203
204+ if ( ( is_instrumental || lyrics_optimizer ) && ! prompt ?. trim ( ) ) {
205+ throw new SDKError (
206+ 'prompt is required with is_instrumental or lyrics_optimizer' ,
207+ ExitCode . USAGE ,
208+ ) ;
209+ }
210+
179211 if ( ! is_instrumental && ! lyrics_optimizer && ! lyrics ?. trim ( ) ) {
180212 throw new SDKError ( 'lyrics is required' , ExitCode . USAGE ) ;
181213 }
182214
183- const VALID_MODELS = [ 'music-2.6' , 'music-2.5+' , 'music-2.5' ] ;
184- if ( model && ! VALID_MODELS . includes ( model ) ) {
215+ if ( model && ! MUSIC_GENERATE_MODELS . includes ( model as typeof MUSIC_GENERATE_MODELS [ number ] ) ) {
185216 throw new SDKError (
186- `Invalid model: ${ model } . Valid models are ${ VALID_MODELS . join ( ', ' ) } .` ,
217+ `Invalid model: ${ model } . Valid models are ${ MUSIC_GENERATE_MODELS . join ( ', ' ) } .` ,
187218 ExitCode . USAGE ,
188219 ) ;
189220 }
@@ -202,7 +233,10 @@ export class MusicSDK extends Client {
202233 ) ;
203234 }
204235
205- const targetPrompt = this . buildPrompt ( params ) ;
236+ const targetPrompt = this . buildPrompt ( {
237+ ...params ,
238+ is_instrumental,
239+ } ) ;
206240
207241 return toMerged ( {
208242 model : musicGenerateModel ( this . config ) ,
@@ -213,7 +247,7 @@ export class MusicSDK extends Client {
213247 } ,
214248 output_format : 'hex' ,
215249 } , {
216- ...params ,
250+ ...normalized ,
217251 prompt : targetPrompt ,
218252 } ) ;
219253 }
0 commit comments