runapi-suno 0.1.0__tar.gz

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.
Files changed (33) hide show
  1. runapi_suno-0.1.0/.gitignore +29 -0
  2. runapi_suno-0.1.0/PKG-INFO +103 -0
  3. runapi_suno-0.1.0/README.md +90 -0
  4. runapi_suno-0.1.0/pyproject.toml +33 -0
  5. runapi_suno-0.1.0/src/runapi/suno/__init__.py +24 -0
  6. runapi_suno-0.1.0/src/runapi/suno/_validators.py +208 -0
  7. runapi_suno-0.1.0/src/runapi/suno/client.py +70 -0
  8. runapi_suno-0.1.0/src/runapi/suno/contract_gen.py +723 -0
  9. runapi_suno-0.1.0/src/runapi/suno/py.typed +0 -0
  10. runapi_suno-0.1.0/src/runapi/suno/resources/__init__.py +45 -0
  11. runapi_suno-0.1.0/src/runapi/suno/resources/add_instrumental.py +58 -0
  12. runapi_suno-0.1.0/src/runapi/suno/resources/add_vocals.py +58 -0
  13. runapi_suno-0.1.0/src/runapi/suno/resources/boost_style.py +34 -0
  14. runapi_suno-0.1.0/src/runapi/suno/resources/check_voice.py +34 -0
  15. runapi_suno-0.1.0/src/runapi/suno/resources/convert_audio.py +58 -0
  16. runapi_suno-0.1.0/src/runapi/suno/resources/cover_audio.py +58 -0
  17. runapi_suno-0.1.0/src/runapi/suno/resources/create_mashup.py +61 -0
  18. runapi_suno-0.1.0/src/runapi/suno/resources/extend_music.py +58 -0
  19. runapi_suno-0.1.0/src/runapi/suno/resources/generate_artwork.py +58 -0
  20. runapi_suno-0.1.0/src/runapi/suno/resources/generate_lyrics.py +58 -0
  21. runapi_suno-0.1.0/src/runapi/suno/resources/generate_midi.py +58 -0
  22. runapi_suno-0.1.0/src/runapi/suno/resources/generate_persona.py +34 -0
  23. runapi_suno-0.1.0/src/runapi/suno/resources/generate_voice.py +58 -0
  24. runapi_suno-0.1.0/src/runapi/suno/resources/get_timestamped_lyrics.py +34 -0
  25. runapi_suno-0.1.0/src/runapi/suno/resources/regenerate_validation_phrase.py +58 -0
  26. runapi_suno-0.1.0/src/runapi/suno/resources/replace_section.py +58 -0
  27. runapi_suno-0.1.0/src/runapi/suno/resources/separate_audio_stems.py +58 -0
  28. runapi_suno-0.1.0/src/runapi/suno/resources/text_to_music.py +58 -0
  29. runapi_suno-0.1.0/src/runapi/suno/resources/text_to_sound.py +58 -0
  30. runapi_suno-0.1.0/src/runapi/suno/resources/visualize_music.py +58 -0
  31. runapi_suno-0.1.0/src/runapi/suno/resources/voice_to_validation_phrase.py +58 -0
  32. runapi_suno-0.1.0/src/runapi/suno/types.py +366 -0
  33. runapi_suno-0.1.0/tests/test_client.py +320 -0
@@ -0,0 +1,29 @@
1
+ # Build artifacts
2
+ dist/
3
+ build/
4
+ *.egg-info/
5
+ *.egg
6
+
7
+ # Bytecode
8
+ __pycache__/
9
+ *.py[cod]
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+
15
+ # uv
16
+ uv.lock
17
+
18
+ # Test / type caches
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+ .coverage
23
+ htmlcov/
24
+
25
+ # IDE / OS
26
+ .idea/
27
+ .vscode/
28
+ *.swp
29
+ .DS_Store
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: runapi-suno
3
+ Version: 0.1.0
4
+ Summary: Suno music, sound, lyrics, and voice client for RunAPI
5
+ Project-URL: Homepage, https://runapi.ai/models/suno
6
+ Project-URL: Documentation, https://runapi.ai/docs#sdk-suno
7
+ Author-email: RunAPI <contact@runapi.ai>
8
+ License-Expression: Apache-2.0
9
+ Keywords: ai,audio,lyrics,music,runapi,sdk,suno,voice
10
+ Requires-Python: >=3.9
11
+ Requires-Dist: runapi-core
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Suno Python SDK for RunAPI
15
+
16
+ The Suno Python SDK is the language-specific package for Suno on RunAPI. Use it
17
+ for music, sound effect, lyrics, stem, MIDI, and custom voice flows when your
18
+ application needs JSON request bodies, task status lookup, and consistent RunAPI
19
+ errors in Python.
20
+
21
+ For model details, use https://runapi.ai/models/suno; for API reference, use
22
+ https://runapi.ai/docs#suno; for SDK docs, use https://runapi.ai/docs#sdk-suno.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install runapi-suno
28
+ ```
29
+
30
+ ## Quick start
31
+
32
+ ```python
33
+ from runapi.suno import SunoClient
34
+
35
+ client = SunoClient() # reads RUNAPI_API_KEY, or pass api_key="sk-..."
36
+
37
+ # Generate music and poll until completion.
38
+ result = client.text_to_music.run(
39
+ model="suno-v4.5-plus",
40
+ vocal_mode="auto_lyrics",
41
+ prompt="A chill lo-fi beat with soft vocals",
42
+ )
43
+ print(result.audios[0].audio_url)
44
+
45
+ # Generate lyrics from a prompt.
46
+ lyrics = client.generate_lyrics.run(prompt="a song about the ocean at night")
47
+ print(lyrics.lyrics[0].text)
48
+ ```
49
+
50
+ Use `create` to submit a task and return quickly, `get` to fetch the latest task
51
+ state, and `run` to create and poll until completion:
52
+
53
+ ```python
54
+ task = client.text_to_music.create(
55
+ model="suno-v4.5-plus",
56
+ vocal_mode="instrumental",
57
+ style="ambient piano",
58
+ title="Quiet Morning",
59
+ )
60
+ status = client.text_to_music.get(task.id)
61
+ ```
62
+
63
+ In web request handlers, prefer `create` plus webhook or later `get` polling so a
64
+ worker is not held open.
65
+
66
+ RunAPI-generated file URLs are temporary. Download and store generated audio,
67
+ images, and videos in your own durable storage within 7 days; do not treat
68
+ returned URLs as long-term assets.
69
+
70
+ ## Resources
71
+
72
+ The client exposes one accessor per resource:
73
+
74
+ - Music: `text_to_music`, `extend_music`, `cover_audio`, `add_instrumental`,
75
+ `add_vocals`, `replace_section`, `create_mashup`
76
+ - Sound and lyrics: `text_to_sound`, `generate_lyrics`, `get_timestamped_lyrics`
77
+ - Audio tooling: `separate_audio_stems`, `generate_midi`, `convert_audio`,
78
+ `visualize_music`, `generate_artwork`
79
+ - Voice and style: `voice_to_validation_phrase`, `regenerate_validation_phrase`,
80
+ `generate_voice`, `check_voice`, `generate_persona`, `boost_style`
81
+
82
+ Music, sound, stem, MIDI, conversion, visualization, artwork, replace-section,
83
+ mashup, validation-phrase, and voice resources are asynchronous: call `run` to
84
+ create and poll, or `create` plus `get`. Lyrics lookup, persona, voice check,
85
+ and style boost return their result directly from `run`.
86
+
87
+ ## Language notes
88
+
89
+ Pass parameters as keyword arguments and catch the `runapi.suno` error classes
90
+ when building audio jobs or scripts. Keep `RUNAPI_API_KEY` in the environment or
91
+ your secret manager; never commit API keys or callback secrets.
92
+
93
+ ## Links
94
+
95
+ - Model page: https://runapi.ai/models/suno
96
+ - SDK docs: https://runapi.ai/docs#sdk-suno
97
+ - Product docs: https://runapi.ai/docs#suno
98
+ - Pricing and rate limits: https://runapi.ai/models/suno
99
+ - Full catalog: https://runapi.ai/models
100
+
101
+ ## License
102
+
103
+ Licensed under the Apache License, Version 2.0.
@@ -0,0 +1,90 @@
1
+ # Suno Python SDK for RunAPI
2
+
3
+ The Suno Python SDK is the language-specific package for Suno on RunAPI. Use it
4
+ for music, sound effect, lyrics, stem, MIDI, and custom voice flows when your
5
+ application needs JSON request bodies, task status lookup, and consistent RunAPI
6
+ errors in Python.
7
+
8
+ For model details, use https://runapi.ai/models/suno; for API reference, use
9
+ https://runapi.ai/docs#suno; for SDK docs, use https://runapi.ai/docs#sdk-suno.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install runapi-suno
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```python
20
+ from runapi.suno import SunoClient
21
+
22
+ client = SunoClient() # reads RUNAPI_API_KEY, or pass api_key="sk-..."
23
+
24
+ # Generate music and poll until completion.
25
+ result = client.text_to_music.run(
26
+ model="suno-v4.5-plus",
27
+ vocal_mode="auto_lyrics",
28
+ prompt="A chill lo-fi beat with soft vocals",
29
+ )
30
+ print(result.audios[0].audio_url)
31
+
32
+ # Generate lyrics from a prompt.
33
+ lyrics = client.generate_lyrics.run(prompt="a song about the ocean at night")
34
+ print(lyrics.lyrics[0].text)
35
+ ```
36
+
37
+ Use `create` to submit a task and return quickly, `get` to fetch the latest task
38
+ state, and `run` to create and poll until completion:
39
+
40
+ ```python
41
+ task = client.text_to_music.create(
42
+ model="suno-v4.5-plus",
43
+ vocal_mode="instrumental",
44
+ style="ambient piano",
45
+ title="Quiet Morning",
46
+ )
47
+ status = client.text_to_music.get(task.id)
48
+ ```
49
+
50
+ In web request handlers, prefer `create` plus webhook or later `get` polling so a
51
+ worker is not held open.
52
+
53
+ RunAPI-generated file URLs are temporary. Download and store generated audio,
54
+ images, and videos in your own durable storage within 7 days; do not treat
55
+ returned URLs as long-term assets.
56
+
57
+ ## Resources
58
+
59
+ The client exposes one accessor per resource:
60
+
61
+ - Music: `text_to_music`, `extend_music`, `cover_audio`, `add_instrumental`,
62
+ `add_vocals`, `replace_section`, `create_mashup`
63
+ - Sound and lyrics: `text_to_sound`, `generate_lyrics`, `get_timestamped_lyrics`
64
+ - Audio tooling: `separate_audio_stems`, `generate_midi`, `convert_audio`,
65
+ `visualize_music`, `generate_artwork`
66
+ - Voice and style: `voice_to_validation_phrase`, `regenerate_validation_phrase`,
67
+ `generate_voice`, `check_voice`, `generate_persona`, `boost_style`
68
+
69
+ Music, sound, stem, MIDI, conversion, visualization, artwork, replace-section,
70
+ mashup, validation-phrase, and voice resources are asynchronous: call `run` to
71
+ create and poll, or `create` plus `get`. Lyrics lookup, persona, voice check,
72
+ and style boost return their result directly from `run`.
73
+
74
+ ## Language notes
75
+
76
+ Pass parameters as keyword arguments and catch the `runapi.suno` error classes
77
+ when building audio jobs or scripts. Keep `RUNAPI_API_KEY` in the environment or
78
+ your secret manager; never commit API keys or callback secrets.
79
+
80
+ ## Links
81
+
82
+ - Model page: https://runapi.ai/models/suno
83
+ - SDK docs: https://runapi.ai/docs#sdk-suno
84
+ - Product docs: https://runapi.ai/docs#suno
85
+ - Pricing and rate limits: https://runapi.ai/models/suno
86
+ - Full catalog: https://runapi.ai/models
87
+
88
+ ## License
89
+
90
+ Licensed under the Apache License, Version 2.0.
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "runapi-suno"
7
+ version = "0.1.0"
8
+ description = "Suno music, sound, lyrics, and voice client for RunAPI"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "Apache-2.0"
12
+ authors = [{ name = "RunAPI", email = "contact@runapi.ai" }]
13
+ keywords = ["runapi", "suno", "music", "audio", "lyrics", "voice", "ai", "sdk"]
14
+ dependencies = ["runapi-core"]
15
+
16
+ [project.urls]
17
+ Homepage = "https://runapi.ai/models/suno"
18
+ Documentation = "https://runapi.ai/docs#sdk-suno"
19
+
20
+ [tool.hatch.build.targets.wheel]
21
+ packages = ["src/runapi"]
22
+
23
+ [tool.uv]
24
+ package = true
25
+
26
+ [tool.uv.sources]
27
+ runapi-core = { workspace = true }
28
+
29
+ [dependency-groups]
30
+ dev = ["pytest>=8"]
31
+
32
+ [tool.runapi]
33
+ slug = "suno"
@@ -0,0 +1,24 @@
1
+ """Suno client for RunAPI."""
2
+
3
+ from runapi.core import (
4
+ AuthenticationError,
5
+ InsufficientCreditsError,
6
+ NotFoundError,
7
+ RateLimitError,
8
+ TaskFailedError,
9
+ TaskTimeoutError,
10
+ ValidationError,
11
+ )
12
+
13
+ from .client import SunoClient
14
+
15
+ __all__ = [
16
+ "SunoClient",
17
+ "AuthenticationError",
18
+ "RateLimitError",
19
+ "InsufficientCreditsError",
20
+ "NotFoundError",
21
+ "ValidationError",
22
+ "TaskFailedError",
23
+ "TaskTimeoutError",
24
+ ]
@@ -0,0 +1,208 @@
1
+ """Shared Suno request validators.
2
+
3
+ Ported from the Ruby ``RunApi::Suno::Validators`` module. Each ``validate_*``
4
+ function mirrors its Ruby counterpart, including the exact ``ValidationError``
5
+ message strings. Resources call these from their ``_validate_params`` hook.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, Sequence
11
+
12
+ from runapi.core import ValidationError
13
+
14
+ from . import types
15
+
16
+ _TRUTHY_VALUES = [True, 1, "1", "true", "TRUE", "True"]
17
+
18
+
19
+ def _param(params: Dict[str, Any], key: str) -> Any:
20
+ return params.get(key)
21
+
22
+
23
+ def _truthy(value: Any) -> bool:
24
+ return value in _TRUTHY_VALUES
25
+
26
+
27
+ def _truthy_presence(value: Any) -> bool:
28
+ if hasattr(value, "__len__"):
29
+ return len(value) > 0
30
+ return value is not None
31
+
32
+
33
+ def _to_i(value: Any) -> int:
34
+ try:
35
+ return int(value)
36
+ except (TypeError, ValueError):
37
+ if isinstance(value, str):
38
+ digits = ""
39
+ for ch in value.strip():
40
+ if ch in "+-" and not digits:
41
+ digits += ch
42
+ elif ch.isdigit():
43
+ digits += ch
44
+ else:
45
+ break
46
+ try:
47
+ return int(digits)
48
+ except ValueError:
49
+ return 0
50
+ return 0
51
+
52
+
53
+ def _to_f(value: Any) -> float:
54
+ try:
55
+ return float(value)
56
+ except (TypeError, ValueError):
57
+ return 0.0
58
+
59
+
60
+ def require_param(params: Dict[str, Any], key: str) -> None:
61
+ if _param(params, key) is None:
62
+ raise ValidationError(f"{key} is required")
63
+
64
+
65
+ def require_all(params: Dict[str, Any], *keys: str) -> None:
66
+ for key in keys:
67
+ require_param(params, key)
68
+
69
+
70
+ def validate_optional(params: Dict[str, Any], key: str, allowed: Sequence[Any]) -> None:
71
+ value = params.get(key)
72
+ if value is None:
73
+ return
74
+ if value not in allowed:
75
+ joined = ", ".join(str(option) for option in allowed)
76
+ raise ValidationError(f"Invalid {key}: {value}. Must be one of: {joined}")
77
+
78
+
79
+ def validate_extend_music_prompt_shape(params: Dict[str, Any]) -> None:
80
+ if not _truthy_presence(_param(params, "lyrics")):
81
+ return
82
+
83
+ if _truthy_presence(_param(params, "prompt")):
84
+ raise ValidationError("prompt cannot be combined with lyrics")
85
+
86
+ if _truthy(_param(params, "instrumental")):
87
+ raise ValidationError("lyrics cannot be used when instrumental is true")
88
+
89
+ upload_mode = any(_truthy_presence(_param(params, key)) for key in ("audio_url", "upload_url"))
90
+ if _param(params, "parameter_mode") == "custom" and upload_mode:
91
+ return
92
+
93
+ raise ValidationError("lyrics can only be used when extending uploaded audio with custom parameters")
94
+
95
+
96
+ def validate_extend_music(params: Dict[str, Any]) -> None:
97
+ if not any(_param(params, key) for key in ("task_id", "audio_id", "audio_url", "upload_url")):
98
+ raise ValidationError("task_id, audio_id, audio_url, or upload_url is required")
99
+ require_param(params, "parameter_mode")
100
+ require_param(params, "model")
101
+
102
+ validate_optional(params, "parameter_mode", types.PARAMETER_MODES)
103
+ if _param(params, "parameter_mode") == "custom":
104
+ require_param(params, "style")
105
+ require_param(params, "title")
106
+ require_param(params, "continue_at")
107
+ validate_extend_music_prompt_shape(params)
108
+ validate_optional(params, "model", types.MODELS)
109
+ validate_optional(params, "vocal_gender", types.VOCAL_GENDERS)
110
+ validate_optional(params, "persona_type", types.PERSONA_TYPES)
111
+
112
+
113
+ def validate_generate_artwork(params: Dict[str, Any]) -> None:
114
+ require_param(params, "task_id")
115
+
116
+
117
+ def validate_add_instrumental(params: Dict[str, Any]) -> None:
118
+ require_all(params, "upload_url", "title", "negative_tags", "tags", "model")
119
+ validate_optional(params, "model", types.MODELS)
120
+ validate_optional(params, "vocal_gender", types.VOCAL_GENDERS)
121
+
122
+
123
+ def validate_add_vocals(params: Dict[str, Any]) -> None:
124
+ require_all(params, "upload_url", "lyrics", "title", "negative_tags", "style", "model")
125
+ validate_optional(params, "model", types.MODELS)
126
+ validate_optional(params, "vocal_gender", types.VOCAL_GENDERS)
127
+
128
+
129
+ def validate_separate_audio_stems(params: Dict[str, Any]) -> None:
130
+ require_all(params, "task_id", "audio_id")
131
+ validate_optional(params, "type", types.SEPARATE_AUDIO_STEMS_TYPES)
132
+
133
+
134
+ def validate_generate_midi(params: Dict[str, Any]) -> None:
135
+ require_param(params, "task_id")
136
+
137
+
138
+ def validate_convert_audio(params: Dict[str, Any]) -> None:
139
+ require_all(params, "task_id", "audio_id")
140
+
141
+
142
+ def validate_visualize_music(params: Dict[str, Any]) -> None:
143
+ require_all(params, "task_id", "audio_id")
144
+
145
+
146
+ def validate_generate_lyrics(params: Dict[str, Any]) -> None:
147
+ require_param(params, "prompt")
148
+
149
+
150
+ def validate_get_timestamped_lyrics(params: Dict[str, Any]) -> None:
151
+ require_all(params, "task_id", "audio_id")
152
+
153
+
154
+ def validate_replace_section(params: Dict[str, Any]) -> None:
155
+ require_all(
156
+ params,
157
+ "task_id",
158
+ "audio_id",
159
+ "lyrics",
160
+ "tags",
161
+ "title",
162
+ "infill_start_time",
163
+ "infill_end_time",
164
+ )
165
+ if _to_f(_param(params, "infill_end_time")) <= _to_f(_param(params, "infill_start_time")):
166
+ raise ValidationError("infill_end_time must be greater than infill_start_time")
167
+
168
+
169
+ def validate_text_to_sound(params: Dict[str, Any]) -> None:
170
+ require_all(params, "prompt", "model")
171
+ validate_optional(params, "model", types.SOUND_MODELS)
172
+ validate_optional(params, "sound_key", types.SOUND_KEYS)
173
+ tempo = _param(params, "sound_tempo")
174
+ if tempo is not None and not (1 <= _to_i(tempo) <= 300):
175
+ raise ValidationError("sound_tempo must be between 1 and 300")
176
+
177
+
178
+ def validate_voice_to_validation_phrase(params: Dict[str, Any]) -> None:
179
+ require_all(params, "voice_url", "vocal_start_seconds", "vocal_end_seconds")
180
+ validate_optional(params, "language", types.VALIDATION_PHRASE_LANGUAGES)
181
+
182
+ start_seconds = _to_i(_param(params, "vocal_start_seconds"))
183
+ end_seconds = _to_i(_param(params, "vocal_end_seconds"))
184
+ if end_seconds > start_seconds:
185
+ return
186
+
187
+ raise ValidationError("vocal_end_seconds must be greater than vocal_start_seconds")
188
+
189
+
190
+ def validate_regenerate_validation_phrase(params: Dict[str, Any]) -> None:
191
+ require_param(params, "task_id")
192
+
193
+
194
+ def validate_generate_voice(params: Dict[str, Any]) -> None:
195
+ require_all(params, "task_id", "verify_url")
196
+ validate_optional(params, "singer_skill_level", types.SINGER_SKILL_LEVELS)
197
+
198
+
199
+ def validate_check_voice(params: Dict[str, Any]) -> None:
200
+ require_param(params, "task_id")
201
+
202
+
203
+ def validate_generate_persona(params: Dict[str, Any]) -> None:
204
+ require_all(params, "task_id", "audio_id", "name", "description")
205
+
206
+
207
+ def validate_boost_style(params: Dict[str, Any]) -> None:
208
+ require_param(params, "description")
@@ -0,0 +1,70 @@
1
+ """Suno client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from runapi.core import ClientOptions, HttpClient, resolve_api_key
8
+
9
+ from .resources.add_instrumental import AddInstrumental
10
+ from .resources.add_vocals import AddVocals
11
+ from .resources.boost_style import BoostStyle
12
+ from .resources.check_voice import CheckVoice
13
+ from .resources.convert_audio import ConvertAudio
14
+ from .resources.cover_audio import CoverAudio
15
+ from .resources.create_mashup import CreateMashup
16
+ from .resources.extend_music import ExtendMusic
17
+ from .resources.generate_artwork import GenerateArtwork
18
+ from .resources.generate_lyrics import GenerateLyrics
19
+ from .resources.generate_midi import GenerateMidi
20
+ from .resources.generate_persona import GeneratePersona
21
+ from .resources.generate_voice import GenerateVoice
22
+ from .resources.get_timestamped_lyrics import GetTimestampedLyrics
23
+ from .resources.regenerate_validation_phrase import RegenerateValidationPhrase
24
+ from .resources.replace_section import ReplaceSection
25
+ from .resources.separate_audio_stems import SeparateAudioStems
26
+ from .resources.text_to_music import TextToMusic
27
+ from .resources.text_to_sound import TextToSound
28
+ from .resources.visualize_music import VisualizeMusic
29
+ from .resources.voice_to_validation_phrase import VoiceToValidationPhrase
30
+
31
+
32
+ class SunoClient:
33
+ """Suno music, sound, lyrics, and voice client.
34
+
35
+ Example::
36
+
37
+ client = SunoClient(api_key="sk-...")
38
+ result = client.text_to_music.run(
39
+ prompt="A chill lo-fi beat with soft vocals",
40
+ model="suno-v4.5-plus",
41
+ vocal_mode="auto_lyrics",
42
+ )
43
+ """
44
+
45
+ def __init__(self, api_key: Optional[str] = None, **options: Any) -> None:
46
+ resolved_api_key = resolve_api_key(api_key)
47
+ client_options = ClientOptions(api_key=resolved_api_key, **options)
48
+ http = client_options.http_client or HttpClient(client_options)
49
+
50
+ self.text_to_music = TextToMusic(http)
51
+ self.extend_music = ExtendMusic(http)
52
+ self.generate_artwork = GenerateArtwork(http)
53
+ self.cover_audio = CoverAudio(http)
54
+ self.add_instrumental = AddInstrumental(http)
55
+ self.add_vocals = AddVocals(http)
56
+ self.separate_audio_stems = SeparateAudioStems(http)
57
+ self.generate_midi = GenerateMidi(http)
58
+ self.convert_audio = ConvertAudio(http)
59
+ self.visualize_music = VisualizeMusic(http)
60
+ self.generate_lyrics = GenerateLyrics(http)
61
+ self.get_timestamped_lyrics = GetTimestampedLyrics(http)
62
+ self.replace_section = ReplaceSection(http)
63
+ self.create_mashup = CreateMashup(http)
64
+ self.text_to_sound = TextToSound(http)
65
+ self.voice_to_validation_phrase = VoiceToValidationPhrase(http)
66
+ self.regenerate_validation_phrase = RegenerateValidationPhrase(http)
67
+ self.generate_voice = GenerateVoice(http)
68
+ self.check_voice = CheckVoice(http)
69
+ self.generate_persona = GeneratePersona(http)
70
+ self.boost_style = BoostStyle(http)