runapi-suno 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,9 @@
1
1
  module RunApi
2
2
  module Suno
3
3
  module Resources
4
+ # Adds a timed sample from an uploaded audio file to a music request.
5
+ #
6
+ # @deprecated Use {RunApi::Suno::Resources::MusicFromSample} instead.
4
7
  class AddSamples < AudioAction
5
8
  ENDPOINT = "/api/v1/suno/add_samples"
6
9
  ACTION = "add-samples"
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Exports an existing track to a downloadable audio file.
7
+ class AudioExports
8
+ include RunApi::Core::ResourceHelpers
9
+
10
+ ENDPOINT = "/api/v1/audio_exports"
11
+ RESPONSE_CLASS = Types::AudioExportResponse
12
+ COMPLETED_RESPONSE_CLASS = Types::CompletedAudioExportResponse
13
+
14
+ def initialize(http)
15
+ @http = http
16
+ end
17
+
18
+ def run(options: nil, **params)
19
+ task = create(options: options, **params)
20
+ poll_until_complete { get(task.id, options: options) }
21
+ end
22
+
23
+ def create(options: nil, **params)
24
+ params = compact_params(params)
25
+ validate_params!(params)
26
+ request(:post, ENDPOINT, body: params, options: options)
27
+ end
28
+
29
+ def get(id, options: nil)
30
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
31
+ end
32
+
33
+ private
34
+
35
+ def validate_params!(params)
36
+ Validators.validate_audio_exports!(params, self)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -4,6 +4,8 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Generates style/genre tags from a text description for use in style fields. Synchronous (run only).
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::StyleExpansions} instead.
7
9
  class BoostStyle
8
10
  include RunApi::Core::ResourceHelpers
9
11
 
@@ -4,6 +4,9 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Step 4 of voice cloning: checks whether a custom voice is ready for use. Synchronous (run only).
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::Voices} instead; its +get+ reports the
9
+ # voice resource status directly.
7
10
  class CheckVoice
8
11
  include RunApi::Core::ResourceHelpers
9
12
 
@@ -4,6 +4,8 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Converts a generated track to WAV format.
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::AudioExports} instead.
7
9
  class ConvertAudio
8
10
  include RunApi::Core::ResourceHelpers
9
11
 
@@ -4,6 +4,9 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Creates a reusable style or voice persona from an existing track's vocals. Synchronous (run only).
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::Personas} instead, which returns an
9
+ # account-owned persona resource that later requests reference by ID.
7
10
  class GeneratePersona
8
11
  include RunApi::Core::ResourceHelpers
9
12
 
@@ -4,6 +4,9 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Step 3 of voice cloning: trains a custom voice from the user's recording of the validation phrase.
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::Voices} instead, which creates a
9
+ # reusable voice resource from a recording directly.
7
10
  class GenerateVoice
8
11
  include RunApi::Core::ResourceHelpers
9
12
 
@@ -4,6 +4,8 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Retrieves word-level timing alignment for a track. Synchronous (run only, no create/get polling).
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::TimestampedLyrics} instead.
7
9
  class GetTimestampedLyrics
8
10
  include RunApi::Core::ResourceHelpers
9
11
 
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Creates music guided by a sample of an uploaded audio file.
7
+ class MusicFromSample
8
+ include RunApi::Core::ResourceHelpers
9
+
10
+ ENDPOINT = "/api/v1/music_from_sample"
11
+ RESPONSE_CLASS = Types::MusicFromSampleResponse
12
+ COMPLETED_RESPONSE_CLASS = Types::CompletedMusicFromSampleResponse
13
+
14
+ def initialize(http)
15
+ @http = http
16
+ end
17
+
18
+ def run(options: nil, **params)
19
+ task = create(options: options, **params)
20
+ poll_until_complete { get(task.id, options: options) }
21
+ end
22
+
23
+ def create(options: nil, **params)
24
+ params = compact_params(params)
25
+ validate_params!(params)
26
+ request(:post, ENDPOINT, body: params, options: options)
27
+ end
28
+
29
+ def get(id, options: nil)
30
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
31
+ end
32
+
33
+ private
34
+
35
+ def validate_params!(params)
36
+ Validators.validate_music_from_sample!(params, self)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Renders a visualization video for an existing track.
7
+ class MusicVisualizations
8
+ include RunApi::Core::ResourceHelpers
9
+
10
+ ENDPOINT = "/api/v1/music_visualizations"
11
+ RESPONSE_CLASS = Types::MusicVisualizationResponse
12
+ COMPLETED_RESPONSE_CLASS = Types::CompletedMusicVisualizationResponse
13
+
14
+ def initialize(http)
15
+ @http = http
16
+ end
17
+
18
+ def run(options: nil, **params)
19
+ task = create(options: options, **params)
20
+ poll_until_complete { get(task.id, options: options) }
21
+ end
22
+
23
+ def create(options: nil, **params)
24
+ params = compact_params(params)
25
+ validate_params!(params)
26
+ request(:post, ENDPOINT, body: params, options: options)
27
+ end
28
+
29
+ def get(id, options: nil)
30
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
31
+ end
32
+
33
+ private
34
+
35
+ def validate_params!(params)
36
+ Validators.validate_music_visualizations!(params, self)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Creates and retrieves the personas a music request can reuse.
7
+ #
8
+ # A persona is an account-owned resource: create it once, then pass its ID in
9
+ # the persona_id field of music generation params. Holding the resource ID
10
+ # instead of the creating request keeps a workflow resumable after that request
11
+ # is gone. A request handled inline returns the persona; a request accepted for
12
+ # deferred execution is followed to its stored result.
13
+ class Personas
14
+ include RunApi::Core::ResourceHelpers
15
+
16
+ ENDPOINT = "/api/v1/personas"
17
+ RESPONSE_CLASS = Types::PersonaCreationResponse
18
+ RESOURCE_RESPONSE_CLASS = Types::PersonaResourceResponse
19
+
20
+ def initialize(http)
21
+ @http = http
22
+ end
23
+
24
+ def run(options: nil, **params)
25
+ params = compact_params(params)
26
+ validate_params!(params)
27
+ run_hybrid(ENDPOINT, body: params, options: options, response_class: RESPONSE_CLASS)
28
+ end
29
+
30
+ # Submits a persona request. A request handled inline carries the finished
31
+ # persona; a request accepted for deferred execution carries its task ID
32
+ # and status, plus Location and Retry-After response headers.
33
+ def create(options: nil, **params)
34
+ params = compact_params(params)
35
+ validate_params!(params)
36
+ request(:post, ENDPOINT, body: params, options: options)
37
+ end
38
+
39
+ def subscribe(options: nil, **params)
40
+ params = compact_params(params)
41
+ validate_params!(params)
42
+ subscribe_hybrid(ENDPOINT, body: params, options: options, response_class: RESPONSE_CLASS)
43
+ end
44
+
45
+ # Retrieves a persona resource by its account-owned ID.
46
+ def get(id, options: nil)
47
+ request(:get, "#{ENDPOINT}/#{id}", options: options, response_class: RESOURCE_RESPONSE_CLASS)
48
+ end
49
+
50
+ private
51
+
52
+ def validate_params!(params)
53
+ Validators.validate_personas!(params, self)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Expands a style description into genre tags for use in style fields.
7
+ # Synchronous (run only, no create/get polling).
8
+ class StyleExpansions
9
+ include RunApi::Core::ResourceHelpers
10
+
11
+ ENDPOINT = "/api/v1/style_expansions"
12
+ RESPONSE_CLASS = Types::BoostStyleResponse
13
+
14
+ def initialize(http)
15
+ @http = http
16
+ end
17
+
18
+ def run(options: nil, **params)
19
+ params = compact_params(params)
20
+ validate_params!(params)
21
+ request(:post, ENDPOINT, body: params, options: options)
22
+ end
23
+
24
+ private
25
+
26
+ def validate_params!(params)
27
+ Validators.validate_style_expansions!(params, self)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Retrieves word-level timing alignment for an existing track.
7
+ # Synchronous (run only, no create/get polling).
8
+ class TimestampedLyrics
9
+ include RunApi::Core::ResourceHelpers
10
+
11
+ ENDPOINT = "/api/v1/timestamped_lyrics"
12
+ RESPONSE_CLASS = Types::TimestampedLyricsResponse
13
+
14
+ def initialize(http)
15
+ @http = http
16
+ end
17
+
18
+ def run(options: nil, **params)
19
+ params = compact_params(params)
20
+ validate_params!(params)
21
+ request(:post, ENDPOINT, body: params, options: options)
22
+ end
23
+
24
+ private
25
+
26
+ def validate_params!(params)
27
+ Validators.validate_timestamped_lyrics!(params, self)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -4,6 +4,8 @@ module RunApi
4
4
  module Suno
5
5
  module Resources
6
6
  # Generates a music visualization video from an existing track.
7
+ #
8
+ # @deprecated Use {RunApi::Suno::Resources::MusicVisualizations} instead.
7
9
  class VisualizeMusic
8
10
  include RunApi::Core::ResourceHelpers
9
11
 
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Resources
6
+ # Creates and retrieves voices a music request can reuse.
7
+ #
8
+ # A voice is an account-owned resource: create it from a recording, then pass its
9
+ # ID wherever a voice persona is accepted. +get+ reports whether the voice is
10
+ # ready, so readiness needs no separate request.
11
+ class Voices
12
+ include RunApi::Core::ResourceHelpers
13
+
14
+ ENDPOINT = "/api/v1/voices"
15
+ RESPONSE_CLASS = Types::VoiceCreationResponse
16
+ RESOURCE_RESPONSE_CLASS = Types::VoiceResourceResponse
17
+
18
+ def initialize(http)
19
+ @http = http
20
+ end
21
+
22
+ def run(options: nil, **params)
23
+ params = compact_params(params)
24
+ validate_params!(params)
25
+ request(:post, ENDPOINT, body: params, options: options)
26
+ end
27
+
28
+ # Retrieves a voice resource by its account-owned ID.
29
+ def get(id, options: nil)
30
+ request(:get, "#{ENDPOINT}/#{id}", options: options, response_class: RESOURCE_RESPONSE_CLASS)
31
+ end
32
+
33
+ private
34
+
35
+ def validate_params!(params)
36
+ Validators.validate_voices!(params, self)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Types
6
+ class CompletedTextToMusicResponse < TextToMusicResponse
7
+ required :audios, [-> { Audio }]
8
+ end
9
+
10
+ class CompletedExtendMusicResponse < ExtendMusicResponse
11
+ required :audios, [-> { Audio }]
12
+ end
13
+
14
+ class CompletedGenerateArtworkResponse < GenerateArtworkResponse
15
+ required :covers, [-> { Cover }]
16
+ end
17
+
18
+ class CompletedCoverAudioResponse < CoverAudioResponse
19
+ required :audios, [-> { Audio }]
20
+ end
21
+
22
+ class CompletedAddInstrumentalResponse < AddInstrumentalResponse
23
+ required :audios, [-> { Audio }]
24
+ end
25
+
26
+ class CompletedAddVocalsResponse < AddVocalsResponse
27
+ required :audios, [-> { Audio }]
28
+ end
29
+
30
+ class CompletedSeparateAudioStemsResponse < SeparateAudioStemsResponse
31
+ required :separated_audios, -> { SeparatedAudio }
32
+ end
33
+
34
+ class CompletedGenerateMidiResponse < GenerateMidiResponse
35
+ required :instruments, [-> { MidiInstrument }]
36
+ end
37
+
38
+ class CompletedConvertAudioResponse < ConvertAudioResponse
39
+ required :wav_url, String
40
+ end
41
+
42
+ class CompletedVisualizeMusicResponse < VisualizeMusicResponse
43
+ required :video_url, String
44
+ end
45
+
46
+ class CompletedGenerateLyricsResponse < GenerateLyricsResponse
47
+ required :lyrics, [-> { Lyric }]
48
+ end
49
+
50
+ class CompletedBlendLyricsResponse < BlendLyricsResponse
51
+ required :lyrics, [-> { Lyric }]
52
+ end
53
+
54
+ class CompletedReplaceSectionResponse < ReplaceSectionResponse
55
+ required :track, -> { Audio }
56
+ end
57
+
58
+ class CompletedCreateMashupResponse < CreateMashupResponse
59
+ required :audios, [-> { Audio }]
60
+ end
61
+
62
+ class CompletedTextToSoundResponse < TextToSoundResponse
63
+ required :audios, [-> { SoundAudio }]
64
+ end
65
+
66
+ class CompletedValidationPhraseResponse < ValidationPhraseResponse
67
+ required :validation_phrase, String
68
+ end
69
+
70
+ class CompletedVoiceGenerationResponse < VoiceGenerationResponse
71
+ required :voice_id, String
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Suno
5
+ module Types
6
+ module ResourceStatus
7
+ AVAILABLE = "available"
8
+ FAILED = "failed"
9
+
10
+ ALL = [AVAILABLE, FAILED].freeze
11
+ end
12
+
13
+ # Billing envelope for a resource lookup. Resource provenance remains opaque.
14
+ class ResourceBilling < RunApi::Core::BaseModel
15
+ end
16
+
17
+ class PersonaResource < RunApi::Core::BaseModel
18
+ required :id, String
19
+ optional :name, String
20
+ optional :description, String
21
+ end
22
+
23
+ class VoiceResource < RunApi::Core::BaseModel
24
+ required :id, String
25
+ optional :name, String
26
+ end
27
+
28
+ class PersonaCreationResponse < RunApi::Core::BaseModel
29
+ optional :persona, -> { PersonaResource }
30
+ optional :id, String
31
+ optional :status, String
32
+ optional :error, String
33
+ optional :billing, RunApi::Core::TaskBillingFacts
34
+ end
35
+
36
+ class VoiceCreationResponse < RunApi::Core::BaseModel
37
+ required :voice, -> { VoiceResource }
38
+ optional :billing, RunApi::Core::TaskBillingFacts
39
+ end
40
+
41
+ class TimestampedLyricsResponse < RunApi::Core::BaseModel
42
+ optional :aligned_words, [-> { AlignedWord }]
43
+ optional :waveform_data, [Numeric]
44
+ optional :hoct_cer, Numeric
45
+ optional :is_streamed
46
+ optional :billing, RunApi::Core::TaskBillingFacts
47
+ end
48
+
49
+ class PersonaResourceResponse < RunApi::Core::BaseModel
50
+ required :persona, -> { PersonaResource }
51
+ required :status, String, enum: -> { ResourceStatus::ALL }
52
+ required :billing, ResourceBilling
53
+ end
54
+
55
+ class VoiceResourceResponse < RunApi::Core::BaseModel
56
+ required :voice, -> { VoiceResource }
57
+ required :status, String, enum: -> { ResourceStatus::ALL }
58
+ required :billing, ResourceBilling
59
+ end
60
+
61
+ class AudioExportResponse < AsyncTaskResponse
62
+ optional :wav_url, String
63
+ optional :original_task_id, String
64
+ end
65
+
66
+ class MusicVisualizationResponse < AsyncTaskResponse
67
+ optional :video_url, String
68
+ optional :original_task_id, String
69
+ end
70
+
71
+ class MusicFromSampleResponse < AsyncTaskResponse
72
+ optional :audios, [-> { Audio }]
73
+ end
74
+
75
+ class CompletedAudioExportResponse < AudioExportResponse
76
+ required :wav_url, String
77
+ end
78
+
79
+ class CompletedMusicVisualizationResponse < MusicVisualizationResponse
80
+ required :video_url, String
81
+ end
82
+
83
+ class CompletedMusicFromSampleResponse < MusicFromSampleResponse
84
+ required :audios, [-> { Audio }]
85
+ end
86
+ end
87
+ end
88
+ end
@@ -5,7 +5,7 @@ module RunApi
5
5
  # Suno type definitions, response models, and enum constants.
6
6
  module Types
7
7
  # Suno music generation engine versions. V5.5 has highest quality; V4 is the earliest available.
8
- MODELS = %w[suno-v5.5 suno-v5 suno-v4.5-plus suno-v4.5-all suno-v4.5 suno-v4].freeze
8
+ MODELS = %w[suno-v6 suno-v6-wild suno-v6-mini suno-v5.5 suno-v5 suno-v4.5-plus suno-v4.5-all suno-v4.5 suno-v4].freeze
9
9
  # Model versions that support sound effect generation (subset of MODELS).
10
10
  SOUND_MODELS = %w[suno-v5 suno-v5.5].freeze
11
11
  # Musical keys (major and minor) for sound effect generation.
@@ -251,74 +251,6 @@ module RunApi
251
251
  optional :error, String
252
252
  optional :billing, RunApi::Core::TaskBillingFacts
253
253
  end
254
-
255
- class CompletedTextToMusicResponse < TextToMusicResponse
256
- required :audios, [-> { Audio }]
257
- end
258
-
259
- class CompletedExtendMusicResponse < ExtendMusicResponse
260
- required :audios, [-> { Audio }]
261
- end
262
-
263
- class CompletedGenerateArtworkResponse < GenerateArtworkResponse
264
- required :covers, [-> { Cover }]
265
- end
266
-
267
- class CompletedCoverAudioResponse < CoverAudioResponse
268
- required :audios, [-> { Audio }]
269
- end
270
-
271
- class CompletedAddInstrumentalResponse < AddInstrumentalResponse
272
- required :audios, [-> { Audio }]
273
- end
274
-
275
- class CompletedAddVocalsResponse < AddVocalsResponse
276
- required :audios, [-> { Audio }]
277
- end
278
-
279
- class CompletedSeparateAudioStemsResponse < SeparateAudioStemsResponse
280
- required :separated_audios, -> { SeparatedAudio }
281
- end
282
-
283
- class CompletedGenerateMidiResponse < GenerateMidiResponse
284
- required :instruments, [-> { MidiInstrument }]
285
- end
286
-
287
- class CompletedConvertAudioResponse < ConvertAudioResponse
288
- required :wav_url, String
289
- end
290
-
291
- class CompletedVisualizeMusicResponse < VisualizeMusicResponse
292
- required :video_url, String
293
- end
294
-
295
- class CompletedGenerateLyricsResponse < GenerateLyricsResponse
296
- required :lyrics, [-> { Lyric }]
297
- end
298
-
299
- class CompletedBlendLyricsResponse < BlendLyricsResponse
300
- required :lyrics, [-> { Lyric }]
301
- end
302
-
303
- class CompletedReplaceSectionResponse < ReplaceSectionResponse
304
- required :track, -> { Audio }
305
- end
306
-
307
- class CompletedCreateMashupResponse < CreateMashupResponse
308
- required :audios, [-> { Audio }]
309
- end
310
-
311
- class CompletedTextToSoundResponse < TextToSoundResponse
312
- required :audios, [-> { SoundAudio }]
313
- end
314
-
315
- class CompletedValidationPhraseResponse < ValidationPhraseResponse
316
- required :validation_phrase, String
317
- end
318
-
319
- class CompletedVoiceGenerationResponse < VoiceGenerationResponse
320
- required :voice_id, String
321
- end
322
254
  end
323
255
  end
324
256
  end
@@ -133,6 +133,34 @@ module RunApi
133
133
  require_param!(resource, params, :description)
134
134
  end
135
135
 
136
+ def validate_personas!(params, resource)
137
+ resource.send(:validate_contract!, CONTRACT["personas"], params)
138
+ end
139
+
140
+ def validate_voices!(params, resource)
141
+ resource.send(:validate_contract!, CONTRACT["voices"], params)
142
+ end
143
+
144
+ def validate_style_expansions!(params, resource)
145
+ resource.send(:validate_contract!, CONTRACT["style-expansions"], params)
146
+ end
147
+
148
+ def validate_timestamped_lyrics!(params, resource)
149
+ resource.send(:validate_contract!, CONTRACT["timestamped-lyrics"], params)
150
+ end
151
+
152
+ def validate_audio_exports!(params, resource)
153
+ resource.send(:validate_contract!, CONTRACT["audio-exports"], params)
154
+ end
155
+
156
+ def validate_music_visualizations!(params, resource)
157
+ resource.send(:validate_contract!, CONTRACT["music-visualizations"], params)
158
+ end
159
+
160
+ def validate_music_from_sample!(params, resource)
161
+ resource.send(:validate_contract!, CONTRACT["music-from-sample"], params)
162
+ end
163
+
136
164
  def validate_extend_music_prompt_shape!(params, resource)
137
165
  return unless truthy_presence?(param(resource, params, :lyrics))
138
166
 
data/lib/runapi/suno.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "runapi/core"
4
4
  require_relative "suno/types"
5
+ require_relative "suno/types/completed_responses"
6
+ require_relative "suno/types/resource_responses"
5
7
  require_relative "suno/contract_gen"
6
8
  require_relative "suno/validators"
7
9
  require_relative "suno/resources/text_to_music"
@@ -31,6 +33,13 @@ require_relative "suno/resources/generate_voice"
31
33
  require_relative "suno/resources/check_voice"
32
34
  require_relative "suno/resources/generate_persona"
33
35
  require_relative "suno/resources/boost_style"
36
+ require_relative "suno/resources/personas"
37
+ require_relative "suno/resources/voices"
38
+ require_relative "suno/resources/style_expansions"
39
+ require_relative "suno/resources/timestamped_lyrics"
40
+ require_relative "suno/resources/audio_exports"
41
+ require_relative "suno/resources/music_visualizations"
42
+ require_relative "suno/resources/music_from_sample"
34
43
  require_relative "suno/client"
35
44
 
36
45
  module RunApi