everypixel-cli 0.3.0__tar.gz → 0.4.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.
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/CHANGELOG.md +5 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/PKG-INFO +26 -4
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/README.md +25 -3
- everypixel_cli-0.4.0/src/everypixel_cli/__init__.py +1 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/application/services.py +176 -61
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/cli.py +86 -18
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/mcp_server.py +65 -19
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/resources/openapi.json +370 -40
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/schemas.py +285 -1
- everypixel_cli-0.3.0/src/everypixel_cli/__init__.py +0 -1
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/.gitignore +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/LICENSE +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/pyproject.toml +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/__main__.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/application/__init__.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/application/chat.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/application/models.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/application/serialization.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/client.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/config.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/errors.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/files.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/openapi.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/output.py +0 -0
- {everypixel_cli-0.3.0 → everypixel_cli-0.4.0}/src/everypixel_cli/resources/__init__.py +0 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.0] - 2026-10-07
|
|
4
|
+
|
|
5
|
+
- Add ElevenLabs speech synthesis and voice design.
|
|
6
|
+
- Add saved voice creation, listing, deletion, and Qwen cloning by voice ID.
|
|
7
|
+
|
|
3
8
|
## [0.3.0] - 2026-09-18
|
|
4
9
|
|
|
5
10
|
- Add GPT Image 2.5 Sunburst and quality selection for GPT Image models.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: everypixel-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Official command line interface for Everypixel API
|
|
5
5
|
Project-URL: Homepage, https://labs.everypixel.com
|
|
6
6
|
Project-URL: Repository, https://github.com/everypixel/everypixel-cli
|
|
@@ -263,9 +263,12 @@ They support 4K output. The default `seedvr2` supports up to 1440p, with a
|
|
|
263
263
|
| `everypixel lipsync video` | Synchronize a video with an audio track |
|
|
264
264
|
| `everypixel lipsync image` | Create a lipsync video from a still image and audio |
|
|
265
265
|
| `everypixel audio transcribe` | Transcribe speech from an audio file |
|
|
266
|
-
| `everypixel audio tts-create` | Create speech with a
|
|
267
|
-
| `everypixel audio tts-clone` | Create speech from
|
|
268
|
-
| `everypixel audio tts-
|
|
266
|
+
| `everypixel audio tts-create` | Create speech with a Qwen preset or saved ElevenLabs voice |
|
|
267
|
+
| `everypixel audio tts-clone` | Create Qwen speech from an audio sample or saved voice |
|
|
268
|
+
| `everypixel audio tts-design` | Design voice previews from a description |
|
|
269
|
+
| `everypixel audio tts-voice` | Save audio samples or a design preview as a voice |
|
|
270
|
+
| `everypixel audio tts-voices` | List presets and saved voices |
|
|
271
|
+
| `everypixel audio tts-delete` | Delete an owned saved voice |
|
|
269
272
|
|
|
270
273
|
Lipsync supports 720p; the API checks source media dimensions and duration.
|
|
271
274
|
|
|
@@ -290,6 +293,25 @@ everypixel audio tts-create \
|
|
|
290
293
|
--download ./outputs
|
|
291
294
|
```
|
|
292
295
|
|
|
296
|
+
`tts-create` lets the API choose the model when `--model` is omitted.
|
|
297
|
+
`tts-clone` and `tts-design` default to `--model qwen3`.
|
|
298
|
+
`--speaker`, `--style`, `--language`, and `--seed` are Qwen controls; `--character` applies only to Qwen voice design.
|
|
299
|
+
Qwen text is limited to 200 characters. ElevenLabs synthesis accepts up to
|
|
300
|
+
2048 characters and requires `--voice-id`. Supported synthesis models are
|
|
301
|
+
`eleven_v4`, `eleven_v4_turbo`, `eleven_v3`, `eleven_v3_conversational`,
|
|
302
|
+
`eleven_multilingual_v2`, and `eleven_flash_v2_5`. ElevenLabs design uses
|
|
303
|
+
`eleven_multilingual_ttv_v2` or `eleven_ttv_v3`, with 100–1000 characters of
|
|
304
|
+
text and a 20–1000 character `--prompt`.
|
|
305
|
+
|
|
306
|
+
Save a returned preview with `tts-voice --name "Narrator" --preview-id UUID`, or save local
|
|
307
|
+
samples with `tts-voice --name "My voice" --provider elevenlabs --audio ./sample.wav`.
|
|
308
|
+
`--audio` is repeatable for ElevenLabs; Qwen (`--provider labs`, the default)
|
|
309
|
+
requires one sample. Saving returns a voice card immediately. Use its ID with
|
|
310
|
+
`tts-create --model eleven_v3 --voice-id UUID --text "Hello"` or
|
|
311
|
+
`tts-clone --voice-id UUID --text "Hello"`. List voices with
|
|
312
|
+
`tts-voices --provider elevenlabs --offset 0 --limit 50`, and delete an owned
|
|
313
|
+
voice with `tts-delete --voice-id UUID`.
|
|
314
|
+
|
|
293
315
|
### Chat
|
|
294
316
|
|
|
295
317
|
```bash
|
|
@@ -229,9 +229,12 @@ They support 4K output. The default `seedvr2` supports up to 1440p, with a
|
|
|
229
229
|
| `everypixel lipsync video` | Synchronize a video with an audio track |
|
|
230
230
|
| `everypixel lipsync image` | Create a lipsync video from a still image and audio |
|
|
231
231
|
| `everypixel audio transcribe` | Transcribe speech from an audio file |
|
|
232
|
-
| `everypixel audio tts-create` | Create speech with a
|
|
233
|
-
| `everypixel audio tts-clone` | Create speech from
|
|
234
|
-
| `everypixel audio tts-
|
|
232
|
+
| `everypixel audio tts-create` | Create speech with a Qwen preset or saved ElevenLabs voice |
|
|
233
|
+
| `everypixel audio tts-clone` | Create Qwen speech from an audio sample or saved voice |
|
|
234
|
+
| `everypixel audio tts-design` | Design voice previews from a description |
|
|
235
|
+
| `everypixel audio tts-voice` | Save audio samples or a design preview as a voice |
|
|
236
|
+
| `everypixel audio tts-voices` | List presets and saved voices |
|
|
237
|
+
| `everypixel audio tts-delete` | Delete an owned saved voice |
|
|
235
238
|
|
|
236
239
|
Lipsync supports 720p; the API checks source media dimensions and duration.
|
|
237
240
|
|
|
@@ -256,6 +259,25 @@ everypixel audio tts-create \
|
|
|
256
259
|
--download ./outputs
|
|
257
260
|
```
|
|
258
261
|
|
|
262
|
+
`tts-create` lets the API choose the model when `--model` is omitted.
|
|
263
|
+
`tts-clone` and `tts-design` default to `--model qwen3`.
|
|
264
|
+
`--speaker`, `--style`, `--language`, and `--seed` are Qwen controls; `--character` applies only to Qwen voice design.
|
|
265
|
+
Qwen text is limited to 200 characters. ElevenLabs synthesis accepts up to
|
|
266
|
+
2048 characters and requires `--voice-id`. Supported synthesis models are
|
|
267
|
+
`eleven_v4`, `eleven_v4_turbo`, `eleven_v3`, `eleven_v3_conversational`,
|
|
268
|
+
`eleven_multilingual_v2`, and `eleven_flash_v2_5`. ElevenLabs design uses
|
|
269
|
+
`eleven_multilingual_ttv_v2` or `eleven_ttv_v3`, with 100–1000 characters of
|
|
270
|
+
text and a 20–1000 character `--prompt`.
|
|
271
|
+
|
|
272
|
+
Save a returned preview with `tts-voice --name "Narrator" --preview-id UUID`, or save local
|
|
273
|
+
samples with `tts-voice --name "My voice" --provider elevenlabs --audio ./sample.wav`.
|
|
274
|
+
`--audio` is repeatable for ElevenLabs; Qwen (`--provider labs`, the default)
|
|
275
|
+
requires one sample. Saving returns a voice card immediately. Use its ID with
|
|
276
|
+
`tts-create --model eleven_v3 --voice-id UUID --text "Hello"` or
|
|
277
|
+
`tts-clone --voice-id UUID --text "Hello"`. List voices with
|
|
278
|
+
`tts-voices --provider elevenlabs --offset 0 --limit 50`, and delete an owned
|
|
279
|
+
voice with `tts-delete --voice-id UUID`.
|
|
280
|
+
|
|
259
281
|
### Chat
|
|
260
282
|
|
|
261
283
|
```bash
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.0"
|
|
@@ -34,6 +34,13 @@ from ..openapi import (
|
|
|
34
34
|
)
|
|
35
35
|
from ..schemas import (
|
|
36
36
|
ChatRequest,
|
|
37
|
+
TTS_CREATE_PAYLOADS,
|
|
38
|
+
TTS_DESIGN_PAYLOADS,
|
|
39
|
+
TTSClonePayload,
|
|
40
|
+
TTSDefaultCreatePayload,
|
|
41
|
+
TTSVoiceSavePayload,
|
|
42
|
+
TTSVoicesPayload,
|
|
43
|
+
TTSVoiceDeletePayload,
|
|
37
44
|
GPT_IMAGE_MODEL_QUALITIES,
|
|
38
45
|
ImageEditPayload,
|
|
39
46
|
ImageGeneratePayload,
|
|
@@ -240,11 +247,14 @@ class OperationService:
|
|
|
240
247
|
def execute(self, request: OperationRequest) -> OperationResult:
|
|
241
248
|
method = request.method.upper()
|
|
242
249
|
payload = dict(request.payload)
|
|
250
|
+
use_query = method == "GET" or (
|
|
251
|
+
method == "DELETE" and request.endpoint == "/v1/tts_voice"
|
|
252
|
+
)
|
|
243
253
|
response = self.client.request(
|
|
244
254
|
method,
|
|
245
255
|
request.endpoint,
|
|
246
|
-
json=
|
|
247
|
-
params=payload if
|
|
256
|
+
json=None if use_query else payload,
|
|
257
|
+
params=payload if use_query else None,
|
|
248
258
|
)
|
|
249
259
|
if not isinstance(response, Mapping) or "task_id" not in response:
|
|
250
260
|
return OperationResult(value=response)
|
|
@@ -753,33 +763,64 @@ def read_text_input(text: str | None, text_file: Path | None) -> str:
|
|
|
753
763
|
return text
|
|
754
764
|
|
|
755
765
|
|
|
756
|
-
def
|
|
757
|
-
|
|
766
|
+
def validate_tts_payload(
|
|
767
|
+
path: str, values: dict[str, Any], *, generic: bool = False
|
|
768
|
+
) -> BaseModel:
|
|
769
|
+
"""Select a provider schema without dropping unsupported controls."""
|
|
770
|
+
if generic:
|
|
771
|
+
schemas: list[type[BaseModel]] = [
|
|
772
|
+
*TTS_CREATE_PAYLOADS.values(),
|
|
773
|
+
*TTS_DESIGN_PAYLOADS.values(),
|
|
774
|
+
TTSClonePayload,
|
|
775
|
+
TTSDefaultCreatePayload,
|
|
776
|
+
]
|
|
777
|
+
known_fields = {field for schema in schemas for field in schema.model_fields}
|
|
778
|
+
values = {key: value for key, value in values.items() if key in known_fields}
|
|
779
|
+
if path == "/v1/tts_create" and "model" not in values:
|
|
780
|
+
return TTSDefaultCreatePayload.model_validate(values)
|
|
781
|
+
registries = {
|
|
782
|
+
"/v1/tts_create": TTS_CREATE_PAYLOADS,
|
|
783
|
+
"/v1/tts_design": TTS_DESIGN_PAYLOADS,
|
|
784
|
+
}
|
|
785
|
+
if path in registries:
|
|
786
|
+
model = values.get("model", "qwen3")
|
|
787
|
+
schema = registries[path].get(model) if isinstance(model, str) else None
|
|
788
|
+
if schema is None:
|
|
789
|
+
raise ValidationCLIError("Unsupported TTS model")
|
|
790
|
+
return schema.model_validate(values)
|
|
791
|
+
return TTSClonePayload.model_validate(values)
|
|
792
|
+
|
|
758
793
|
|
|
794
|
+
def _build_tts_payload(path: str, values: dict[str, Any]) -> dict[str, Any]:
|
|
759
795
|
text = values.pop("text")
|
|
760
796
|
text_file = values.pop("text_file")
|
|
761
|
-
|
|
797
|
+
values = {key: value for key, value in values.items() if value is not None}
|
|
798
|
+
values["text"] = read_text_input(text, text_file)
|
|
799
|
+
return validate_tts_payload(path, values).model_dump(mode="json", exclude_none=True)
|
|
762
800
|
|
|
763
801
|
|
|
764
|
-
def
|
|
765
|
-
""
|
|
802
|
+
def build_tts_create_payload(**values: Any) -> dict[str, Any]:
|
|
803
|
+
return _build_tts_payload("/v1/tts_create", values)
|
|
766
804
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
return
|
|
805
|
+
|
|
806
|
+
def build_tts_design_payload(**values: Any) -> dict[str, Any]:
|
|
807
|
+
return _build_tts_payload("/v1/tts_design", values)
|
|
770
808
|
|
|
771
809
|
|
|
772
810
|
def build_tts_clone_payload(**values: Any) -> dict[str, Any]:
|
|
773
|
-
|
|
811
|
+
audio = values.pop("audio")
|
|
812
|
+
if audio is not None:
|
|
813
|
+
values["audio_url"] = media_value(audio)
|
|
814
|
+
return _build_tts_payload("/v1/tts_clone", values)
|
|
815
|
+
|
|
774
816
|
|
|
817
|
+
def build_tts_voice_payload(**values: Any) -> dict[str, Any]:
|
|
775
818
|
audio = values.pop("audio")
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
return
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
**values,
|
|
782
|
-
}
|
|
819
|
+
if audio:
|
|
820
|
+
values["audio_urls"] = [media_value(sample) for sample in audio]
|
|
821
|
+
return TTSVoiceSavePayload.model_validate(
|
|
822
|
+
{key: value for key, value in values.items() if value is not None}
|
|
823
|
+
).model_dump(mode="json", exclude_none=True)
|
|
783
824
|
|
|
784
825
|
|
|
785
826
|
@dataclass
|
|
@@ -1147,25 +1188,28 @@ class ApplicationServices:
|
|
|
1147
1188
|
*,
|
|
1148
1189
|
text: str | None,
|
|
1149
1190
|
text_file: Path | None,
|
|
1150
|
-
speaker: str,
|
|
1151
|
-
style: str,
|
|
1152
|
-
language: str,
|
|
1153
|
-
prompt: str,
|
|
1154
|
-
seed: int,
|
|
1155
1191
|
execution: ExecutionOptions,
|
|
1192
|
+
model: str | None = None,
|
|
1193
|
+
voice_id: str | None = None,
|
|
1194
|
+
speaker: str | None = None,
|
|
1195
|
+
style: str | None = None,
|
|
1196
|
+
language: str | None = None,
|
|
1197
|
+
prompt: str | None = None,
|
|
1198
|
+
seed: int | None = None,
|
|
1156
1199
|
) -> OperationResult:
|
|
1157
|
-
payload = build_tts_create_payload(
|
|
1158
|
-
text=text,
|
|
1159
|
-
text_file=text_file,
|
|
1160
|
-
speaker=speaker,
|
|
1161
|
-
style=style,
|
|
1162
|
-
language=language,
|
|
1163
|
-
prompt=prompt,
|
|
1164
|
-
seed=seed,
|
|
1165
|
-
)
|
|
1166
1200
|
return self._execute_async(
|
|
1167
1201
|
endpoint="/v1/tts_create",
|
|
1168
|
-
payload=
|
|
1202
|
+
payload=build_tts_create_payload(
|
|
1203
|
+
text=text,
|
|
1204
|
+
text_file=text_file,
|
|
1205
|
+
model=model,
|
|
1206
|
+
voice_id=voice_id,
|
|
1207
|
+
speaker=speaker,
|
|
1208
|
+
style=style,
|
|
1209
|
+
language=language,
|
|
1210
|
+
prompt=prompt,
|
|
1211
|
+
seed=seed,
|
|
1212
|
+
),
|
|
1169
1213
|
execution=execution,
|
|
1170
1214
|
fallback_extension=".mp3",
|
|
1171
1215
|
)
|
|
@@ -1173,55 +1217,113 @@ class ApplicationServices:
|
|
|
1173
1217
|
def execute_tts_clone(
|
|
1174
1218
|
self,
|
|
1175
1219
|
*,
|
|
1176
|
-
audio: str,
|
|
1177
1220
|
text: str | None,
|
|
1178
1221
|
text_file: Path | None,
|
|
1179
|
-
language: str,
|
|
1180
|
-
seed: int,
|
|
1181
1222
|
execution: ExecutionOptions,
|
|
1223
|
+
audio: str | None = None,
|
|
1224
|
+
voice_id: str | None = None,
|
|
1225
|
+
model: str = "qwen3",
|
|
1226
|
+
language: str | None = None,
|
|
1227
|
+
seed: int | None = None,
|
|
1182
1228
|
) -> OperationResult:
|
|
1183
|
-
payload = build_tts_clone_payload(
|
|
1184
|
-
audio=audio,
|
|
1185
|
-
text=text,
|
|
1186
|
-
text_file=text_file,
|
|
1187
|
-
language=language,
|
|
1188
|
-
seed=seed,
|
|
1189
|
-
)
|
|
1190
1229
|
return self._execute_async(
|
|
1191
1230
|
endpoint="/v1/tts_clone",
|
|
1192
|
-
payload=
|
|
1231
|
+
payload=build_tts_clone_payload(
|
|
1232
|
+
audio=audio,
|
|
1233
|
+
text=text,
|
|
1234
|
+
text_file=text_file,
|
|
1235
|
+
voice_id=voice_id,
|
|
1236
|
+
model=model,
|
|
1237
|
+
language=language,
|
|
1238
|
+
seed=seed,
|
|
1239
|
+
),
|
|
1193
1240
|
execution=execution,
|
|
1194
1241
|
fallback_extension=".mp3",
|
|
1195
1242
|
)
|
|
1196
1243
|
|
|
1197
|
-
def
|
|
1244
|
+
def execute_tts_design(
|
|
1198
1245
|
self,
|
|
1199
1246
|
*,
|
|
1200
1247
|
text: str | None,
|
|
1201
1248
|
text_file: Path | None,
|
|
1202
|
-
character: str,
|
|
1203
|
-
style: str,
|
|
1204
|
-
language: str,
|
|
1205
|
-
prompt: str,
|
|
1206
|
-
seed: int,
|
|
1207
1249
|
execution: ExecutionOptions,
|
|
1250
|
+
model: str = "qwen3",
|
|
1251
|
+
character: str | None = None,
|
|
1252
|
+
style: str | None = None,
|
|
1253
|
+
language: str | None = None,
|
|
1254
|
+
prompt: str | None = None,
|
|
1255
|
+
seed: int | None = None,
|
|
1208
1256
|
) -> OperationResult:
|
|
1209
|
-
payload = build_tts_voice_payload(
|
|
1210
|
-
text=text,
|
|
1211
|
-
text_file=text_file,
|
|
1212
|
-
character=character,
|
|
1213
|
-
style=style,
|
|
1214
|
-
language=language,
|
|
1215
|
-
prompt=prompt,
|
|
1216
|
-
seed=seed,
|
|
1217
|
-
)
|
|
1218
1257
|
return self._execute_async(
|
|
1219
|
-
endpoint="/v1/
|
|
1220
|
-
payload=
|
|
1258
|
+
endpoint="/v1/tts_design",
|
|
1259
|
+
payload=build_tts_design_payload(
|
|
1260
|
+
text=text,
|
|
1261
|
+
text_file=text_file,
|
|
1262
|
+
model=model,
|
|
1263
|
+
character=character,
|
|
1264
|
+
style=style,
|
|
1265
|
+
language=language,
|
|
1266
|
+
prompt=prompt,
|
|
1267
|
+
seed=seed,
|
|
1268
|
+
),
|
|
1221
1269
|
execution=execution,
|
|
1222
1270
|
fallback_extension=".mp3",
|
|
1223
1271
|
)
|
|
1224
1272
|
|
|
1273
|
+
def execute_tts_voice(
|
|
1274
|
+
self,
|
|
1275
|
+
*,
|
|
1276
|
+
name: str,
|
|
1277
|
+
audio: list[str],
|
|
1278
|
+
provider: str | None = None,
|
|
1279
|
+
preview_id: str | None = None,
|
|
1280
|
+
description: str = "",
|
|
1281
|
+
) -> OperationResult:
|
|
1282
|
+
return self._operations.execute(
|
|
1283
|
+
OperationRequest(
|
|
1284
|
+
endpoint="/v1/tts_voice",
|
|
1285
|
+
method="POST",
|
|
1286
|
+
payload=build_tts_voice_payload(
|
|
1287
|
+
name=name,
|
|
1288
|
+
audio=audio,
|
|
1289
|
+
provider=provider,
|
|
1290
|
+
preview_id=preview_id,
|
|
1291
|
+
description=description,
|
|
1292
|
+
),
|
|
1293
|
+
execution=ExecutionOptions(),
|
|
1294
|
+
)
|
|
1295
|
+
)
|
|
1296
|
+
|
|
1297
|
+
def list_tts_voices(
|
|
1298
|
+
self,
|
|
1299
|
+
*,
|
|
1300
|
+
provider: str = "labs",
|
|
1301
|
+
offset: int = 0,
|
|
1302
|
+
limit: int = 50,
|
|
1303
|
+
) -> OperationResult:
|
|
1304
|
+
return self._operations.execute(
|
|
1305
|
+
OperationRequest(
|
|
1306
|
+
endpoint="/v1/tts_voices",
|
|
1307
|
+
method="GET",
|
|
1308
|
+
payload=TTSVoicesPayload.model_validate(
|
|
1309
|
+
{"provider": provider, "offset": offset, "limit": limit}
|
|
1310
|
+
).model_dump(),
|
|
1311
|
+
execution=ExecutionOptions(),
|
|
1312
|
+
)
|
|
1313
|
+
)
|
|
1314
|
+
|
|
1315
|
+
def delete_tts_voice(self, *, voice_id: str) -> OperationResult:
|
|
1316
|
+
return self._operations.execute(
|
|
1317
|
+
OperationRequest(
|
|
1318
|
+
endpoint="/v1/tts_voice",
|
|
1319
|
+
method="DELETE",
|
|
1320
|
+
payload=TTSVoiceDeletePayload.model_validate(
|
|
1321
|
+
{"voice_id": voice_id}
|
|
1322
|
+
).model_dump(mode="json"),
|
|
1323
|
+
execution=ExecutionOptions(),
|
|
1324
|
+
)
|
|
1325
|
+
)
|
|
1326
|
+
|
|
1225
1327
|
def execute_chat(
|
|
1226
1328
|
self,
|
|
1227
1329
|
*,
|
|
@@ -1340,6 +1442,19 @@ class ApplicationServices:
|
|
|
1340
1442
|
_VIDEO_EDIT_ADAPTER.validate_python(payload, extra="ignore")
|
|
1341
1443
|
if path == "/v1/chat/completions":
|
|
1342
1444
|
ChatRequest.model_validate(payload, extra="ignore")
|
|
1445
|
+
if resolved_method == "POST" and path in {
|
|
1446
|
+
"/v1/tts_create",
|
|
1447
|
+
"/v1/tts_clone",
|
|
1448
|
+
"/v1/tts_design",
|
|
1449
|
+
}:
|
|
1450
|
+
validate_tts_payload(path, payload, generic=True)
|
|
1451
|
+
if path == "/v1/tts_voice":
|
|
1452
|
+
if resolved_method == "POST":
|
|
1453
|
+
TTSVoiceSavePayload.model_validate(payload)
|
|
1454
|
+
elif resolved_method == "DELETE":
|
|
1455
|
+
TTSVoiceDeletePayload.model_validate(payload)
|
|
1456
|
+
if path == "/v1/tts_voices" and resolved_method == "GET":
|
|
1457
|
+
TTSVoicesPayload.model_validate(payload)
|
|
1343
1458
|
validate_payload_against_operation(operation, payload)
|
|
1344
1459
|
if dry_run:
|
|
1345
1460
|
return OperationResult(
|
|
@@ -1285,17 +1285,19 @@ def tts_create(
|
|
|
1285
1285
|
ctx: typer.Context,
|
|
1286
1286
|
text: Annotated[Optional[str], typer.Option("--text")] = None,
|
|
1287
1287
|
text_file: Annotated[Optional[Path], typer.Option("--text-file")] = None,
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1288
|
+
model: Optional[str] = None,
|
|
1289
|
+
voice_id: Optional[str] = None,
|
|
1290
|
+
speaker: Optional[str] = None,
|
|
1291
|
+
style: Optional[str] = None,
|
|
1292
|
+
language: Optional[str] = None,
|
|
1293
|
+
prompt: Optional[str] = None,
|
|
1294
|
+
seed: Optional[int] = None,
|
|
1293
1295
|
wait_option: WaitOption = None,
|
|
1294
1296
|
download: DownloadOption = None,
|
|
1295
1297
|
output_json: OutputJsonOption = False,
|
|
1296
1298
|
jq_expr: JqOption = None,
|
|
1297
1299
|
) -> None:
|
|
1298
|
-
"""Create speech
|
|
1300
|
+
"""Create speech using Qwen presets or a saved ElevenLabs voice."""
|
|
1299
1301
|
|
|
1300
1302
|
runtime = apply_common_options(
|
|
1301
1303
|
ctx,
|
|
@@ -1309,6 +1311,8 @@ def tts_create(
|
|
|
1309
1311
|
lambda: runtime.services().execute_tts_create(
|
|
1310
1312
|
text=text,
|
|
1311
1313
|
text_file=text_file,
|
|
1314
|
+
model=model,
|
|
1315
|
+
voice_id=voice_id,
|
|
1312
1316
|
speaker=speaker,
|
|
1313
1317
|
style=style,
|
|
1314
1318
|
language=language,
|
|
@@ -1322,11 +1326,13 @@ def tts_create(
|
|
|
1322
1326
|
@audio_app.command("tts-clone")
|
|
1323
1327
|
def tts_clone(
|
|
1324
1328
|
ctx: typer.Context,
|
|
1325
|
-
audio: Annotated[str, typer.Option("--audio")],
|
|
1329
|
+
audio: Annotated[Optional[str], typer.Option("--audio")] = None,
|
|
1330
|
+
voice_id: Optional[str] = None,
|
|
1326
1331
|
text: Annotated[Optional[str], typer.Option("--text")] = None,
|
|
1327
1332
|
text_file: Annotated[Optional[Path], typer.Option("--text-file")] = None,
|
|
1328
|
-
|
|
1329
|
-
|
|
1333
|
+
model: str = "qwen3",
|
|
1334
|
+
language: Optional[str] = None,
|
|
1335
|
+
seed: Optional[int] = None,
|
|
1330
1336
|
wait_option: WaitOption = None,
|
|
1331
1337
|
download: DownloadOption = None,
|
|
1332
1338
|
output_json: OutputJsonOption = False,
|
|
@@ -1345,8 +1351,10 @@ def tts_clone(
|
|
|
1345
1351
|
ctx,
|
|
1346
1352
|
lambda: runtime.services().execute_tts_clone(
|
|
1347
1353
|
audio=audio,
|
|
1354
|
+
voice_id=voice_id,
|
|
1348
1355
|
text=text,
|
|
1349
1356
|
text_file=text_file,
|
|
1357
|
+
model=model,
|
|
1350
1358
|
language=language,
|
|
1351
1359
|
seed=seed,
|
|
1352
1360
|
execution=runtime.execution_options(),
|
|
@@ -1354,22 +1362,23 @@ def tts_clone(
|
|
|
1354
1362
|
)
|
|
1355
1363
|
|
|
1356
1364
|
|
|
1357
|
-
@audio_app.command("tts-
|
|
1358
|
-
def
|
|
1365
|
+
@audio_app.command("tts-design")
|
|
1366
|
+
def tts_design(
|
|
1359
1367
|
ctx: typer.Context,
|
|
1360
1368
|
text: Annotated[Optional[str], typer.Option("--text")] = None,
|
|
1361
1369
|
text_file: Annotated[Optional[Path], typer.Option("--text-file")] = None,
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1370
|
+
model: str = "qwen3",
|
|
1371
|
+
character: Optional[str] = None,
|
|
1372
|
+
style: Optional[str] = None,
|
|
1373
|
+
language: Optional[str] = None,
|
|
1374
|
+
prompt: Optional[str] = None,
|
|
1375
|
+
seed: Optional[int] = None,
|
|
1367
1376
|
wait_option: WaitOption = None,
|
|
1368
1377
|
download: DownloadOption = None,
|
|
1369
1378
|
output_json: OutputJsonOption = False,
|
|
1370
1379
|
jq_expr: JqOption = None,
|
|
1371
1380
|
) -> None:
|
|
1372
|
-
"""
|
|
1381
|
+
"""Design voice previews from a description."""
|
|
1373
1382
|
|
|
1374
1383
|
runtime = apply_common_options(
|
|
1375
1384
|
ctx,
|
|
@@ -1380,9 +1389,10 @@ def tts_voice(
|
|
|
1380
1389
|
)
|
|
1381
1390
|
run_action(
|
|
1382
1391
|
ctx,
|
|
1383
|
-
lambda: runtime.services().
|
|
1392
|
+
lambda: runtime.services().execute_tts_design(
|
|
1384
1393
|
text=text,
|
|
1385
1394
|
text_file=text_file,
|
|
1395
|
+
model=model,
|
|
1386
1396
|
character=character,
|
|
1387
1397
|
style=style,
|
|
1388
1398
|
language=language,
|
|
@@ -1393,6 +1403,64 @@ def tts_voice(
|
|
|
1393
1403
|
)
|
|
1394
1404
|
|
|
1395
1405
|
|
|
1406
|
+
@audio_app.command("tts-voice")
|
|
1407
|
+
def tts_voice(
|
|
1408
|
+
ctx: typer.Context,
|
|
1409
|
+
name: Annotated[str, typer.Option("--name")],
|
|
1410
|
+
audio: Annotated[list[str], typer.Option("--audio")] = [],
|
|
1411
|
+
provider: Optional[str] = None,
|
|
1412
|
+
preview_id: Optional[str] = None,
|
|
1413
|
+
description: str = "",
|
|
1414
|
+
output_json: OutputJsonOption = False,
|
|
1415
|
+
jq_expr: JqOption = None,
|
|
1416
|
+
) -> None:
|
|
1417
|
+
"""Save a voice from audio samples or a design preview."""
|
|
1418
|
+
runtime = apply_common_options(ctx, output_json=output_json, jq_expr=jq_expr)
|
|
1419
|
+
run_action(
|
|
1420
|
+
ctx,
|
|
1421
|
+
lambda: runtime.services().execute_tts_voice(
|
|
1422
|
+
name=name,
|
|
1423
|
+
audio=audio,
|
|
1424
|
+
provider=provider,
|
|
1425
|
+
preview_id=preview_id,
|
|
1426
|
+
description=description,
|
|
1427
|
+
),
|
|
1428
|
+
)
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
@audio_app.command("tts-voices")
|
|
1432
|
+
def tts_voices(
|
|
1433
|
+
ctx: typer.Context,
|
|
1434
|
+
provider: str = "labs",
|
|
1435
|
+
offset: int = 0,
|
|
1436
|
+
limit: int = 50,
|
|
1437
|
+
output_json: OutputJsonOption = False,
|
|
1438
|
+
jq_expr: JqOption = None,
|
|
1439
|
+
) -> None:
|
|
1440
|
+
"""List presets and saved voices for a provider."""
|
|
1441
|
+
runtime = apply_common_options(ctx, output_json=output_json, jq_expr=jq_expr)
|
|
1442
|
+
run_action(
|
|
1443
|
+
ctx,
|
|
1444
|
+
lambda: runtime.services().list_tts_voices(
|
|
1445
|
+
provider=provider,
|
|
1446
|
+
offset=offset,
|
|
1447
|
+
limit=limit,
|
|
1448
|
+
),
|
|
1449
|
+
)
|
|
1450
|
+
|
|
1451
|
+
|
|
1452
|
+
@audio_app.command("tts-delete")
|
|
1453
|
+
def tts_delete(
|
|
1454
|
+
ctx: typer.Context,
|
|
1455
|
+
voice_id: Annotated[str, typer.Option("--voice-id")],
|
|
1456
|
+
output_json: OutputJsonOption = False,
|
|
1457
|
+
jq_expr: JqOption = None,
|
|
1458
|
+
) -> None:
|
|
1459
|
+
"""Delete an owned saved voice."""
|
|
1460
|
+
runtime = apply_common_options(ctx, output_json=output_json, jq_expr=jq_expr)
|
|
1461
|
+
run_action(ctx, lambda: runtime.services().delete_tts_voice(voice_id=voice_id))
|
|
1462
|
+
|
|
1463
|
+
|
|
1396
1464
|
@app.command("status")
|
|
1397
1465
|
def status(
|
|
1398
1466
|
ctx: typer.Context,
|