cartesia 1.0.8__tar.gz → 1.0.10__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.
- {cartesia-1.0.8 → cartesia-1.0.10}/PKG-INFO +1 -1
- cartesia-1.0.10/cartesia/__init__.py +3 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia/_types.py +3 -2
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia/client.py +13 -10
- cartesia-1.0.10/cartesia/version.py +1 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia.egg-info/PKG-INFO +1 -1
- {cartesia-1.0.8 → cartesia-1.0.10}/pyproject.toml +11 -11
- {cartesia-1.0.8 → cartesia-1.0.10}/tests/test_deprecated.py +1 -2
- {cartesia-1.0.8 → cartesia-1.0.10}/tests/test_tts.py +19 -10
- cartesia-1.0.8/cartesia/__init__.py +0 -3
- cartesia-1.0.8/cartesia/version.py +0 -1
- {cartesia-1.0.8 → cartesia-1.0.10}/LICENSE.md +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/README.md +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia/utils/__init__.py +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia/utils/deprecated.py +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia/utils/retry.py +3 -3
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia.egg-info/SOURCES.txt +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia.egg-info/dependency_links.txt +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia.egg-info/requires.txt +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/cartesia.egg-info/top_level.txt +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/setup.cfg +0 -0
- {cartesia-1.0.8 → cartesia-1.0.10}/setup.py +0 -0
@@ -1,4 +1,5 @@
|
|
1
|
-
from typing import List, TypedDict
|
1
|
+
from typing import List, TypedDict, Union
|
2
|
+
|
2
3
|
from cartesia.utils.deprecated import deprecated
|
3
4
|
|
4
5
|
|
@@ -85,7 +86,7 @@ class VoiceControls(TypedDict):
|
|
85
86
|
This is an experimental class and is subject to rapid change in future versions.
|
86
87
|
"""
|
87
88
|
|
88
|
-
speed: str = ""
|
89
|
+
speed: Union[str, float] = ""
|
89
90
|
emotion: List[str] = []
|
90
91
|
|
91
92
|
|
@@ -1,46 +1,48 @@
|
|
1
1
|
import asyncio
|
2
2
|
import base64
|
3
|
-
from collections import defaultdict
|
4
3
|
import json
|
4
|
+
import logging
|
5
5
|
import os
|
6
6
|
import uuid
|
7
|
+
from collections import defaultdict
|
7
8
|
from types import TracebackType
|
8
9
|
from typing import (
|
9
10
|
Any,
|
10
11
|
AsyncGenerator,
|
11
|
-
|
12
|
+
Callable,
|
12
13
|
Dict,
|
13
14
|
Generator,
|
15
|
+
Iterator,
|
14
16
|
List,
|
15
17
|
Optional,
|
18
|
+
Set,
|
16
19
|
Tuple,
|
17
20
|
Union,
|
18
|
-
Callable,
|
19
|
-
Set,
|
20
21
|
)
|
21
22
|
|
22
23
|
import aiohttp
|
23
24
|
import httpx
|
24
|
-
import logging
|
25
25
|
import requests
|
26
|
+
|
26
27
|
try:
|
27
28
|
from websockets.sync.client import connect
|
29
|
+
|
28
30
|
IS_WEBSOCKET_SYNC_AVAILABLE = True
|
29
31
|
except ImportError:
|
30
32
|
IS_WEBSOCKET_SYNC_AVAILABLE = False
|
31
33
|
|
32
34
|
from iterators import TimeoutIterator
|
35
|
+
from websockets.sync.client import connect
|
33
36
|
|
34
|
-
from cartesia.utils.retry import retry_on_connection_error, retry_on_connection_error_async
|
35
37
|
from cartesia._types import (
|
38
|
+
DeprecatedOutputFormatMapping,
|
36
39
|
EventType,
|
37
40
|
OutputFormat,
|
38
41
|
OutputFormatMapping,
|
39
|
-
DeprecatedOutputFormatMapping,
|
40
42
|
VoiceControls,
|
41
43
|
VoiceMetadata,
|
42
44
|
)
|
43
|
-
|
45
|
+
from cartesia.utils.retry import retry_on_connection_error, retry_on_connection_error_async
|
44
46
|
|
45
47
|
DEFAULT_MODEL_ID = "sonic-english" # latest default model
|
46
48
|
MULTILINGUAL_MODEL_ID = "sonic-multilingual" # latest multilingual model
|
@@ -212,21 +214,22 @@ class Voices(Resource):
|
|
212
214
|
|
213
215
|
return response.json()
|
214
216
|
|
215
|
-
def clone(self, filepath: Optional[str] = None,
|
217
|
+
def clone(self, filepath: Optional[str] = None, enhance: str = True) -> List[float]:
|
216
218
|
"""Clone a voice from a clip.
|
217
219
|
|
218
220
|
Args:
|
219
221
|
filepath: The path to the clip file.
|
222
|
+
enhance: Whether to enhance the clip before cloning the voice (highly recommended). Defaults to True.
|
220
223
|
|
221
224
|
Returns:
|
222
225
|
The embedding of the cloned voice as a list of floats.
|
223
226
|
"""
|
224
|
-
# TODO: Python has a bytes object, use that instead of a filepath
|
225
227
|
if not filepath:
|
226
228
|
raise ValueError("Filepath must be specified.")
|
227
229
|
url = f"{self._http_url()}/voices/clone/clip"
|
228
230
|
with open(filepath, "rb") as file:
|
229
231
|
files = {"clip": file}
|
232
|
+
files["enhance"] = str(enhance).lower()
|
230
233
|
headers = self.headers.copy()
|
231
234
|
headers.pop("Content-Type", None)
|
232
235
|
response = httpx.post(url, headers=headers, files=files, timeout=self.timeout)
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "1.0.10"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.ruff]
|
2
2
|
# Add more rule codes as needed
|
3
|
-
extend-select = [
|
3
|
+
lint.extend-select = [
|
4
4
|
"D", # pydocstyle - to replace docformatter
|
5
5
|
]
|
6
6
|
|
@@ -43,14 +43,14 @@ line-length = 100
|
|
43
43
|
# Enable the count of violations
|
44
44
|
output-format = "full"
|
45
45
|
|
46
|
-
[tool.ruff.
|
47
|
-
force-wrap-aliases = true
|
48
|
-
combine-as-imports = true
|
49
|
-
force-sort-within-sections = true
|
50
|
-
known-first-party = []
|
51
|
-
known-third-party = []
|
52
|
-
known-local-folder = []
|
53
|
-
lines-after-imports = 2
|
54
|
-
|
55
|
-
[tool.ruff.pydocstyle]
|
46
|
+
[tool.ruff.lint.pydocstyle]
|
56
47
|
convention = "google"
|
48
|
+
|
49
|
+
[tool.isort]
|
50
|
+
profile = "black"
|
51
|
+
multi_line_output = 3
|
52
|
+
include_trailing_comma = true
|
53
|
+
force_grid_wrap = 0
|
54
|
+
use_parentheses = true
|
55
|
+
ensure_newline_before_comments = true
|
56
|
+
line_length = 100
|
@@ -1,8 +1,7 @@
|
|
1
1
|
from packaging.version import Version
|
2
2
|
|
3
|
-
import cartesia as Cartesia
|
4
|
-
from cartesia.utils.deprecated import _DEPRECATED_FUNCTION_STATS
|
5
3
|
import cartesia.version as version
|
4
|
+
from cartesia.utils.deprecated import _DEPRECATED_FUNCTION_STATS
|
6
5
|
|
7
6
|
|
8
7
|
def test_deprecated_to_remove_by_version():
|
@@ -5,17 +5,19 @@ different results. Therefore, we cannot test for complete correctness but rather
|
|
5
5
|
general correctness.
|
6
6
|
"""
|
7
7
|
|
8
|
+
import asyncio
|
8
9
|
import logging
|
9
10
|
import os
|
10
11
|
import sys
|
11
|
-
|
12
|
-
from cartesia.client import DEFAULT_MODEL_ID, MULTILINGUAL_MODEL_ID
|
13
|
-
from cartesia._types import VoiceControls, VoiceMetadata
|
12
|
+
import uuid
|
14
13
|
from typing import AsyncGenerator, Generator, List
|
14
|
+
|
15
15
|
import numpy as np
|
16
16
|
import pytest
|
17
|
-
|
18
|
-
import
|
17
|
+
|
18
|
+
from cartesia import AsyncCartesia, Cartesia
|
19
|
+
from cartesia._types import VoiceControls, VoiceMetadata
|
20
|
+
from cartesia.client import DEFAULT_MODEL_ID, MULTILINGUAL_MODEL_ID
|
19
21
|
|
20
22
|
THISDIR = os.path.dirname(__file__)
|
21
23
|
sys.path.insert(0, os.path.dirname(THISDIR))
|
@@ -24,6 +26,7 @@ RESOURCES_DIR = os.path.join(THISDIR, "resources")
|
|
24
26
|
SAMPLE_VOICE = "Newsman"
|
25
27
|
SAMPLE_VOICE_ID = "d46abd1d-2d02-43e8-819f-51fb652c1c61"
|
26
28
|
EXPERIMENTAL_VOICE_CONTROLS = {"emotion": ["anger:high", "positivity:low"], "speed": "fastest"}
|
29
|
+
EXPERIMENTAL_VOICE_CONTROLS_2 = {"speed": 0.4}
|
27
30
|
|
28
31
|
logger = logging.getLogger(__name__)
|
29
32
|
|
@@ -84,6 +87,12 @@ def test_clone_voice_with_file(client: Cartesia):
|
|
84
87
|
output = client.voices.clone(filepath=os.path.join(RESOURCES_DIR, "sample-speech-4s.wav"))
|
85
88
|
assert isinstance(output, list)
|
86
89
|
|
90
|
+
@pytest.mark.parametrize("enhance", [True, False])
|
91
|
+
def test_clone_voice_with_file_enhance(client: Cartesia, enhance: bool):
|
92
|
+
logger.info("Testing voices.clone with file")
|
93
|
+
output = client.voices.clone(filepath=os.path.join(RESOURCES_DIR, "sample-speech-4s.wav"), enhance=enhance)
|
94
|
+
assert isinstance(output, list)
|
95
|
+
|
87
96
|
def test_create_voice(client: Cartesia):
|
88
97
|
logger.info("Testing voices.create")
|
89
98
|
embedding = np.ones(192).tolist()
|
@@ -95,7 +104,7 @@ def test_create_voice(client: Cartesia):
|
|
95
104
|
assert voice in voices
|
96
105
|
|
97
106
|
@pytest.mark.parametrize("stream", [True, False])
|
98
|
-
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS])
|
107
|
+
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS, EXPERIMENTAL_VOICE_CONTROLS_2])
|
99
108
|
def test_sse_send(resources: _Resources, stream: bool, _experimental_voice_controls: VoiceControls):
|
100
109
|
logger.info("Testing SSE send")
|
101
110
|
client = resources.client
|
@@ -132,7 +141,7 @@ def test_sse_send_with_model_id(resources: _Resources, stream: bool):
|
|
132
141
|
assert isinstance(out["audio"], bytes)
|
133
142
|
|
134
143
|
@pytest.mark.parametrize("stream", [True, False])
|
135
|
-
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS])
|
144
|
+
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS, EXPERIMENTAL_VOICE_CONTROLS_2])
|
136
145
|
def test_websocket_send(resources: _Resources, stream: bool, _experimental_voice_controls: VoiceControls):
|
137
146
|
logger.info("Testing WebSocket send")
|
138
147
|
client = resources.client
|
@@ -182,7 +191,7 @@ def test_websocket_send_timestamps(resources: _Resources, stream: bool):
|
|
182
191
|
ws.close()
|
183
192
|
|
184
193
|
|
185
|
-
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS])
|
194
|
+
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS, EXPERIMENTAL_VOICE_CONTROLS_2])
|
186
195
|
def test_sse_send_context_manager(resources: _Resources, _experimental_voice_controls: VoiceControls):
|
187
196
|
logger.info("Testing SSE send context manager")
|
188
197
|
transcript = "Hello, world! I'\''m generating audio on Cartesia."
|
@@ -248,7 +257,7 @@ def test_websocket_send_context_manage_err(resources: _Resources):
|
|
248
257
|
pass
|
249
258
|
|
250
259
|
@pytest.mark.asyncio
|
251
|
-
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS])
|
260
|
+
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS, EXPERIMENTAL_VOICE_CONTROLS_2])
|
252
261
|
async def test_async_sse_send( resources: _Resources, _experimental_voice_controls: VoiceControls):
|
253
262
|
logger.info("Testing async SSE send")
|
254
263
|
transcript = "Hello, world! I'\''m generating audio on Cartesia."
|
@@ -269,7 +278,7 @@ async def test_async_sse_send( resources: _Resources, _experimental_voice_contro
|
|
269
278
|
await async_client.close()
|
270
279
|
|
271
280
|
@pytest.mark.asyncio
|
272
|
-
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS])
|
281
|
+
@pytest.mark.parametrize("_experimental_voice_controls", [None, EXPERIMENTAL_VOICE_CONTROLS, EXPERIMENTAL_VOICE_CONTROLS_2])
|
273
282
|
async def test_async_websocket_send(resources: _Resources, _experimental_voice_controls: VoiceControls):
|
274
283
|
logger.info("Testing async WebSocket send")
|
275
284
|
transcript = "Hello, world! I'\''m generating audio on Cartesia."
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "1.0.8"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import time
|
2
|
-
|
3
|
-
from aiohttp.client_exceptions import ServerDisconnectedError
|
4
1
|
import asyncio
|
2
|
+
import time
|
5
3
|
from functools import wraps
|
6
4
|
from http.client import RemoteDisconnected
|
5
|
+
|
6
|
+
from aiohttp.client_exceptions import ServerDisconnectedError
|
7
7
|
from httpx import TimeoutException
|
8
8
|
from requests.exceptions import ConnectionError
|
9
9
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|