typecast-python 0.3.8__py3-none-any.whl → 0.3.10__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.
- typecast/async_client.py +5 -2
- typecast/client.py +21 -2
- typecast/composer.py +46 -104
- typecast/models/tts.py +6 -4
- typecast/models/voices.py +7 -5
- {typecast_python-0.3.8.dist-info → typecast_python-0.3.10.dist-info}/METADATA +14 -10
- typecast_python-0.3.10.dist-info/RECORD +18 -0
- {typecast_python-0.3.8.dist-info → typecast_python-0.3.10.dist-info}/WHEEL +1 -1
- typecast_python-0.3.8.dist-info/RECORD +0 -18
- {typecast_python-0.3.8.dist-info → typecast_python-0.3.10.dist-info}/licenses/LICENSE +0 -0
typecast/async_client.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import asyncio
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
from typing import AsyncIterator, BinaryIO, Optional, Union
|
|
@@ -208,7 +210,8 @@ class AsyncTypecast:
|
|
|
208
210
|
seed=seed,
|
|
209
211
|
)
|
|
210
212
|
)
|
|
211
|
-
|
|
213
|
+
loop = asyncio.get_running_loop()
|
|
214
|
+
await loop.run_in_executor(None, output_path.write_bytes, response.audio_data)
|
|
212
215
|
return response
|
|
213
216
|
|
|
214
217
|
async def text_to_speech_stream(
|
|
@@ -255,7 +258,7 @@ class AsyncTypecast:
|
|
|
255
258
|
error_text = await response.text()
|
|
256
259
|
self._handle_error(response.status, error_text)
|
|
257
260
|
|
|
258
|
-
async for chunk in response.content.iter_chunked(chunk_size):
|
|
261
|
+
async for chunk in response.content.iter_chunked(chunk_size): # pragma: no branch
|
|
259
262
|
yield chunk
|
|
260
263
|
|
|
261
264
|
async def text_to_speech_with_timestamps(
|
typecast/client.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from pathlib import Path
|
|
2
4
|
from typing import BinaryIO, Iterator, Optional, Union
|
|
3
5
|
from urllib.parse import quote
|
|
@@ -195,10 +197,11 @@ class Typecast:
|
|
|
195
197
|
if response.status_code != 200:
|
|
196
198
|
self._handle_error(response.status_code, response.text)
|
|
197
199
|
|
|
200
|
+
content_type = response.headers.get("Content-Type", "audio/wav").lower()
|
|
198
201
|
return TTSResponse(
|
|
199
202
|
audio_data=response.content,
|
|
200
203
|
duration=response.headers.get("X-Audio-Duration", 0),
|
|
201
|
-
format=
|
|
204
|
+
format="mp3" if "mp3" in content_type or "mpeg" in content_type else "wav",
|
|
202
205
|
)
|
|
203
206
|
|
|
204
207
|
def compose_speech(self) -> SpeechComposer:
|
|
@@ -207,7 +210,23 @@ class Typecast:
|
|
|
207
210
|
Text passed to ``say()`` may include pause markup such as ``<|0.3s|>``.
|
|
208
211
|
``pause(seconds)`` also uses seconds, e.g. ``0.3`` for 300 ms.
|
|
209
212
|
"""
|
|
210
|
-
return SpeechComposer(self.
|
|
213
|
+
return SpeechComposer(self.compose_text_to_speech)
|
|
214
|
+
|
|
215
|
+
def compose_text_to_speech(self, segments: list[dict]) -> TTSResponse:
|
|
216
|
+
response = self.session.post(
|
|
217
|
+
f"{self.host}/v1/text-to-speech/compose",
|
|
218
|
+
json={"segments": segments},
|
|
219
|
+
headers=self._request_headers(),
|
|
220
|
+
timeout=(10, 300),
|
|
221
|
+
)
|
|
222
|
+
if response.status_code != 200:
|
|
223
|
+
self._handle_error(response.status_code, response.text)
|
|
224
|
+
content_type = response.headers.get("Content-Type", "audio/wav").lower()
|
|
225
|
+
return TTSResponse(
|
|
226
|
+
audio_data=response.content,
|
|
227
|
+
duration=response.headers.get("X-Audio-Duration", 0),
|
|
228
|
+
format="mp3" if "mp3" in content_type or "mpeg" in content_type else "wav",
|
|
229
|
+
)
|
|
211
230
|
|
|
212
231
|
def generate_to_file(
|
|
213
232
|
self,
|
typecast/composer.py
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import io
|
|
4
3
|
import math
|
|
5
4
|
import re
|
|
6
|
-
import struct
|
|
7
|
-
import wave
|
|
8
5
|
from dataclasses import dataclass
|
|
9
6
|
from typing import Callable, Literal, Optional, Union
|
|
10
7
|
|
|
@@ -31,19 +28,6 @@ class _SpeechPart:
|
|
|
31
28
|
settings: "_ComposerSettings"
|
|
32
29
|
|
|
33
30
|
|
|
34
|
-
@dataclass(frozen=True)
|
|
35
|
-
class _WavSpec:
|
|
36
|
-
sample_rate: int
|
|
37
|
-
channels: int
|
|
38
|
-
sample_width: int
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@dataclass(frozen=True)
|
|
42
|
-
class _ParsedWav:
|
|
43
|
-
spec: _WavSpec
|
|
44
|
-
samples: list[int]
|
|
45
|
-
|
|
46
|
-
|
|
47
31
|
@dataclass(frozen=True)
|
|
48
32
|
class _ComposerSettings:
|
|
49
33
|
voice_id: Optional[str] = None
|
|
@@ -55,8 +39,8 @@ class _ComposerSettings:
|
|
|
55
39
|
|
|
56
40
|
|
|
57
41
|
class SpeechComposer:
|
|
58
|
-
def __init__(self,
|
|
59
|
-
self.
|
|
42
|
+
def __init__(self, compose: Callable[[list[dict]], TTSResponse]):
|
|
43
|
+
self._compose = compose
|
|
60
44
|
self._defaults = _ComposerSettings()
|
|
61
45
|
self._parts: list[Union[_SpeechPart, _PausePart]] = []
|
|
62
46
|
|
|
@@ -124,41 +108,29 @@ class SpeechComposer:
|
|
|
124
108
|
if not any(isinstance(part, _SpeechPart) for part in plan):
|
|
125
109
|
raise ValueError("at least one speech segment is required")
|
|
126
110
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
111
|
+
formats = {
|
|
112
|
+
part.settings.output.audio_format
|
|
113
|
+
for part in plan
|
|
114
|
+
if isinstance(part, _SpeechPart)
|
|
115
|
+
and part.settings.output
|
|
116
|
+
and part.settings.output.audio_format
|
|
117
|
+
}
|
|
118
|
+
if len(formats) > 1:
|
|
119
|
+
raise ValueError("composed speech segments must use one audio format")
|
|
120
|
+
output_format = next(iter(formats), "wav")
|
|
130
121
|
if output_format not in ("wav", "mp3"):
|
|
131
|
-
raise ValueError(
|
|
122
|
+
raise ValueError(
|
|
123
|
+
f"unsupported composed speech output format: {output_format}"
|
|
124
|
+
)
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
output_samples: list[int] = []
|
|
126
|
+
segments: list[dict] = []
|
|
135
127
|
for part in plan:
|
|
136
128
|
if isinstance(part, _PausePart):
|
|
137
|
-
|
|
138
|
-
raise ValueError("pause cannot be the first composed part")
|
|
139
|
-
output_samples.extend(
|
|
140
|
-
[0] * _seconds_to_samples(part.seconds, wav_spec.sample_rate)
|
|
141
|
-
)
|
|
129
|
+
segments.append({"type": "pause", "duration_seconds": part.seconds})
|
|
142
130
|
continue
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
wav = _parse_wav(response.audio_data)
|
|
147
|
-
if wav_spec is not None and wav.spec != wav_spec:
|
|
148
|
-
raise ValueError("all composed WAV segments must use the same PCM format")
|
|
149
|
-
wav_spec = wav.spec
|
|
150
|
-
output_samples.extend(_trim_silence(wav.samples))
|
|
151
|
-
|
|
152
|
-
final_spec = wav_spec
|
|
153
|
-
assert final_spec is not None
|
|
154
|
-
wav_bytes = _encode_wav(output_samples, final_spec)
|
|
155
|
-
if output_format == "mp3":
|
|
156
|
-
raise ValueError("ffmpeg is required to encode composed speech as mp3")
|
|
157
|
-
return TTSResponse(
|
|
158
|
-
audio_data=wav_bytes,
|
|
159
|
-
duration=len(output_samples) / final_spec.sample_rate,
|
|
160
|
-
format="wav",
|
|
161
|
-
)
|
|
131
|
+
request = _settings_to_request(part.text, part.settings, output_format)
|
|
132
|
+
segments.append({"type": "tts", **request.model_dump(exclude_none=True)})
|
|
133
|
+
return self._compose(segments)
|
|
162
134
|
|
|
163
135
|
def _build_plan(self) -> list[Union[_SpeechPart, _PausePart]]:
|
|
164
136
|
plan: list[Union[_SpeechPart, _PausePart]] = []
|
|
@@ -173,7 +145,9 @@ class SpeechComposer:
|
|
|
173
145
|
if not parsed.text.strip():
|
|
174
146
|
continue
|
|
175
147
|
if not part.settings.voice_id:
|
|
176
|
-
raise ValueError(
|
|
148
|
+
raise ValueError(
|
|
149
|
+
"voice_id is required for composed speech segments"
|
|
150
|
+
)
|
|
177
151
|
if not part.settings.model:
|
|
178
152
|
raise ValueError("model is required for composed speech segments")
|
|
179
153
|
plan.append(_SpeechPart(text=parsed.text, settings=part.settings))
|
|
@@ -184,10 +158,14 @@ def parse_pause_markup(text: str) -> list[Union[_TextPart, _PausePart]]:
|
|
|
184
158
|
parts: list[Union[_TextPart, _PausePart]] = []
|
|
185
159
|
last_index = 0
|
|
186
160
|
for match in _PAUSE_TOKEN.finditer(text):
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
161
|
+
seconds = float(match.group(1))
|
|
162
|
+
if math.isfinite(seconds) and seconds > 0:
|
|
163
|
+
if match.start() > last_index:
|
|
164
|
+
parts.append(
|
|
165
|
+
_TextPart(kind="text", text=text[last_index : match.start()])
|
|
166
|
+
)
|
|
167
|
+
parts.append(_PausePart(kind="pause", seconds=seconds))
|
|
168
|
+
last_index = match.end()
|
|
191
169
|
if last_index < len(text):
|
|
192
170
|
parts.append(_TextPart(kind="text", text=text[last_index:]))
|
|
193
171
|
return parts
|
|
@@ -207,69 +185,33 @@ def _merge_settings(
|
|
|
207
185
|
)
|
|
208
186
|
|
|
209
187
|
|
|
210
|
-
def _merge_output(
|
|
188
|
+
def _merge_output(
|
|
189
|
+
base: Optional[Output], override: Optional[Output]
|
|
190
|
+
) -> Optional[Output]:
|
|
211
191
|
if base is None and override is None:
|
|
212
192
|
return None
|
|
213
|
-
data =
|
|
193
|
+
data = (
|
|
194
|
+
base.model_dump(exclude_none=True, exclude_unset=True)
|
|
195
|
+
if base is not None
|
|
196
|
+
else {}
|
|
197
|
+
)
|
|
214
198
|
if override is not None:
|
|
215
199
|
data.update(override.model_dump(exclude_none=True, exclude_unset=True))
|
|
216
200
|
return Output(**data)
|
|
217
201
|
|
|
218
202
|
|
|
219
|
-
def _settings_to_request(
|
|
220
|
-
|
|
203
|
+
def _settings_to_request(
|
|
204
|
+
text: str, settings: _ComposerSettings, output_format: str
|
|
205
|
+
) -> TTSRequest:
|
|
206
|
+
output = _merge_output(settings.output, Output(audio_format=output_format))
|
|
221
207
|
return TTSRequest(
|
|
222
208
|
text=text,
|
|
223
209
|
voice_id=settings.voice_id or "",
|
|
224
|
-
model=settings.model
|
|
210
|
+
model=settings.model
|
|
211
|
+
if isinstance(settings.model, TTSModel)
|
|
212
|
+
else TTSModel(settings.model),
|
|
225
213
|
language=settings.language,
|
|
226
214
|
prompt=settings.prompt,
|
|
227
215
|
output=output,
|
|
228
216
|
seed=settings.seed,
|
|
229
217
|
)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def _parse_wav(data: bytes) -> _ParsedWav:
|
|
233
|
-
try:
|
|
234
|
-
with wave.open(io.BytesIO(data), "rb") as reader:
|
|
235
|
-
channels = reader.getnchannels()
|
|
236
|
-
sample_width = reader.getsampwidth()
|
|
237
|
-
sample_rate = reader.getframerate()
|
|
238
|
-
if channels != 1 or sample_width != 2:
|
|
239
|
-
raise ValueError("only mono 16-bit PCM WAV is supported for composed speech")
|
|
240
|
-
frames = reader.readframes(reader.getnframes())
|
|
241
|
-
except (EOFError, wave.Error) as exc:
|
|
242
|
-
raise ValueError("unsupported WAV data") from exc
|
|
243
|
-
samples = [
|
|
244
|
-
struct.unpack("<h", frames[offset : offset + 2])[0]
|
|
245
|
-
for offset in range(0, len(frames), 2)
|
|
246
|
-
]
|
|
247
|
-
return _ParsedWav(
|
|
248
|
-
spec=_WavSpec(sample_rate=sample_rate, channels=channels, sample_width=sample_width),
|
|
249
|
-
samples=samples,
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
def _encode_wav(samples: list[int], spec: _WavSpec) -> bytes:
|
|
254
|
-
payload = b"".join(struct.pack("<h", sample) for sample in samples)
|
|
255
|
-
out = io.BytesIO()
|
|
256
|
-
with wave.open(out, "wb") as writer:
|
|
257
|
-
writer.setnchannels(spec.channels)
|
|
258
|
-
writer.setsampwidth(spec.sample_width)
|
|
259
|
-
writer.setframerate(spec.sample_rate)
|
|
260
|
-
writer.writeframes(payload)
|
|
261
|
-
return out.getvalue()
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def _trim_silence(samples: list[int]) -> list[int]:
|
|
265
|
-
start = 0
|
|
266
|
-
end = len(samples)
|
|
267
|
-
while start < end and samples[start] == 0:
|
|
268
|
-
start += 1
|
|
269
|
-
while end > start and samples[end - 1] == 0:
|
|
270
|
-
end -= 1
|
|
271
|
-
return samples[start:end]
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
def _seconds_to_samples(seconds: float, sample_rate: int) -> int:
|
|
275
|
-
return round(seconds * sample_rate)
|
typecast/models/tts.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from enum import Enum
|
|
2
|
-
from typing import Literal, Optional, Union
|
|
4
|
+
from typing import List, Literal, Optional, Union
|
|
3
5
|
|
|
4
6
|
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
5
7
|
|
|
@@ -330,7 +332,7 @@ def _group_into_cues(
|
|
|
330
332
|
word_mode=True: parts are joined with a single space.
|
|
331
333
|
word_mode=False: parts are concatenated directly.
|
|
332
334
|
|
|
333
|
-
Returns
|
|
335
|
+
Returns List[(text, start, end)] tuples.
|
|
334
336
|
"""
|
|
335
337
|
cues = []
|
|
336
338
|
cur_text_parts = []
|
|
@@ -404,11 +406,11 @@ class TTSWithTimestampsResponse(BaseModel):
|
|
|
404
406
|
audio: str = Field(description="Base64-encoded audio bytes.")
|
|
405
407
|
audio_format: Literal["wav", "mp3"] = Field(description="Audio encoding format.")
|
|
406
408
|
audio_duration: float = Field(description="Length of audio in seconds.")
|
|
407
|
-
words: Optional[
|
|
409
|
+
words: Optional[List[AlignmentSegmentWord]] = Field(
|
|
408
410
|
default=None,
|
|
409
411
|
description="Word-level timestamps; null when granularity=char.",
|
|
410
412
|
)
|
|
411
|
-
characters: Optional[
|
|
413
|
+
characters: Optional[List[AlignmentSegmentCharacter]] = Field(
|
|
412
414
|
default=None,
|
|
413
415
|
description="Character-level timestamps; null when granularity=word.",
|
|
414
416
|
)
|
typecast/models/voices.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from enum import Enum
|
|
2
|
-
from typing import Optional
|
|
4
|
+
from typing import List, Optional
|
|
3
5
|
|
|
4
6
|
from pydantic import BaseModel, Field
|
|
5
7
|
|
|
@@ -12,7 +14,7 @@ class VoicesResponse(BaseModel):
|
|
|
12
14
|
voice_id: str
|
|
13
15
|
voice_name: str
|
|
14
16
|
model: str
|
|
15
|
-
emotions:
|
|
17
|
+
emotions: List[str]
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class GenderEnum(str, Enum):
|
|
@@ -54,7 +56,7 @@ class ModelInfo(BaseModel):
|
|
|
54
56
|
"""Model information with supported emotions"""
|
|
55
57
|
|
|
56
58
|
version: TTSModel
|
|
57
|
-
emotions:
|
|
59
|
+
emotions: List[str]
|
|
58
60
|
|
|
59
61
|
|
|
60
62
|
class VoiceV2Response(BaseModel):
|
|
@@ -62,10 +64,10 @@ class VoiceV2Response(BaseModel):
|
|
|
62
64
|
|
|
63
65
|
voice_id: str
|
|
64
66
|
voice_name: str
|
|
65
|
-
models:
|
|
67
|
+
models: List[ModelInfo]
|
|
66
68
|
gender: Optional[GenderEnum] = None
|
|
67
69
|
age: Optional[AgeEnum] = None
|
|
68
|
-
use_cases: Optional[
|
|
70
|
+
use_cases: Optional[List[str]] = None
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
class RecommendedVoice(BaseModel):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: typecast-python
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
4
4
|
Summary: Official Typecast Python SDK - Convert text to lifelike speech using AI-powered voices
|
|
5
5
|
Project-URL: Homepage, https://typecast.ai
|
|
6
6
|
Project-URL: Documentation, https://typecast.ai/docs/overview
|
|
@@ -217,26 +217,30 @@ Classifier: Intended Audience :: Developers
|
|
|
217
217
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
218
218
|
Classifier: Operating System :: OS Independent
|
|
219
219
|
Classifier: Programming Language :: Python :: 3
|
|
220
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
221
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
222
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
220
223
|
Classifier: Programming Language :: Python :: 3.11
|
|
221
224
|
Classifier: Programming Language :: Python :: 3.12
|
|
222
225
|
Classifier: Programming Language :: Python :: 3.13
|
|
226
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
223
227
|
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
224
228
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
225
|
-
Requires-Python:
|
|
226
|
-
Requires-Dist: aiohttp>=3.
|
|
229
|
+
Requires-Python: <3.15,>=3.8
|
|
230
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
227
231
|
Requires-Dist: pydantic>=2.0.0
|
|
228
232
|
Requires-Dist: requests>=2.28.0
|
|
229
233
|
Requires-Dist: typing-extensions>=4.0.0
|
|
230
234
|
Provides-Extra: dev
|
|
231
235
|
Requires-Dist: aioresponses>=0.7.6; extra == 'dev'
|
|
232
|
-
Requires-Dist: black
|
|
233
|
-
Requires-Dist: flake8
|
|
236
|
+
Requires-Dist: black<25.0.0,>=23.0.0; extra == 'dev'
|
|
237
|
+
Requires-Dist: flake8<6.0.0,>=5.0.0; extra == 'dev'
|
|
234
238
|
Requires-Dist: isort>=5.0.0; extra == 'dev'
|
|
235
|
-
Requires-Dist: mypy
|
|
236
|
-
Requires-Dist: pytest-asyncio
|
|
237
|
-
Requires-Dist: pytest-cov
|
|
239
|
+
Requires-Dist: mypy<1.11.0,>=1.0.0; extra == 'dev'
|
|
240
|
+
Requires-Dist: pytest-asyncio<1.0.0,>=0.21.0; extra == 'dev'
|
|
241
|
+
Requires-Dist: pytest-cov<6.0.0,>=5.0.0; extra == 'dev'
|
|
238
242
|
Requires-Dist: pytest-mock>=3.14.0; extra == 'dev'
|
|
239
|
-
Requires-Dist: pytest
|
|
243
|
+
Requires-Dist: pytest<9.0.0,>=7.0.0; extra == 'dev'
|
|
240
244
|
Description-Content-Type: text/markdown
|
|
241
245
|
|
|
242
246
|
<div align="center">
|
|
@@ -250,7 +254,7 @@ Convert text to lifelike speech using AI-powered voices
|
|
|
250
254
|
[](https://pypi.org/project/typecast-python/)
|
|
251
255
|
[](../docs/coverage-policy.md)
|
|
252
256
|
[](LICENSE)
|
|
253
|
-
[](https://www.python.org/)
|
|
254
258
|
|
|
255
259
|
[Documentation](https://typecast.ai/docs) | [API Reference](https://typecast.ai/docs/api-reference) | [Get API Key](https://typecast.ai/developers/api/api-key)
|
|
256
260
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
typecast/__init__.py,sha256=L6m0Z1jn1UgGjPp9AFiTwhHk9DVV_B4WrLfQDEfbcZI,1093
|
|
2
|
+
typecast/_user_agent.py,sha256=R_0eSKpuP9jLp_wDJcJGFvFtUh9BZwEgsT1buVeHRAA,1786
|
|
3
|
+
typecast/_voice_clone.py,sha256=TN2tbB3b5lC5uFCBnbERhz37bNJlbv6VZ-vj70EfTs4,3464
|
|
4
|
+
typecast/async_client.py,sha256=Gidl-gj0zGMzZCPzmMRcr2GiYFi0cBmZOwrLhSVRL_Y,21700
|
|
5
|
+
typecast/client.py,sha256=Ac6hcginhJheh6CcstzaMtyXzRbnSfUerI8rt6l_f58,21695
|
|
6
|
+
typecast/composer.py,sha256=pkRSVIv99uuAwPyOXw7KSW7NAkqvAUK4hCS5pmBb7bA,7313
|
|
7
|
+
typecast/conf.py,sha256=yfOHYZDvIshWWMriN5wE0GFPR8AX3zv4Rg2655OvA9Q,724
|
|
8
|
+
typecast/exceptions.py,sha256=Y0ZzYebe8zOSOSAHbXfKR0G_RJgdmZXxi15Z7ZxPLIk,1568
|
|
9
|
+
typecast/utils.py,sha256=XuNuX7gW8_CGKqZ-cv_tKlPVMPBluAYJBw2clwmjIMI,708
|
|
10
|
+
typecast/models/__init__.py,sha256=OmaFdGpH6gK7EJyNgvbwqZHXVxjnWKJzynn7D3pfULo,1249
|
|
11
|
+
typecast/models/error.py,sha256=XomIjx7jvlCjItqzJuCAT4mXC9jwTjxR8lLDUk6P8KA,152
|
|
12
|
+
typecast/models/subscription.py,sha256=EIaAAo3cCRw8LYT_O6D9AVwxqIHrWCijzl4UTx7FZB8,894
|
|
13
|
+
typecast/models/tts.py,sha256=xiO1e936vFr7vZqUErTEhexydoaMem6BcY_x1A1zFow,16495
|
|
14
|
+
typecast/models/voices.py,sha256=3UeBLwAlaNbQQUrt7FO18zqczLoP7jmi2x68yaUtllU,2687
|
|
15
|
+
typecast_python-0.3.10.dist-info/METADATA,sha256=z8W8o3SeRtx4C9PWgEvRCJ3fOcfoVTy2Utp0mqUvkOs,25786
|
|
16
|
+
typecast_python-0.3.10.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
17
|
+
typecast_python-0.3.10.dist-info/licenses/LICENSE,sha256=HvtJ-S89uUkuYmt-OvVk4MRxmzwtbn84__qJtSrGU2Q,11348
|
|
18
|
+
typecast_python-0.3.10.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
typecast/__init__.py,sha256=L6m0Z1jn1UgGjPp9AFiTwhHk9DVV_B4WrLfQDEfbcZI,1093
|
|
2
|
-
typecast/_user_agent.py,sha256=R_0eSKpuP9jLp_wDJcJGFvFtUh9BZwEgsT1buVeHRAA,1786
|
|
3
|
-
typecast/_voice_clone.py,sha256=TN2tbB3b5lC5uFCBnbERhz37bNJlbv6VZ-vj70EfTs4,3464
|
|
4
|
-
typecast/async_client.py,sha256=H3hCoGb6h0UyrnYUlQ0lhnpaCV-hxnZtsQKYlqaGPSk,21592
|
|
5
|
-
typecast/client.py,sha256=VPZVRnB9_T4VkSlrHpKLRahhEaxIF05XUAk-skqYKz8,20850
|
|
6
|
-
typecast/composer.py,sha256=r1kpRGlSJ1s4C1PkE7yIpGwnKtxYfIdFSLWaf8v1RAQ,9422
|
|
7
|
-
typecast/conf.py,sha256=yfOHYZDvIshWWMriN5wE0GFPR8AX3zv4Rg2655OvA9Q,724
|
|
8
|
-
typecast/exceptions.py,sha256=Y0ZzYebe8zOSOSAHbXfKR0G_RJgdmZXxi15Z7ZxPLIk,1568
|
|
9
|
-
typecast/utils.py,sha256=XuNuX7gW8_CGKqZ-cv_tKlPVMPBluAYJBw2clwmjIMI,708
|
|
10
|
-
typecast/models/__init__.py,sha256=OmaFdGpH6gK7EJyNgvbwqZHXVxjnWKJzynn7D3pfULo,1249
|
|
11
|
-
typecast/models/error.py,sha256=XomIjx7jvlCjItqzJuCAT4mXC9jwTjxR8lLDUk6P8KA,152
|
|
12
|
-
typecast/models/subscription.py,sha256=EIaAAo3cCRw8LYT_O6D9AVwxqIHrWCijzl4UTx7FZB8,894
|
|
13
|
-
typecast/models/tts.py,sha256=W2Bp9M-xPJPODlk89P9CnLA2fwb__4SR4yoMkG_O8kA,16453
|
|
14
|
-
typecast/models/voices.py,sha256=3yJD78QbZe3pTZv61GnB8up8qlIHKd1iSe5Bow-4ocU,2645
|
|
15
|
-
typecast_python-0.3.8.dist-info/METADATA,sha256=5Gbl-QxbRCGnqUwn_8Yr2xssRMZD_3GvZghgWsUxByg,25530
|
|
16
|
-
typecast_python-0.3.8.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
17
|
-
typecast_python-0.3.8.dist-info/licenses/LICENSE,sha256=HvtJ-S89uUkuYmt-OvVk4MRxmzwtbn84__qJtSrGU2Q,11348
|
|
18
|
-
typecast_python-0.3.8.dist-info/RECORD,,
|
|
File without changes
|