cartesia 1.3.1__py3-none-any.whl → 2.0.0__py3-none-any.whl
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.
- cartesia/__init__.py +302 -3
- cartesia/api_status/__init__.py +6 -0
- cartesia/api_status/client.py +104 -0
- cartesia/api_status/requests/__init__.py +5 -0
- cartesia/api_status/requests/api_info.py +8 -0
- cartesia/api_status/types/__init__.py +5 -0
- cartesia/api_status/types/api_info.py +20 -0
- cartesia/base_client.py +156 -0
- cartesia/client.py +163 -40
- cartesia/core/__init__.py +50 -0
- cartesia/core/api_error.py +15 -0
- cartesia/core/client_wrapper.py +55 -0
- cartesia/core/datetime_utils.py +28 -0
- cartesia/core/file.py +67 -0
- cartesia/core/http_client.py +499 -0
- cartesia/core/jsonable_encoder.py +101 -0
- cartesia/core/pagination.py +88 -0
- cartesia/core/pydantic_utilities.py +296 -0
- cartesia/core/query_encoder.py +58 -0
- cartesia/core/remove_none_from_dict.py +11 -0
- cartesia/core/request_options.py +35 -0
- cartesia/core/serialization.py +272 -0
- cartesia/datasets/__init__.py +24 -0
- cartesia/datasets/requests/__init__.py +15 -0
- cartesia/datasets/requests/create_dataset_request.py +7 -0
- cartesia/datasets/requests/dataset.py +9 -0
- cartesia/datasets/requests/dataset_file.py +9 -0
- cartesia/datasets/requests/paginated_dataset_files.py +10 -0
- cartesia/datasets/requests/paginated_datasets.py +10 -0
- cartesia/datasets/types/__init__.py +17 -0
- cartesia/datasets/types/create_dataset_request.py +19 -0
- cartesia/datasets/types/dataset.py +21 -0
- cartesia/datasets/types/dataset_file.py +21 -0
- cartesia/datasets/types/file_purpose.py +5 -0
- cartesia/datasets/types/paginated_dataset_files.py +21 -0
- cartesia/datasets/types/paginated_datasets.py +21 -0
- cartesia/embedding/__init__.py +5 -0
- cartesia/embedding/types/__init__.py +5 -0
- cartesia/embedding/types/embedding.py +201 -0
- cartesia/environment.py +7 -0
- cartesia/infill/__init__.py +2 -0
- cartesia/infill/client.py +318 -0
- cartesia/tts/__init__.py +167 -0
- cartesia/{_async_websocket.py → tts/_async_websocket.py} +212 -85
- cartesia/tts/_websocket.py +479 -0
- cartesia/tts/client.py +407 -0
- cartesia/tts/requests/__init__.py +76 -0
- cartesia/tts/requests/cancel_context_request.py +17 -0
- cartesia/tts/requests/controls.py +11 -0
- cartesia/tts/requests/generation_request.py +58 -0
- cartesia/tts/requests/mp_3_output_format.py +11 -0
- cartesia/tts/requests/output_format.py +30 -0
- cartesia/tts/requests/phoneme_timestamps.py +10 -0
- cartesia/tts/requests/raw_output_format.py +11 -0
- cartesia/tts/requests/speed.py +7 -0
- cartesia/tts/requests/tts_request.py +24 -0
- cartesia/tts/requests/tts_request_embedding_specifier.py +16 -0
- cartesia/tts/requests/tts_request_id_specifier.py +16 -0
- cartesia/tts/requests/tts_request_voice_specifier.py +7 -0
- cartesia/tts/requests/wav_output_format.py +7 -0
- cartesia/tts/requests/web_socket_base_response.py +11 -0
- cartesia/tts/requests/web_socket_chunk_response.py +11 -0
- cartesia/tts/requests/web_socket_done_response.py +7 -0
- cartesia/tts/requests/web_socket_error_response.py +7 -0
- cartesia/tts/requests/web_socket_flush_done_response.py +9 -0
- cartesia/tts/requests/web_socket_phoneme_timestamps_response.py +9 -0
- cartesia/tts/requests/web_socket_raw_output_format.py +11 -0
- cartesia/tts/requests/web_socket_request.py +7 -0
- cartesia/tts/requests/web_socket_response.py +70 -0
- cartesia/tts/requests/web_socket_stream_options.py +8 -0
- cartesia/tts/requests/web_socket_timestamps_response.py +9 -0
- cartesia/tts/requests/web_socket_tts_output.py +18 -0
- cartesia/tts/requests/web_socket_tts_request.py +25 -0
- cartesia/tts/requests/word_timestamps.py +10 -0
- cartesia/tts/socket_client.py +302 -0
- cartesia/tts/types/__init__.py +90 -0
- cartesia/tts/types/cancel_context_request.py +28 -0
- cartesia/tts/types/context_id.py +3 -0
- cartesia/tts/types/controls.py +22 -0
- cartesia/tts/types/emotion.py +34 -0
- cartesia/tts/types/flush_id.py +3 -0
- cartesia/tts/types/generation_request.py +71 -0
- cartesia/tts/types/mp_3_output_format.py +23 -0
- cartesia/tts/types/natural_specifier.py +5 -0
- cartesia/tts/types/numerical_specifier.py +3 -0
- cartesia/tts/types/output_format.py +58 -0
- cartesia/tts/types/phoneme_timestamps.py +21 -0
- cartesia/tts/types/raw_encoding.py +5 -0
- cartesia/tts/types/raw_output_format.py +22 -0
- cartesia/tts/types/speed.py +7 -0
- cartesia/tts/types/supported_language.py +7 -0
- cartesia/tts/types/tts_request.py +35 -0
- cartesia/tts/types/tts_request_embedding_specifier.py +27 -0
- cartesia/tts/types/tts_request_id_specifier.py +27 -0
- cartesia/tts/types/tts_request_voice_specifier.py +7 -0
- cartesia/tts/types/wav_output_format.py +17 -0
- cartesia/tts/types/web_socket_base_response.py +22 -0
- cartesia/tts/types/web_socket_chunk_response.py +22 -0
- cartesia/tts/types/web_socket_done_response.py +17 -0
- cartesia/tts/types/web_socket_error_response.py +19 -0
- cartesia/tts/types/web_socket_flush_done_response.py +21 -0
- cartesia/tts/types/web_socket_phoneme_timestamps_response.py +20 -0
- cartesia/tts/types/web_socket_raw_output_format.py +22 -0
- cartesia/tts/types/web_socket_request.py +7 -0
- cartesia/tts/types/web_socket_response.py +125 -0
- cartesia/tts/types/web_socket_stream_options.py +19 -0
- cartesia/tts/types/web_socket_timestamps_response.py +20 -0
- cartesia/tts/types/web_socket_tts_output.py +29 -0
- cartesia/tts/types/web_socket_tts_request.py +37 -0
- cartesia/tts/types/word_timestamps.py +21 -0
- cartesia/{_constants.py → tts/utils/constants.py} +2 -2
- cartesia/tts/utils/tts.py +64 -0
- cartesia/tts/utils/types.py +70 -0
- cartesia/version.py +3 -1
- cartesia/voice_changer/__init__.py +27 -0
- cartesia/voice_changer/client.py +395 -0
- cartesia/voice_changer/requests/__init__.py +15 -0
- cartesia/voice_changer/requests/streaming_response.py +38 -0
- cartesia/voice_changer/types/__init__.py +17 -0
- cartesia/voice_changer/types/output_format_container.py +5 -0
- cartesia/voice_changer/types/streaming_response.py +64 -0
- cartesia/voices/__init__.py +81 -0
- cartesia/voices/client.py +1218 -0
- cartesia/voices/requests/__init__.py +29 -0
- cartesia/voices/requests/create_voice_request.py +23 -0
- cartesia/voices/requests/embedding_response.py +8 -0
- cartesia/voices/requests/embedding_specifier.py +10 -0
- cartesia/voices/requests/get_voices_response.py +24 -0
- cartesia/voices/requests/id_specifier.py +10 -0
- cartesia/voices/requests/localize_dialect.py +11 -0
- cartesia/voices/requests/localize_voice_request.py +28 -0
- cartesia/voices/requests/mix_voice_specifier.py +7 -0
- cartesia/voices/requests/mix_voices_request.py +9 -0
- cartesia/voices/requests/update_voice_request.py +15 -0
- cartesia/voices/requests/voice.py +43 -0
- cartesia/voices/requests/voice_metadata.py +36 -0
- cartesia/voices/types/__init__.py +53 -0
- cartesia/voices/types/base_voice_id.py +5 -0
- cartesia/voices/types/clone_mode.py +5 -0
- cartesia/voices/types/create_voice_request.py +34 -0
- cartesia/voices/types/embedding_response.py +20 -0
- cartesia/voices/types/embedding_specifier.py +22 -0
- cartesia/voices/types/gender.py +5 -0
- cartesia/voices/types/gender_presentation.py +5 -0
- cartesia/voices/types/get_voices_response.py +34 -0
- cartesia/voices/types/id_specifier.py +22 -0
- cartesia/voices/types/localize_dialect.py +11 -0
- cartesia/voices/types/localize_english_dialect.py +5 -0
- cartesia/voices/types/localize_french_dialect.py +5 -0
- cartesia/voices/types/localize_portuguese_dialect.py +5 -0
- cartesia/voices/types/localize_spanish_dialect.py +5 -0
- cartesia/voices/types/localize_target_language.py +7 -0
- cartesia/voices/types/localize_voice_request.py +39 -0
- cartesia/voices/types/mix_voice_specifier.py +7 -0
- cartesia/voices/types/mix_voices_request.py +20 -0
- cartesia/voices/types/update_voice_request.py +27 -0
- cartesia/voices/types/voice.py +54 -0
- cartesia/voices/types/voice_expand_options.py +5 -0
- cartesia/voices/types/voice_id.py +3 -0
- cartesia/voices/types/voice_metadata.py +48 -0
- cartesia/voices/types/weight.py +3 -0
- cartesia-2.0.0.dist-info/METADATA +414 -0
- cartesia-2.0.0.dist-info/RECORD +165 -0
- {cartesia-1.3.1.dist-info → cartesia-2.0.0.dist-info}/WHEEL +1 -1
- cartesia/_async_sse.py +0 -95
- cartesia/_logger.py +0 -3
- cartesia/_sse.py +0 -143
- cartesia/_types.py +0 -70
- cartesia/_websocket.py +0 -358
- cartesia/async_client.py +0 -82
- cartesia/async_tts.py +0 -63
- cartesia/resource.py +0 -44
- cartesia/tts.py +0 -137
- cartesia/utils/deprecated.py +0 -55
- cartesia/utils/retry.py +0 -87
- cartesia/utils/tts.py +0 -78
- cartesia/voices.py +0 -208
- cartesia-1.3.1.dist-info/METADATA +0 -661
- cartesia-1.3.1.dist-info/RECORD +0 -23
- cartesia-1.3.1.dist-info/licenses/LICENSE.md +0 -21
- /cartesia/{utils/__init__.py → py.typed} +0 -0
@@ -0,0 +1,1218 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
import typing
|
4
|
+
from ..core.client_wrapper import SyncClientWrapper
|
5
|
+
from .types.gender_presentation import GenderPresentation
|
6
|
+
from .types.voice_expand_options import VoiceExpandOptions
|
7
|
+
from ..core.request_options import RequestOptions
|
8
|
+
from ..core.pagination import SyncPager
|
9
|
+
from .types.voice import Voice
|
10
|
+
from .types.get_voices_response import GetVoicesResponse
|
11
|
+
from ..core.pydantic_utilities import parse_obj_as
|
12
|
+
from json.decoder import JSONDecodeError
|
13
|
+
from ..core.api_error import ApiError
|
14
|
+
from .. import core
|
15
|
+
from ..tts.types.supported_language import SupportedLanguage
|
16
|
+
from .types.clone_mode import CloneMode
|
17
|
+
from .types.voice_metadata import VoiceMetadata
|
18
|
+
from .types.voice_id import VoiceId
|
19
|
+
from ..core.jsonable_encoder import jsonable_encoder
|
20
|
+
from .types.localize_target_language import LocalizeTargetLanguage
|
21
|
+
from .types.gender import Gender
|
22
|
+
from .requests.localize_dialect import LocalizeDialectParams
|
23
|
+
from ..core.serialization import convert_and_respect_annotation_metadata
|
24
|
+
from .requests.mix_voice_specifier import MixVoiceSpecifierParams
|
25
|
+
from .types.embedding_response import EmbeddingResponse
|
26
|
+
from ..embedding.types.embedding import Embedding
|
27
|
+
from .types.base_voice_id import BaseVoiceId
|
28
|
+
from ..core.client_wrapper import AsyncClientWrapper
|
29
|
+
from ..core.pagination import AsyncPager
|
30
|
+
|
31
|
+
# this is used as the default value for optional parameters
|
32
|
+
OMIT = typing.cast(typing.Any, ...)
|
33
|
+
|
34
|
+
|
35
|
+
class VoicesClient:
|
36
|
+
def __init__(self, *, client_wrapper: SyncClientWrapper):
|
37
|
+
self._client_wrapper = client_wrapper
|
38
|
+
|
39
|
+
def list(
|
40
|
+
self,
|
41
|
+
*,
|
42
|
+
limit: typing.Optional[int] = None,
|
43
|
+
starting_after: typing.Optional[str] = None,
|
44
|
+
ending_before: typing.Optional[str] = None,
|
45
|
+
is_owner: typing.Optional[bool] = None,
|
46
|
+
is_starred: typing.Optional[bool] = None,
|
47
|
+
gender: typing.Optional[GenderPresentation] = None,
|
48
|
+
expand: typing.Optional[typing.Sequence[VoiceExpandOptions]] = None,
|
49
|
+
request_options: typing.Optional[RequestOptions] = None,
|
50
|
+
) -> SyncPager[Voice]:
|
51
|
+
"""
|
52
|
+
Parameters
|
53
|
+
----------
|
54
|
+
limit : typing.Optional[int]
|
55
|
+
The number of Voices to return per page, ranging between 1 and 100.
|
56
|
+
|
57
|
+
starting_after : typing.Optional[str]
|
58
|
+
A cursor to use in pagination. `starting_after` is a Voice ID that defines your
|
59
|
+
place in the list. For example, if you make a /voices request and receive 100
|
60
|
+
objects, ending with `voice_abc123`, your subsequent call can include
|
61
|
+
`starting_after=voice_abc123` to fetch the next page of the list.
|
62
|
+
|
63
|
+
ending_before : typing.Optional[str]
|
64
|
+
A cursor to use in pagination. `ending_before` is a Voice ID that defines your
|
65
|
+
place in the list. For example, if you make a /voices request and receive 100
|
66
|
+
objects, starting with `voice_abc123`, your subsequent call can include
|
67
|
+
`ending_before=voice_abc123` to fetch the previous page of the list.
|
68
|
+
|
69
|
+
is_owner : typing.Optional[bool]
|
70
|
+
Whether to only return voices owned by the current user.
|
71
|
+
|
72
|
+
is_starred : typing.Optional[bool]
|
73
|
+
Whether to only return starred voices.
|
74
|
+
|
75
|
+
gender : typing.Optional[GenderPresentation]
|
76
|
+
The gender presentation of the voices to return.
|
77
|
+
|
78
|
+
expand : typing.Optional[typing.Sequence[VoiceExpandOptions]]
|
79
|
+
Additional fields to include in the response.
|
80
|
+
|
81
|
+
request_options : typing.Optional[RequestOptions]
|
82
|
+
Request-specific configuration.
|
83
|
+
|
84
|
+
Returns
|
85
|
+
-------
|
86
|
+
SyncPager[Voice]
|
87
|
+
|
88
|
+
Examples
|
89
|
+
--------
|
90
|
+
from cartesia import Cartesia
|
91
|
+
|
92
|
+
client = Cartesia(
|
93
|
+
api_key="YOUR_API_KEY",
|
94
|
+
)
|
95
|
+
response = client.voices.list()
|
96
|
+
for item in response:
|
97
|
+
yield item
|
98
|
+
# alternatively, you can paginate page-by-page
|
99
|
+
for page in response.iter_pages():
|
100
|
+
yield page
|
101
|
+
"""
|
102
|
+
_response = self._client_wrapper.httpx_client.request(
|
103
|
+
"voices/",
|
104
|
+
method="GET",
|
105
|
+
params={
|
106
|
+
"limit": limit,
|
107
|
+
"starting_after": starting_after,
|
108
|
+
"ending_before": ending_before,
|
109
|
+
"is_owner": is_owner,
|
110
|
+
"is_starred": is_starred,
|
111
|
+
"gender": gender,
|
112
|
+
"expand[]": expand,
|
113
|
+
},
|
114
|
+
request_options=request_options,
|
115
|
+
)
|
116
|
+
try:
|
117
|
+
if 200 <= _response.status_code < 300:
|
118
|
+
_parsed_response = typing.cast(
|
119
|
+
GetVoicesResponse,
|
120
|
+
parse_obj_as(
|
121
|
+
type_=GetVoicesResponse, # type: ignore
|
122
|
+
object_=_response.json(),
|
123
|
+
),
|
124
|
+
)
|
125
|
+
_parsed_next = _parsed_response.next_page
|
126
|
+
_has_next = _parsed_next is not None and _parsed_next != ""
|
127
|
+
_get_next = lambda: self.list(
|
128
|
+
limit=limit,
|
129
|
+
starting_after=_parsed_next,
|
130
|
+
ending_before=ending_before,
|
131
|
+
is_owner=is_owner,
|
132
|
+
is_starred=is_starred,
|
133
|
+
gender=gender,
|
134
|
+
expand=expand,
|
135
|
+
request_options=request_options,
|
136
|
+
)
|
137
|
+
_items = _parsed_response.data
|
138
|
+
return SyncPager(has_next=_has_next, items=_items, get_next=_get_next)
|
139
|
+
_response_json = _response.json()
|
140
|
+
except JSONDecodeError:
|
141
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
142
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
143
|
+
|
144
|
+
def clone(
|
145
|
+
self,
|
146
|
+
*,
|
147
|
+
clip: core.File,
|
148
|
+
name: str,
|
149
|
+
language: SupportedLanguage,
|
150
|
+
mode: CloneMode,
|
151
|
+
enhance: bool,
|
152
|
+
description: typing.Optional[str] = OMIT,
|
153
|
+
transcript: typing.Optional[str] = OMIT,
|
154
|
+
request_options: typing.Optional[RequestOptions] = None,
|
155
|
+
) -> VoiceMetadata:
|
156
|
+
"""
|
157
|
+
Clone a voice from an audio clip. This endpoint has two modes, stability and similarity.
|
158
|
+
|
159
|
+
Similarity mode clones are more similar to the source clip, but may reproduce background noise. For these, use an audio clip about 5 seconds long.
|
160
|
+
|
161
|
+
Stability mode clones are more stable, but may not sound as similar to the source clip. For these, use an audio clip 10-20 seconds long.
|
162
|
+
|
163
|
+
Parameters
|
164
|
+
----------
|
165
|
+
clip : core.File
|
166
|
+
See core.File for more documentation
|
167
|
+
|
168
|
+
name : str
|
169
|
+
The name of the voice.
|
170
|
+
|
171
|
+
|
172
|
+
language : SupportedLanguage
|
173
|
+
The language of the voice.
|
174
|
+
|
175
|
+
|
176
|
+
mode : CloneMode
|
177
|
+
Tradeoff between similarity and stability. Similarity clones sound more like the source clip, but may reproduce background noise. Stability clones always sound like a studio recording, but may not sound as similar to the source clip.
|
178
|
+
|
179
|
+
|
180
|
+
enhance : bool
|
181
|
+
Whether to enhance the clip to improve its quality before cloning. Useful if the clip has background noise.
|
182
|
+
|
183
|
+
|
184
|
+
description : typing.Optional[str]
|
185
|
+
A description for the voice.
|
186
|
+
|
187
|
+
|
188
|
+
transcript : typing.Optional[str]
|
189
|
+
Optional transcript of the words spoken in the audio clip. Only used for similarity mode.
|
190
|
+
|
191
|
+
|
192
|
+
request_options : typing.Optional[RequestOptions]
|
193
|
+
Request-specific configuration.
|
194
|
+
|
195
|
+
Returns
|
196
|
+
-------
|
197
|
+
VoiceMetadata
|
198
|
+
|
199
|
+
Examples
|
200
|
+
--------
|
201
|
+
from cartesia import Cartesia
|
202
|
+
|
203
|
+
client = Cartesia(
|
204
|
+
api_key="YOUR_API_KEY",
|
205
|
+
)
|
206
|
+
client.voices.clone(
|
207
|
+
name="A high-stability cloned voice",
|
208
|
+
description="Copied from Cartesia docs",
|
209
|
+
mode="stability",
|
210
|
+
language="en",
|
211
|
+
enhance=True,
|
212
|
+
)
|
213
|
+
"""
|
214
|
+
_response = self._client_wrapper.httpx_client.request(
|
215
|
+
"voices/clone",
|
216
|
+
method="POST",
|
217
|
+
data={
|
218
|
+
"name": name,
|
219
|
+
"description": description,
|
220
|
+
"language": language,
|
221
|
+
"mode": mode,
|
222
|
+
"enhance": enhance,
|
223
|
+
"transcript": transcript,
|
224
|
+
},
|
225
|
+
files={
|
226
|
+
"clip": clip,
|
227
|
+
},
|
228
|
+
request_options=request_options,
|
229
|
+
omit=OMIT,
|
230
|
+
)
|
231
|
+
try:
|
232
|
+
if 200 <= _response.status_code < 300:
|
233
|
+
return typing.cast(
|
234
|
+
VoiceMetadata,
|
235
|
+
parse_obj_as(
|
236
|
+
type_=VoiceMetadata, # type: ignore
|
237
|
+
object_=_response.json(),
|
238
|
+
),
|
239
|
+
)
|
240
|
+
_response_json = _response.json()
|
241
|
+
except JSONDecodeError:
|
242
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
243
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
244
|
+
|
245
|
+
def delete(self, id: VoiceId, *, request_options: typing.Optional[RequestOptions] = None) -> None:
|
246
|
+
"""
|
247
|
+
Parameters
|
248
|
+
----------
|
249
|
+
id : VoiceId
|
250
|
+
|
251
|
+
request_options : typing.Optional[RequestOptions]
|
252
|
+
Request-specific configuration.
|
253
|
+
|
254
|
+
Returns
|
255
|
+
-------
|
256
|
+
None
|
257
|
+
|
258
|
+
Examples
|
259
|
+
--------
|
260
|
+
from cartesia import Cartesia
|
261
|
+
|
262
|
+
client = Cartesia(
|
263
|
+
api_key="YOUR_API_KEY",
|
264
|
+
)
|
265
|
+
client.voices.delete(
|
266
|
+
id="id",
|
267
|
+
)
|
268
|
+
"""
|
269
|
+
_response = self._client_wrapper.httpx_client.request(
|
270
|
+
f"voices/{jsonable_encoder(id)}",
|
271
|
+
method="DELETE",
|
272
|
+
request_options=request_options,
|
273
|
+
)
|
274
|
+
try:
|
275
|
+
if 200 <= _response.status_code < 300:
|
276
|
+
return
|
277
|
+
_response_json = _response.json()
|
278
|
+
except JSONDecodeError:
|
279
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
280
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
281
|
+
|
282
|
+
def update(
|
283
|
+
self, id: VoiceId, *, name: str, description: str, request_options: typing.Optional[RequestOptions] = None
|
284
|
+
) -> Voice:
|
285
|
+
"""
|
286
|
+
Parameters
|
287
|
+
----------
|
288
|
+
id : VoiceId
|
289
|
+
|
290
|
+
name : str
|
291
|
+
The name of the voice.
|
292
|
+
|
293
|
+
description : str
|
294
|
+
The description of the voice.
|
295
|
+
|
296
|
+
request_options : typing.Optional[RequestOptions]
|
297
|
+
Request-specific configuration.
|
298
|
+
|
299
|
+
Returns
|
300
|
+
-------
|
301
|
+
Voice
|
302
|
+
|
303
|
+
Examples
|
304
|
+
--------
|
305
|
+
from cartesia import Cartesia
|
306
|
+
|
307
|
+
client = Cartesia(
|
308
|
+
api_key="YOUR_API_KEY",
|
309
|
+
)
|
310
|
+
client.voices.update(
|
311
|
+
id="id",
|
312
|
+
name="name",
|
313
|
+
description="description",
|
314
|
+
)
|
315
|
+
"""
|
316
|
+
_response = self._client_wrapper.httpx_client.request(
|
317
|
+
f"voices/{jsonable_encoder(id)}",
|
318
|
+
method="PATCH",
|
319
|
+
json={
|
320
|
+
"name": name,
|
321
|
+
"description": description,
|
322
|
+
},
|
323
|
+
request_options=request_options,
|
324
|
+
omit=OMIT,
|
325
|
+
)
|
326
|
+
try:
|
327
|
+
if 200 <= _response.status_code < 300:
|
328
|
+
return typing.cast(
|
329
|
+
Voice,
|
330
|
+
parse_obj_as(
|
331
|
+
type_=Voice, # type: ignore
|
332
|
+
object_=_response.json(),
|
333
|
+
),
|
334
|
+
)
|
335
|
+
_response_json = _response.json()
|
336
|
+
except JSONDecodeError:
|
337
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
338
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
339
|
+
|
340
|
+
def get(self, id: VoiceId, *, request_options: typing.Optional[RequestOptions] = None) -> Voice:
|
341
|
+
"""
|
342
|
+
Parameters
|
343
|
+
----------
|
344
|
+
id : VoiceId
|
345
|
+
|
346
|
+
request_options : typing.Optional[RequestOptions]
|
347
|
+
Request-specific configuration.
|
348
|
+
|
349
|
+
Returns
|
350
|
+
-------
|
351
|
+
Voice
|
352
|
+
|
353
|
+
Examples
|
354
|
+
--------
|
355
|
+
from cartesia import Cartesia
|
356
|
+
|
357
|
+
client = Cartesia(
|
358
|
+
api_key="YOUR_API_KEY",
|
359
|
+
)
|
360
|
+
client.voices.get(
|
361
|
+
id="id",
|
362
|
+
)
|
363
|
+
"""
|
364
|
+
_response = self._client_wrapper.httpx_client.request(
|
365
|
+
f"voices/{jsonable_encoder(id)}",
|
366
|
+
method="GET",
|
367
|
+
request_options=request_options,
|
368
|
+
)
|
369
|
+
try:
|
370
|
+
if 200 <= _response.status_code < 300:
|
371
|
+
return typing.cast(
|
372
|
+
Voice,
|
373
|
+
parse_obj_as(
|
374
|
+
type_=Voice, # type: ignore
|
375
|
+
object_=_response.json(),
|
376
|
+
),
|
377
|
+
)
|
378
|
+
_response_json = _response.json()
|
379
|
+
except JSONDecodeError:
|
380
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
381
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
382
|
+
|
383
|
+
def localize(
|
384
|
+
self,
|
385
|
+
*,
|
386
|
+
voice_id: str,
|
387
|
+
name: str,
|
388
|
+
description: str,
|
389
|
+
language: LocalizeTargetLanguage,
|
390
|
+
original_speaker_gender: Gender,
|
391
|
+
dialect: typing.Optional[LocalizeDialectParams] = OMIT,
|
392
|
+
request_options: typing.Optional[RequestOptions] = None,
|
393
|
+
) -> VoiceMetadata:
|
394
|
+
"""
|
395
|
+
Create a new voice from an existing voice localized to a new language and dialect.
|
396
|
+
|
397
|
+
Parameters
|
398
|
+
----------
|
399
|
+
voice_id : str
|
400
|
+
The ID of the voice to localize.
|
401
|
+
|
402
|
+
name : str
|
403
|
+
The name of the new localized voice.
|
404
|
+
|
405
|
+
description : str
|
406
|
+
The description of the new localized voice.
|
407
|
+
|
408
|
+
language : LocalizeTargetLanguage
|
409
|
+
|
410
|
+
original_speaker_gender : Gender
|
411
|
+
|
412
|
+
dialect : typing.Optional[LocalizeDialectParams]
|
413
|
+
|
414
|
+
request_options : typing.Optional[RequestOptions]
|
415
|
+
Request-specific configuration.
|
416
|
+
|
417
|
+
Returns
|
418
|
+
-------
|
419
|
+
VoiceMetadata
|
420
|
+
|
421
|
+
Examples
|
422
|
+
--------
|
423
|
+
from cartesia import Cartesia
|
424
|
+
|
425
|
+
client = Cartesia(
|
426
|
+
api_key="YOUR_API_KEY",
|
427
|
+
)
|
428
|
+
client.voices.localize(
|
429
|
+
voice_id="694f9389-aac1-45b6-b726-9d9369183238",
|
430
|
+
name="Sarah Peninsular Spanish",
|
431
|
+
description="Sarah Voice in Peninsular Spanish",
|
432
|
+
language="es",
|
433
|
+
original_speaker_gender="female",
|
434
|
+
dialect="pe",
|
435
|
+
)
|
436
|
+
"""
|
437
|
+
_response = self._client_wrapper.httpx_client.request(
|
438
|
+
"voices/localize",
|
439
|
+
method="POST",
|
440
|
+
json={
|
441
|
+
"voice_id": voice_id,
|
442
|
+
"name": name,
|
443
|
+
"description": description,
|
444
|
+
"language": language,
|
445
|
+
"original_speaker_gender": original_speaker_gender,
|
446
|
+
"dialect": convert_and_respect_annotation_metadata(
|
447
|
+
object_=dialect, annotation=LocalizeDialectParams, direction="write"
|
448
|
+
),
|
449
|
+
},
|
450
|
+
request_options=request_options,
|
451
|
+
omit=OMIT,
|
452
|
+
)
|
453
|
+
try:
|
454
|
+
if 200 <= _response.status_code < 300:
|
455
|
+
return typing.cast(
|
456
|
+
VoiceMetadata,
|
457
|
+
parse_obj_as(
|
458
|
+
type_=VoiceMetadata, # type: ignore
|
459
|
+
object_=_response.json(),
|
460
|
+
),
|
461
|
+
)
|
462
|
+
_response_json = _response.json()
|
463
|
+
except JSONDecodeError:
|
464
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
465
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
466
|
+
|
467
|
+
def mix(
|
468
|
+
self,
|
469
|
+
*,
|
470
|
+
voices: typing.Sequence[MixVoiceSpecifierParams],
|
471
|
+
request_options: typing.Optional[RequestOptions] = None,
|
472
|
+
) -> EmbeddingResponse:
|
473
|
+
"""
|
474
|
+
Parameters
|
475
|
+
----------
|
476
|
+
voices : typing.Sequence[MixVoiceSpecifierParams]
|
477
|
+
|
478
|
+
request_options : typing.Optional[RequestOptions]
|
479
|
+
Request-specific configuration.
|
480
|
+
|
481
|
+
Returns
|
482
|
+
-------
|
483
|
+
EmbeddingResponse
|
484
|
+
|
485
|
+
Examples
|
486
|
+
--------
|
487
|
+
from cartesia import Cartesia
|
488
|
+
|
489
|
+
client = Cartesia(
|
490
|
+
api_key="YOUR_API_KEY",
|
491
|
+
)
|
492
|
+
client.voices.mix(
|
493
|
+
voices=[{"id": "id", "weight": 1.1}, {"id": "id", "weight": 1.1}],
|
494
|
+
)
|
495
|
+
"""
|
496
|
+
_response = self._client_wrapper.httpx_client.request(
|
497
|
+
"voices/mix",
|
498
|
+
method="POST",
|
499
|
+
json={
|
500
|
+
"voices": convert_and_respect_annotation_metadata(
|
501
|
+
object_=voices, annotation=typing.Sequence[MixVoiceSpecifierParams], direction="write"
|
502
|
+
),
|
503
|
+
},
|
504
|
+
request_options=request_options,
|
505
|
+
omit=OMIT,
|
506
|
+
)
|
507
|
+
try:
|
508
|
+
if 200 <= _response.status_code < 300:
|
509
|
+
return typing.cast(
|
510
|
+
EmbeddingResponse,
|
511
|
+
parse_obj_as(
|
512
|
+
type_=EmbeddingResponse, # type: ignore
|
513
|
+
object_=_response.json(),
|
514
|
+
),
|
515
|
+
)
|
516
|
+
_response_json = _response.json()
|
517
|
+
except JSONDecodeError:
|
518
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
519
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
520
|
+
|
521
|
+
def create(
|
522
|
+
self,
|
523
|
+
*,
|
524
|
+
name: str,
|
525
|
+
description: str,
|
526
|
+
embedding: Embedding,
|
527
|
+
language: typing.Optional[SupportedLanguage] = OMIT,
|
528
|
+
base_voice_id: typing.Optional[BaseVoiceId] = OMIT,
|
529
|
+
request_options: typing.Optional[RequestOptions] = None,
|
530
|
+
) -> Voice:
|
531
|
+
"""
|
532
|
+
Create voice from raw features. If you'd like to clone a voice from an audio file, please use Clone Voice instead.
|
533
|
+
|
534
|
+
Parameters
|
535
|
+
----------
|
536
|
+
name : str
|
537
|
+
The name of the voice.
|
538
|
+
|
539
|
+
description : str
|
540
|
+
The description of the voice.
|
541
|
+
|
542
|
+
embedding : Embedding
|
543
|
+
|
544
|
+
language : typing.Optional[SupportedLanguage]
|
545
|
+
|
546
|
+
base_voice_id : typing.Optional[BaseVoiceId]
|
547
|
+
|
548
|
+
request_options : typing.Optional[RequestOptions]
|
549
|
+
Request-specific configuration.
|
550
|
+
|
551
|
+
Returns
|
552
|
+
-------
|
553
|
+
Voice
|
554
|
+
|
555
|
+
Examples
|
556
|
+
--------
|
557
|
+
from cartesia import Cartesia
|
558
|
+
|
559
|
+
client = Cartesia(
|
560
|
+
api_key="YOUR_API_KEY",
|
561
|
+
)
|
562
|
+
client.voices.create(
|
563
|
+
name="name",
|
564
|
+
description="description",
|
565
|
+
embedding=[1.1, 1.1],
|
566
|
+
)
|
567
|
+
"""
|
568
|
+
_response = self._client_wrapper.httpx_client.request(
|
569
|
+
"voices/",
|
570
|
+
method="POST",
|
571
|
+
json={
|
572
|
+
"name": name,
|
573
|
+
"description": description,
|
574
|
+
"embedding": embedding,
|
575
|
+
"language": language,
|
576
|
+
"base_voice_id": base_voice_id,
|
577
|
+
},
|
578
|
+
request_options=request_options,
|
579
|
+
omit=OMIT,
|
580
|
+
)
|
581
|
+
try:
|
582
|
+
if 200 <= _response.status_code < 300:
|
583
|
+
return typing.cast(
|
584
|
+
Voice,
|
585
|
+
parse_obj_as(
|
586
|
+
type_=Voice, # type: ignore
|
587
|
+
object_=_response.json(),
|
588
|
+
),
|
589
|
+
)
|
590
|
+
_response_json = _response.json()
|
591
|
+
except JSONDecodeError:
|
592
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
593
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
594
|
+
|
595
|
+
|
596
|
+
class AsyncVoicesClient:
|
597
|
+
def __init__(self, *, client_wrapper: AsyncClientWrapper):
|
598
|
+
self._client_wrapper = client_wrapper
|
599
|
+
|
600
|
+
async def list(
|
601
|
+
self,
|
602
|
+
*,
|
603
|
+
limit: typing.Optional[int] = None,
|
604
|
+
starting_after: typing.Optional[str] = None,
|
605
|
+
ending_before: typing.Optional[str] = None,
|
606
|
+
is_owner: typing.Optional[bool] = None,
|
607
|
+
is_starred: typing.Optional[bool] = None,
|
608
|
+
gender: typing.Optional[GenderPresentation] = None,
|
609
|
+
expand: typing.Optional[typing.Sequence[VoiceExpandOptions]] = None,
|
610
|
+
request_options: typing.Optional[RequestOptions] = None,
|
611
|
+
) -> AsyncPager[Voice]:
|
612
|
+
"""
|
613
|
+
Parameters
|
614
|
+
----------
|
615
|
+
limit : typing.Optional[int]
|
616
|
+
The number of Voices to return per page, ranging between 1 and 100.
|
617
|
+
|
618
|
+
starting_after : typing.Optional[str]
|
619
|
+
A cursor to use in pagination. `starting_after` is a Voice ID that defines your
|
620
|
+
place in the list. For example, if you make a /voices request and receive 100
|
621
|
+
objects, ending with `voice_abc123`, your subsequent call can include
|
622
|
+
`starting_after=voice_abc123` to fetch the next page of the list.
|
623
|
+
|
624
|
+
ending_before : typing.Optional[str]
|
625
|
+
A cursor to use in pagination. `ending_before` is a Voice ID that defines your
|
626
|
+
place in the list. For example, if you make a /voices request and receive 100
|
627
|
+
objects, starting with `voice_abc123`, your subsequent call can include
|
628
|
+
`ending_before=voice_abc123` to fetch the previous page of the list.
|
629
|
+
|
630
|
+
is_owner : typing.Optional[bool]
|
631
|
+
Whether to only return voices owned by the current user.
|
632
|
+
|
633
|
+
is_starred : typing.Optional[bool]
|
634
|
+
Whether to only return starred voices.
|
635
|
+
|
636
|
+
gender : typing.Optional[GenderPresentation]
|
637
|
+
The gender presentation of the voices to return.
|
638
|
+
|
639
|
+
expand : typing.Optional[typing.Sequence[VoiceExpandOptions]]
|
640
|
+
Additional fields to include in the response.
|
641
|
+
|
642
|
+
request_options : typing.Optional[RequestOptions]
|
643
|
+
Request-specific configuration.
|
644
|
+
|
645
|
+
Returns
|
646
|
+
-------
|
647
|
+
AsyncPager[Voice]
|
648
|
+
|
649
|
+
Examples
|
650
|
+
--------
|
651
|
+
import asyncio
|
652
|
+
|
653
|
+
from cartesia import AsyncCartesia
|
654
|
+
|
655
|
+
client = AsyncCartesia(
|
656
|
+
api_key="YOUR_API_KEY",
|
657
|
+
)
|
658
|
+
|
659
|
+
|
660
|
+
async def main() -> None:
|
661
|
+
response = await client.voices.list()
|
662
|
+
async for item in response:
|
663
|
+
yield item
|
664
|
+
# alternatively, you can paginate page-by-page
|
665
|
+
async for page in response.iter_pages():
|
666
|
+
yield page
|
667
|
+
|
668
|
+
|
669
|
+
asyncio.run(main())
|
670
|
+
"""
|
671
|
+
_response = await self._client_wrapper.httpx_client.request(
|
672
|
+
"voices/",
|
673
|
+
method="GET",
|
674
|
+
params={
|
675
|
+
"limit": limit,
|
676
|
+
"starting_after": starting_after,
|
677
|
+
"ending_before": ending_before,
|
678
|
+
"is_owner": is_owner,
|
679
|
+
"is_starred": is_starred,
|
680
|
+
"gender": gender,
|
681
|
+
"expand[]": expand,
|
682
|
+
},
|
683
|
+
request_options=request_options,
|
684
|
+
)
|
685
|
+
try:
|
686
|
+
if 200 <= _response.status_code < 300:
|
687
|
+
_parsed_response = typing.cast(
|
688
|
+
GetVoicesResponse,
|
689
|
+
parse_obj_as(
|
690
|
+
type_=GetVoicesResponse, # type: ignore
|
691
|
+
object_=_response.json(),
|
692
|
+
),
|
693
|
+
)
|
694
|
+
_parsed_next = _parsed_response.next_page
|
695
|
+
_has_next = _parsed_next is not None and _parsed_next != ""
|
696
|
+
_get_next = lambda: self.list(
|
697
|
+
limit=limit,
|
698
|
+
starting_after=_parsed_next,
|
699
|
+
ending_before=ending_before,
|
700
|
+
is_owner=is_owner,
|
701
|
+
is_starred=is_starred,
|
702
|
+
gender=gender,
|
703
|
+
expand=expand,
|
704
|
+
request_options=request_options,
|
705
|
+
)
|
706
|
+
_items = _parsed_response.data
|
707
|
+
return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next)
|
708
|
+
_response_json = _response.json()
|
709
|
+
except JSONDecodeError:
|
710
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
711
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
712
|
+
|
713
|
+
async def clone(
|
714
|
+
self,
|
715
|
+
*,
|
716
|
+
clip: core.File,
|
717
|
+
name: str,
|
718
|
+
language: SupportedLanguage,
|
719
|
+
mode: CloneMode,
|
720
|
+
enhance: bool,
|
721
|
+
description: typing.Optional[str] = OMIT,
|
722
|
+
transcript: typing.Optional[str] = OMIT,
|
723
|
+
request_options: typing.Optional[RequestOptions] = None,
|
724
|
+
) -> VoiceMetadata:
|
725
|
+
"""
|
726
|
+
Clone a voice from an audio clip. This endpoint has two modes, stability and similarity.
|
727
|
+
|
728
|
+
Similarity mode clones are more similar to the source clip, but may reproduce background noise. For these, use an audio clip about 5 seconds long.
|
729
|
+
|
730
|
+
Stability mode clones are more stable, but may not sound as similar to the source clip. For these, use an audio clip 10-20 seconds long.
|
731
|
+
|
732
|
+
Parameters
|
733
|
+
----------
|
734
|
+
clip : core.File
|
735
|
+
See core.File for more documentation
|
736
|
+
|
737
|
+
name : str
|
738
|
+
The name of the voice.
|
739
|
+
|
740
|
+
|
741
|
+
language : SupportedLanguage
|
742
|
+
The language of the voice.
|
743
|
+
|
744
|
+
|
745
|
+
mode : CloneMode
|
746
|
+
Tradeoff between similarity and stability. Similarity clones sound more like the source clip, but may reproduce background noise. Stability clones always sound like a studio recording, but may not sound as similar to the source clip.
|
747
|
+
|
748
|
+
|
749
|
+
enhance : bool
|
750
|
+
Whether to enhance the clip to improve its quality before cloning. Useful if the clip has background noise.
|
751
|
+
|
752
|
+
|
753
|
+
description : typing.Optional[str]
|
754
|
+
A description for the voice.
|
755
|
+
|
756
|
+
|
757
|
+
transcript : typing.Optional[str]
|
758
|
+
Optional transcript of the words spoken in the audio clip. Only used for similarity mode.
|
759
|
+
|
760
|
+
|
761
|
+
request_options : typing.Optional[RequestOptions]
|
762
|
+
Request-specific configuration.
|
763
|
+
|
764
|
+
Returns
|
765
|
+
-------
|
766
|
+
VoiceMetadata
|
767
|
+
|
768
|
+
Examples
|
769
|
+
--------
|
770
|
+
import asyncio
|
771
|
+
|
772
|
+
from cartesia import AsyncCartesia
|
773
|
+
|
774
|
+
client = AsyncCartesia(
|
775
|
+
api_key="YOUR_API_KEY",
|
776
|
+
)
|
777
|
+
|
778
|
+
|
779
|
+
async def main() -> None:
|
780
|
+
await client.voices.clone(
|
781
|
+
name="A high-stability cloned voice",
|
782
|
+
description="Copied from Cartesia docs",
|
783
|
+
mode="stability",
|
784
|
+
language="en",
|
785
|
+
enhance=True,
|
786
|
+
)
|
787
|
+
|
788
|
+
|
789
|
+
asyncio.run(main())
|
790
|
+
"""
|
791
|
+
_response = await self._client_wrapper.httpx_client.request(
|
792
|
+
"voices/clone",
|
793
|
+
method="POST",
|
794
|
+
data={
|
795
|
+
"name": name,
|
796
|
+
"description": description,
|
797
|
+
"language": language,
|
798
|
+
"mode": mode,
|
799
|
+
"enhance": enhance,
|
800
|
+
"transcript": transcript,
|
801
|
+
},
|
802
|
+
files={
|
803
|
+
"clip": clip,
|
804
|
+
},
|
805
|
+
request_options=request_options,
|
806
|
+
omit=OMIT,
|
807
|
+
)
|
808
|
+
try:
|
809
|
+
if 200 <= _response.status_code < 300:
|
810
|
+
return typing.cast(
|
811
|
+
VoiceMetadata,
|
812
|
+
parse_obj_as(
|
813
|
+
type_=VoiceMetadata, # type: ignore
|
814
|
+
object_=_response.json(),
|
815
|
+
),
|
816
|
+
)
|
817
|
+
_response_json = _response.json()
|
818
|
+
except JSONDecodeError:
|
819
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
820
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
821
|
+
|
822
|
+
async def delete(self, id: VoiceId, *, request_options: typing.Optional[RequestOptions] = None) -> None:
|
823
|
+
"""
|
824
|
+
Parameters
|
825
|
+
----------
|
826
|
+
id : VoiceId
|
827
|
+
|
828
|
+
request_options : typing.Optional[RequestOptions]
|
829
|
+
Request-specific configuration.
|
830
|
+
|
831
|
+
Returns
|
832
|
+
-------
|
833
|
+
None
|
834
|
+
|
835
|
+
Examples
|
836
|
+
--------
|
837
|
+
import asyncio
|
838
|
+
|
839
|
+
from cartesia import AsyncCartesia
|
840
|
+
|
841
|
+
client = AsyncCartesia(
|
842
|
+
api_key="YOUR_API_KEY",
|
843
|
+
)
|
844
|
+
|
845
|
+
|
846
|
+
async def main() -> None:
|
847
|
+
await client.voices.delete(
|
848
|
+
id="id",
|
849
|
+
)
|
850
|
+
|
851
|
+
|
852
|
+
asyncio.run(main())
|
853
|
+
"""
|
854
|
+
_response = await self._client_wrapper.httpx_client.request(
|
855
|
+
f"voices/{jsonable_encoder(id)}",
|
856
|
+
method="DELETE",
|
857
|
+
request_options=request_options,
|
858
|
+
)
|
859
|
+
try:
|
860
|
+
if 200 <= _response.status_code < 300:
|
861
|
+
return
|
862
|
+
_response_json = _response.json()
|
863
|
+
except JSONDecodeError:
|
864
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
865
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
866
|
+
|
867
|
+
async def update(
|
868
|
+
self, id: VoiceId, *, name: str, description: str, request_options: typing.Optional[RequestOptions] = None
|
869
|
+
) -> Voice:
|
870
|
+
"""
|
871
|
+
Parameters
|
872
|
+
----------
|
873
|
+
id : VoiceId
|
874
|
+
|
875
|
+
name : str
|
876
|
+
The name of the voice.
|
877
|
+
|
878
|
+
description : str
|
879
|
+
The description of the voice.
|
880
|
+
|
881
|
+
request_options : typing.Optional[RequestOptions]
|
882
|
+
Request-specific configuration.
|
883
|
+
|
884
|
+
Returns
|
885
|
+
-------
|
886
|
+
Voice
|
887
|
+
|
888
|
+
Examples
|
889
|
+
--------
|
890
|
+
import asyncio
|
891
|
+
|
892
|
+
from cartesia import AsyncCartesia
|
893
|
+
|
894
|
+
client = AsyncCartesia(
|
895
|
+
api_key="YOUR_API_KEY",
|
896
|
+
)
|
897
|
+
|
898
|
+
|
899
|
+
async def main() -> None:
|
900
|
+
await client.voices.update(
|
901
|
+
id="id",
|
902
|
+
name="name",
|
903
|
+
description="description",
|
904
|
+
)
|
905
|
+
|
906
|
+
|
907
|
+
asyncio.run(main())
|
908
|
+
"""
|
909
|
+
_response = await self._client_wrapper.httpx_client.request(
|
910
|
+
f"voices/{jsonable_encoder(id)}",
|
911
|
+
method="PATCH",
|
912
|
+
json={
|
913
|
+
"name": name,
|
914
|
+
"description": description,
|
915
|
+
},
|
916
|
+
request_options=request_options,
|
917
|
+
omit=OMIT,
|
918
|
+
)
|
919
|
+
try:
|
920
|
+
if 200 <= _response.status_code < 300:
|
921
|
+
return typing.cast(
|
922
|
+
Voice,
|
923
|
+
parse_obj_as(
|
924
|
+
type_=Voice, # type: ignore
|
925
|
+
object_=_response.json(),
|
926
|
+
),
|
927
|
+
)
|
928
|
+
_response_json = _response.json()
|
929
|
+
except JSONDecodeError:
|
930
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
931
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
932
|
+
|
933
|
+
async def get(self, id: VoiceId, *, request_options: typing.Optional[RequestOptions] = None) -> Voice:
|
934
|
+
"""
|
935
|
+
Parameters
|
936
|
+
----------
|
937
|
+
id : VoiceId
|
938
|
+
|
939
|
+
request_options : typing.Optional[RequestOptions]
|
940
|
+
Request-specific configuration.
|
941
|
+
|
942
|
+
Returns
|
943
|
+
-------
|
944
|
+
Voice
|
945
|
+
|
946
|
+
Examples
|
947
|
+
--------
|
948
|
+
import asyncio
|
949
|
+
|
950
|
+
from cartesia import AsyncCartesia
|
951
|
+
|
952
|
+
client = AsyncCartesia(
|
953
|
+
api_key="YOUR_API_KEY",
|
954
|
+
)
|
955
|
+
|
956
|
+
|
957
|
+
async def main() -> None:
|
958
|
+
await client.voices.get(
|
959
|
+
id="id",
|
960
|
+
)
|
961
|
+
|
962
|
+
|
963
|
+
asyncio.run(main())
|
964
|
+
"""
|
965
|
+
_response = await self._client_wrapper.httpx_client.request(
|
966
|
+
f"voices/{jsonable_encoder(id)}",
|
967
|
+
method="GET",
|
968
|
+
request_options=request_options,
|
969
|
+
)
|
970
|
+
try:
|
971
|
+
if 200 <= _response.status_code < 300:
|
972
|
+
return typing.cast(
|
973
|
+
Voice,
|
974
|
+
parse_obj_as(
|
975
|
+
type_=Voice, # type: ignore
|
976
|
+
object_=_response.json(),
|
977
|
+
),
|
978
|
+
)
|
979
|
+
_response_json = _response.json()
|
980
|
+
except JSONDecodeError:
|
981
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
982
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
983
|
+
|
984
|
+
async def localize(
|
985
|
+
self,
|
986
|
+
*,
|
987
|
+
voice_id: str,
|
988
|
+
name: str,
|
989
|
+
description: str,
|
990
|
+
language: LocalizeTargetLanguage,
|
991
|
+
original_speaker_gender: Gender,
|
992
|
+
dialect: typing.Optional[LocalizeDialectParams] = OMIT,
|
993
|
+
request_options: typing.Optional[RequestOptions] = None,
|
994
|
+
) -> VoiceMetadata:
|
995
|
+
"""
|
996
|
+
Create a new voice from an existing voice localized to a new language and dialect.
|
997
|
+
|
998
|
+
Parameters
|
999
|
+
----------
|
1000
|
+
voice_id : str
|
1001
|
+
The ID of the voice to localize.
|
1002
|
+
|
1003
|
+
name : str
|
1004
|
+
The name of the new localized voice.
|
1005
|
+
|
1006
|
+
description : str
|
1007
|
+
The description of the new localized voice.
|
1008
|
+
|
1009
|
+
language : LocalizeTargetLanguage
|
1010
|
+
|
1011
|
+
original_speaker_gender : Gender
|
1012
|
+
|
1013
|
+
dialect : typing.Optional[LocalizeDialectParams]
|
1014
|
+
|
1015
|
+
request_options : typing.Optional[RequestOptions]
|
1016
|
+
Request-specific configuration.
|
1017
|
+
|
1018
|
+
Returns
|
1019
|
+
-------
|
1020
|
+
VoiceMetadata
|
1021
|
+
|
1022
|
+
Examples
|
1023
|
+
--------
|
1024
|
+
import asyncio
|
1025
|
+
|
1026
|
+
from cartesia import AsyncCartesia
|
1027
|
+
|
1028
|
+
client = AsyncCartesia(
|
1029
|
+
api_key="YOUR_API_KEY",
|
1030
|
+
)
|
1031
|
+
|
1032
|
+
|
1033
|
+
async def main() -> None:
|
1034
|
+
await client.voices.localize(
|
1035
|
+
voice_id="694f9389-aac1-45b6-b726-9d9369183238",
|
1036
|
+
name="Sarah Peninsular Spanish",
|
1037
|
+
description="Sarah Voice in Peninsular Spanish",
|
1038
|
+
language="es",
|
1039
|
+
original_speaker_gender="female",
|
1040
|
+
dialect="pe",
|
1041
|
+
)
|
1042
|
+
|
1043
|
+
|
1044
|
+
asyncio.run(main())
|
1045
|
+
"""
|
1046
|
+
_response = await self._client_wrapper.httpx_client.request(
|
1047
|
+
"voices/localize",
|
1048
|
+
method="POST",
|
1049
|
+
json={
|
1050
|
+
"voice_id": voice_id,
|
1051
|
+
"name": name,
|
1052
|
+
"description": description,
|
1053
|
+
"language": language,
|
1054
|
+
"original_speaker_gender": original_speaker_gender,
|
1055
|
+
"dialect": convert_and_respect_annotation_metadata(
|
1056
|
+
object_=dialect, annotation=LocalizeDialectParams, direction="write"
|
1057
|
+
),
|
1058
|
+
},
|
1059
|
+
request_options=request_options,
|
1060
|
+
omit=OMIT,
|
1061
|
+
)
|
1062
|
+
try:
|
1063
|
+
if 200 <= _response.status_code < 300:
|
1064
|
+
return typing.cast(
|
1065
|
+
VoiceMetadata,
|
1066
|
+
parse_obj_as(
|
1067
|
+
type_=VoiceMetadata, # type: ignore
|
1068
|
+
object_=_response.json(),
|
1069
|
+
),
|
1070
|
+
)
|
1071
|
+
_response_json = _response.json()
|
1072
|
+
except JSONDecodeError:
|
1073
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
1074
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
1075
|
+
|
1076
|
+
async def mix(
|
1077
|
+
self,
|
1078
|
+
*,
|
1079
|
+
voices: typing.Sequence[MixVoiceSpecifierParams],
|
1080
|
+
request_options: typing.Optional[RequestOptions] = None,
|
1081
|
+
) -> EmbeddingResponse:
|
1082
|
+
"""
|
1083
|
+
Parameters
|
1084
|
+
----------
|
1085
|
+
voices : typing.Sequence[MixVoiceSpecifierParams]
|
1086
|
+
|
1087
|
+
request_options : typing.Optional[RequestOptions]
|
1088
|
+
Request-specific configuration.
|
1089
|
+
|
1090
|
+
Returns
|
1091
|
+
-------
|
1092
|
+
EmbeddingResponse
|
1093
|
+
|
1094
|
+
Examples
|
1095
|
+
--------
|
1096
|
+
import asyncio
|
1097
|
+
|
1098
|
+
from cartesia import AsyncCartesia
|
1099
|
+
|
1100
|
+
client = AsyncCartesia(
|
1101
|
+
api_key="YOUR_API_KEY",
|
1102
|
+
)
|
1103
|
+
|
1104
|
+
|
1105
|
+
async def main() -> None:
|
1106
|
+
await client.voices.mix(
|
1107
|
+
voices=[{"id": "id", "weight": 1.1}, {"id": "id", "weight": 1.1}],
|
1108
|
+
)
|
1109
|
+
|
1110
|
+
|
1111
|
+
asyncio.run(main())
|
1112
|
+
"""
|
1113
|
+
_response = await self._client_wrapper.httpx_client.request(
|
1114
|
+
"voices/mix",
|
1115
|
+
method="POST",
|
1116
|
+
json={
|
1117
|
+
"voices": convert_and_respect_annotation_metadata(
|
1118
|
+
object_=voices, annotation=typing.Sequence[MixVoiceSpecifierParams], direction="write"
|
1119
|
+
),
|
1120
|
+
},
|
1121
|
+
request_options=request_options,
|
1122
|
+
omit=OMIT,
|
1123
|
+
)
|
1124
|
+
try:
|
1125
|
+
if 200 <= _response.status_code < 300:
|
1126
|
+
return typing.cast(
|
1127
|
+
EmbeddingResponse,
|
1128
|
+
parse_obj_as(
|
1129
|
+
type_=EmbeddingResponse, # type: ignore
|
1130
|
+
object_=_response.json(),
|
1131
|
+
),
|
1132
|
+
)
|
1133
|
+
_response_json = _response.json()
|
1134
|
+
except JSONDecodeError:
|
1135
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
1136
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
1137
|
+
|
1138
|
+
async def create(
|
1139
|
+
self,
|
1140
|
+
*,
|
1141
|
+
name: str,
|
1142
|
+
description: str,
|
1143
|
+
embedding: Embedding,
|
1144
|
+
language: typing.Optional[SupportedLanguage] = OMIT,
|
1145
|
+
base_voice_id: typing.Optional[BaseVoiceId] = OMIT,
|
1146
|
+
request_options: typing.Optional[RequestOptions] = None,
|
1147
|
+
) -> Voice:
|
1148
|
+
"""
|
1149
|
+
Create voice from raw features. If you'd like to clone a voice from an audio file, please use Clone Voice instead.
|
1150
|
+
|
1151
|
+
Parameters
|
1152
|
+
----------
|
1153
|
+
name : str
|
1154
|
+
The name of the voice.
|
1155
|
+
|
1156
|
+
description : str
|
1157
|
+
The description of the voice.
|
1158
|
+
|
1159
|
+
embedding : Embedding
|
1160
|
+
|
1161
|
+
language : typing.Optional[SupportedLanguage]
|
1162
|
+
|
1163
|
+
base_voice_id : typing.Optional[BaseVoiceId]
|
1164
|
+
|
1165
|
+
request_options : typing.Optional[RequestOptions]
|
1166
|
+
Request-specific configuration.
|
1167
|
+
|
1168
|
+
Returns
|
1169
|
+
-------
|
1170
|
+
Voice
|
1171
|
+
|
1172
|
+
Examples
|
1173
|
+
--------
|
1174
|
+
import asyncio
|
1175
|
+
|
1176
|
+
from cartesia import AsyncCartesia
|
1177
|
+
|
1178
|
+
client = AsyncCartesia(
|
1179
|
+
api_key="YOUR_API_KEY",
|
1180
|
+
)
|
1181
|
+
|
1182
|
+
|
1183
|
+
async def main() -> None:
|
1184
|
+
await client.voices.create(
|
1185
|
+
name="name",
|
1186
|
+
description="description",
|
1187
|
+
embedding=[1.1, 1.1],
|
1188
|
+
)
|
1189
|
+
|
1190
|
+
|
1191
|
+
asyncio.run(main())
|
1192
|
+
"""
|
1193
|
+
_response = await self._client_wrapper.httpx_client.request(
|
1194
|
+
"voices/",
|
1195
|
+
method="POST",
|
1196
|
+
json={
|
1197
|
+
"name": name,
|
1198
|
+
"description": description,
|
1199
|
+
"embedding": embedding,
|
1200
|
+
"language": language,
|
1201
|
+
"base_voice_id": base_voice_id,
|
1202
|
+
},
|
1203
|
+
request_options=request_options,
|
1204
|
+
omit=OMIT,
|
1205
|
+
)
|
1206
|
+
try:
|
1207
|
+
if 200 <= _response.status_code < 300:
|
1208
|
+
return typing.cast(
|
1209
|
+
Voice,
|
1210
|
+
parse_obj_as(
|
1211
|
+
type_=Voice, # type: ignore
|
1212
|
+
object_=_response.json(),
|
1213
|
+
),
|
1214
|
+
)
|
1215
|
+
_response_json = _response.json()
|
1216
|
+
except JSONDecodeError:
|
1217
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
1218
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|