everypixel-cli 0.1.0__tar.gz → 0.2.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.1.0 → everypixel_cli-0.2.0}/CHANGELOG.md +7 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/PKG-INFO +49 -1
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/README.md +48 -0
- everypixel_cli-0.2.0/src/everypixel_cli/__init__.py +1 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/application/services.py +129 -28
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/cli.py +58 -10
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/mcp_server.py +33 -5
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/resources/openapi.json +604 -123
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/schemas.py +241 -75
- everypixel_cli-0.1.0/src/everypixel_cli/__init__.py +0 -1
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/.gitignore +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/LICENSE +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/pyproject.toml +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/__main__.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/application/__init__.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/application/models.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/application/serialization.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/client.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/config.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/errors.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/files.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/openapi.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/output.py +0 -0
- {everypixel_cli-0.1.0 → everypixel_cli-0.2.0}/src/everypixel_cli/resources/__init__.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2026-09-09
|
|
4
|
+
|
|
5
|
+
- Add MiniMax H3/Turbo, WAN 3.0, Flux 3, and Seedance 2.5 video models.
|
|
6
|
+
- Add Recraft vector generation, palette controls, and image-to-SVG conversion.
|
|
7
|
+
- Update Grok Imagine models, image-edit input limits, and megapixel controls.
|
|
8
|
+
- Add Topaz 4K video upscaling and 720p lipsync.
|
|
9
|
+
|
|
3
10
|
## [0.1.0] - 2026-08-17
|
|
4
11
|
|
|
5
12
|
Initial public release.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: everypixel-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.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
|
|
@@ -144,6 +144,7 @@ CLI falls back to its user configuration file when a keyring is unavailable;
|
|
|
144
144
|
| --- | --- |
|
|
145
145
|
| `everypixel image generate PROMPT` | Generate an image from a text prompt |
|
|
146
146
|
| `everypixel image edit PROMPT --image FILE` | Edit one or more images |
|
|
147
|
+
| `everypixel image vectorize FILE` | Convert an image to SVG |
|
|
147
148
|
| `everypixel image upscale` | Upscale an image, URL, or existing task result |
|
|
148
149
|
| `everypixel image angles --image FILE` | Change the camera angle of an image |
|
|
149
150
|
| `everypixel image colors --image FILE --reference FILE` | Transfer colors from a reference image |
|
|
@@ -159,6 +160,13 @@ everypixel image edit \
|
|
|
159
160
|
|
|
160
161
|
everypixel image upscale --image ./input.png --download ./outputs
|
|
161
162
|
|
|
163
|
+
everypixel image generate "a mountain icon" \
|
|
164
|
+
--model recraftv4_1_vector \
|
|
165
|
+
--controls '{"colors":[{"rgb":[20,100,180],"weight":1}]}' \
|
|
166
|
+
--download ./outputs
|
|
167
|
+
|
|
168
|
+
everypixel image vectorize ./input.png --download ./outputs
|
|
169
|
+
|
|
162
170
|
everypixel image angles \
|
|
163
171
|
--image ./input.png \
|
|
164
172
|
--azimuth right \
|
|
@@ -167,6 +175,16 @@ everypixel image angles \
|
|
|
167
175
|
--download ./outputs
|
|
168
176
|
```
|
|
169
177
|
|
|
178
|
+
Recraft V4.1 vector models (`recraftv4_1_vector`, `recraftv4_1_pro_vector`)
|
|
179
|
+
produce SVG files and accept optional JSON palette `--controls`. Use `--size`
|
|
180
|
+
to select their aspect ratio. Raster models also accept `--resolution`.
|
|
181
|
+
|
|
182
|
+
`--lora-url` is supported only by `zimage`.
|
|
183
|
+
|
|
184
|
+
Grok image models are `grok-imagine`, `grok-imagine-2`, and
|
|
185
|
+
`grok-imagine-2-low`. The `grok` alias remains supported. `grok_quality` and
|
|
186
|
+
`wan22` have been removed from the API.
|
|
187
|
+
|
|
170
188
|
### Video
|
|
171
189
|
|
|
172
190
|
| Command | Description |
|
|
@@ -197,8 +215,36 @@ everypixel video edit \
|
|
|
197
215
|
"make the scene cinematic" \
|
|
198
216
|
--video ./input.mp4 \
|
|
199
217
|
--download ./outputs
|
|
218
|
+
|
|
219
|
+
everypixel video generate "a slow aerial shot over mountain lakes" \
|
|
220
|
+
--model minimax-h3-turbo --duration 10 --download ./outputs
|
|
221
|
+
|
|
222
|
+
everypixel video edit "continue the scene with a slow camera pan" \
|
|
223
|
+
--model flux3 --video ./input.mp4 --download ./outputs
|
|
224
|
+
|
|
225
|
+
everypixel video upscale --video ./input.mp4 \
|
|
226
|
+
--model topaz-prob-4 --resolution 4k --download ./outputs
|
|
200
227
|
```
|
|
201
228
|
|
|
229
|
+
New video models use these provider defaults and limits:
|
|
230
|
+
|
|
231
|
+
| Model | Duration | Default resolution / aspect ratio | Inputs |
|
|
232
|
+
| --- | --- | --- | --- |
|
|
233
|
+
| `minimax-h3-turbo`, `minimax-h3` | 3–15 s | 768p / 7:4 | Text, first/last frames, or one `--reference-image` |
|
|
234
|
+
| `wan3.0` | 2–30 s | 1080p / adaptive | Text, frames, or up to 10 reference images and 5 reference videos |
|
|
235
|
+
| `flux3` | 5–20 s generation; 5–15 s continuation | 720p / 16:9 | Text, frames, or `video edit --video` for continuation |
|
|
236
|
+
| `seedance2.5` | 4–30 s | 720p / 16:9 | Text or `video edit` references, including audio alone |
|
|
237
|
+
|
|
238
|
+
MiniMax reference images cannot be combined with first/last frames. WAN 3.0
|
|
239
|
+
also separates frame and reference inputs. Seedance 2.5 supports up to 1080p;
|
|
240
|
+
Seedance 2 and Mini retain their 15-second limit. Grok video model names are
|
|
241
|
+
`grok-imagine` and `grok-imagine-1.5` (image required); `grok` and `grok15`
|
|
242
|
+
remain accepted aliases. The CLI's default video model remains `ltx23`.
|
|
243
|
+
|
|
244
|
+
Topaz upscaling models are `topaz-prob-4`, `topaz-slp-2.5`, and `topaz-ast-2`.
|
|
245
|
+
They support 4K output. The default `seedvr2` supports up to 1440p, with a
|
|
246
|
+
20-second source limit at 1440p.
|
|
247
|
+
|
|
202
248
|
### Lipsync and Audio
|
|
203
249
|
|
|
204
250
|
| Command | Description |
|
|
@@ -210,6 +256,8 @@ everypixel video edit \
|
|
|
210
256
|
| `everypixel audio tts-clone` | Create speech from a cloned voice sample |
|
|
211
257
|
| `everypixel audio tts-voice` | Create speech with a character voice |
|
|
212
258
|
|
|
259
|
+
Lipsync supports 720p; the API checks source media dimensions and duration.
|
|
260
|
+
|
|
213
261
|
Examples:
|
|
214
262
|
|
|
215
263
|
```bash
|
|
@@ -110,6 +110,7 @@ CLI falls back to its user configuration file when a keyring is unavailable;
|
|
|
110
110
|
| --- | --- |
|
|
111
111
|
| `everypixel image generate PROMPT` | Generate an image from a text prompt |
|
|
112
112
|
| `everypixel image edit PROMPT --image FILE` | Edit one or more images |
|
|
113
|
+
| `everypixel image vectorize FILE` | Convert an image to SVG |
|
|
113
114
|
| `everypixel image upscale` | Upscale an image, URL, or existing task result |
|
|
114
115
|
| `everypixel image angles --image FILE` | Change the camera angle of an image |
|
|
115
116
|
| `everypixel image colors --image FILE --reference FILE` | Transfer colors from a reference image |
|
|
@@ -125,6 +126,13 @@ everypixel image edit \
|
|
|
125
126
|
|
|
126
127
|
everypixel image upscale --image ./input.png --download ./outputs
|
|
127
128
|
|
|
129
|
+
everypixel image generate "a mountain icon" \
|
|
130
|
+
--model recraftv4_1_vector \
|
|
131
|
+
--controls '{"colors":[{"rgb":[20,100,180],"weight":1}]}' \
|
|
132
|
+
--download ./outputs
|
|
133
|
+
|
|
134
|
+
everypixel image vectorize ./input.png --download ./outputs
|
|
135
|
+
|
|
128
136
|
everypixel image angles \
|
|
129
137
|
--image ./input.png \
|
|
130
138
|
--azimuth right \
|
|
@@ -133,6 +141,16 @@ everypixel image angles \
|
|
|
133
141
|
--download ./outputs
|
|
134
142
|
```
|
|
135
143
|
|
|
144
|
+
Recraft V4.1 vector models (`recraftv4_1_vector`, `recraftv4_1_pro_vector`)
|
|
145
|
+
produce SVG files and accept optional JSON palette `--controls`. Use `--size`
|
|
146
|
+
to select their aspect ratio. Raster models also accept `--resolution`.
|
|
147
|
+
|
|
148
|
+
`--lora-url` is supported only by `zimage`.
|
|
149
|
+
|
|
150
|
+
Grok image models are `grok-imagine`, `grok-imagine-2`, and
|
|
151
|
+
`grok-imagine-2-low`. The `grok` alias remains supported. `grok_quality` and
|
|
152
|
+
`wan22` have been removed from the API.
|
|
153
|
+
|
|
136
154
|
### Video
|
|
137
155
|
|
|
138
156
|
| Command | Description |
|
|
@@ -163,8 +181,36 @@ everypixel video edit \
|
|
|
163
181
|
"make the scene cinematic" \
|
|
164
182
|
--video ./input.mp4 \
|
|
165
183
|
--download ./outputs
|
|
184
|
+
|
|
185
|
+
everypixel video generate "a slow aerial shot over mountain lakes" \
|
|
186
|
+
--model minimax-h3-turbo --duration 10 --download ./outputs
|
|
187
|
+
|
|
188
|
+
everypixel video edit "continue the scene with a slow camera pan" \
|
|
189
|
+
--model flux3 --video ./input.mp4 --download ./outputs
|
|
190
|
+
|
|
191
|
+
everypixel video upscale --video ./input.mp4 \
|
|
192
|
+
--model topaz-prob-4 --resolution 4k --download ./outputs
|
|
166
193
|
```
|
|
167
194
|
|
|
195
|
+
New video models use these provider defaults and limits:
|
|
196
|
+
|
|
197
|
+
| Model | Duration | Default resolution / aspect ratio | Inputs |
|
|
198
|
+
| --- | --- | --- | --- |
|
|
199
|
+
| `minimax-h3-turbo`, `minimax-h3` | 3–15 s | 768p / 7:4 | Text, first/last frames, or one `--reference-image` |
|
|
200
|
+
| `wan3.0` | 2–30 s | 1080p / adaptive | Text, frames, or up to 10 reference images and 5 reference videos |
|
|
201
|
+
| `flux3` | 5–20 s generation; 5–15 s continuation | 720p / 16:9 | Text, frames, or `video edit --video` for continuation |
|
|
202
|
+
| `seedance2.5` | 4–30 s | 720p / 16:9 | Text or `video edit` references, including audio alone |
|
|
203
|
+
|
|
204
|
+
MiniMax reference images cannot be combined with first/last frames. WAN 3.0
|
|
205
|
+
also separates frame and reference inputs. Seedance 2.5 supports up to 1080p;
|
|
206
|
+
Seedance 2 and Mini retain their 15-second limit. Grok video model names are
|
|
207
|
+
`grok-imagine` and `grok-imagine-1.5` (image required); `grok` and `grok15`
|
|
208
|
+
remain accepted aliases. The CLI's default video model remains `ltx23`.
|
|
209
|
+
|
|
210
|
+
Topaz upscaling models are `topaz-prob-4`, `topaz-slp-2.5`, and `topaz-ast-2`.
|
|
211
|
+
They support 4K output. The default `seedvr2` supports up to 1440p, with a
|
|
212
|
+
20-second source limit at 1440p.
|
|
213
|
+
|
|
168
214
|
### Lipsync and Audio
|
|
169
215
|
|
|
170
216
|
| Command | Description |
|
|
@@ -176,6 +222,8 @@ everypixel video edit \
|
|
|
176
222
|
| `everypixel audio tts-clone` | Create speech from a cloned voice sample |
|
|
177
223
|
| `everypixel audio tts-voice` | Create speech with a character voice |
|
|
178
224
|
|
|
225
|
+
Lipsync supports 720p; the API checks source media dimensions and duration.
|
|
226
|
+
|
|
179
227
|
Examples:
|
|
180
228
|
|
|
181
229
|
```bash
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.0"
|
|
@@ -7,9 +7,9 @@ import time
|
|
|
7
7
|
from collections.abc import Callable, Mapping
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Any, Protocol
|
|
10
|
+
from typing import Any, Protocol, get_args
|
|
11
11
|
|
|
12
|
-
from pydantic import TypeAdapter, ValidationError
|
|
12
|
+
from pydantic import BaseModel, TypeAdapter, ValidationError
|
|
13
13
|
|
|
14
14
|
from ..errors import (
|
|
15
15
|
APIResponseError,
|
|
@@ -36,12 +36,16 @@ from ..schemas import (
|
|
|
36
36
|
ImageEditPayload,
|
|
37
37
|
ImageGeneratePayload,
|
|
38
38
|
ImageUpscalePayload,
|
|
39
|
+
ImageVectorizePayload,
|
|
39
40
|
LipsyncImagePayload,
|
|
40
41
|
LipsyncVideoPayload,
|
|
42
|
+
RecraftGeneratePayload,
|
|
41
43
|
TaskResponse,
|
|
42
44
|
VideoEditRequest,
|
|
43
45
|
VideoGenerateRequest,
|
|
46
|
+
VideoGenerateModel,
|
|
44
47
|
VideoUpscalePayload,
|
|
48
|
+
normalize_grok_model,
|
|
45
49
|
)
|
|
46
50
|
from .models import (
|
|
47
51
|
ExecutionOptions,
|
|
@@ -328,6 +332,8 @@ def fallback_extension_for_endpoint(path: str) -> str:
|
|
|
328
332
|
"""Infer the existing conservative extension fallback from an endpoint path."""
|
|
329
333
|
|
|
330
334
|
lowered = path.lower()
|
|
335
|
+
if lowered == "/v1/image_vectorize":
|
|
336
|
+
return ".svg"
|
|
331
337
|
if "transcribe" in lowered or "asr" in lowered:
|
|
332
338
|
return ".txt"
|
|
333
339
|
if "video" in lowered or "lipsync" in lowered:
|
|
@@ -468,6 +474,31 @@ def _build_wan_video_edit_payload(inputs: _VideoEditInputs) -> dict[str, Any]:
|
|
|
468
474
|
)
|
|
469
475
|
|
|
470
476
|
|
|
477
|
+
def _build_flux3_video_edit_payload(inputs: _VideoEditInputs) -> dict[str, Any]:
|
|
478
|
+
_reject_video_edit_options(
|
|
479
|
+
inputs.model,
|
|
480
|
+
{
|
|
481
|
+
"image": inputs.images,
|
|
482
|
+
"audio": inputs.audio,
|
|
483
|
+
"seed": inputs.seed,
|
|
484
|
+
"keyframe": inputs.keyframes,
|
|
485
|
+
"public_figure_threshold": inputs.public_figure_threshold,
|
|
486
|
+
},
|
|
487
|
+
)
|
|
488
|
+
return _validated_video_edit_payload(
|
|
489
|
+
{
|
|
490
|
+
"prompt": inputs.prompt,
|
|
491
|
+
"model": inputs.model,
|
|
492
|
+
"duration": inputs.duration,
|
|
493
|
+
"resolution": inputs.resolution,
|
|
494
|
+
"aspect_ratio": inputs.aspect_ratio,
|
|
495
|
+
"video_url": media_value(inputs.video) if inputs.video else None,
|
|
496
|
+
"generate_audio": inputs.generate_audio,
|
|
497
|
+
"callback_url": inputs.callback_url,
|
|
498
|
+
}
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
|
|
471
502
|
def _parse_aleph_keyframe(value: str) -> dict[str, Any]:
|
|
472
503
|
try:
|
|
473
504
|
keyframe = json.loads(value)
|
|
@@ -509,9 +540,11 @@ def _build_aleph_video_edit_payload(inputs: _VideoEditInputs) -> dict[str, Any]:
|
|
|
509
540
|
_VIDEO_EDIT_BUILDERS: dict[str, Callable[[_VideoEditInputs], dict[str, Any]]] = {
|
|
510
541
|
"seedance2": _build_seedance_video_edit_payload,
|
|
511
542
|
"seedance2-mini": _build_seedance_video_edit_payload,
|
|
543
|
+
"seedance2.5": _build_seedance_video_edit_payload,
|
|
512
544
|
"kling-3-omni": _build_kling_video_edit_payload,
|
|
513
545
|
"wan2.7": _build_wan_video_edit_payload,
|
|
514
546
|
"aleph2": _build_aleph_video_edit_payload,
|
|
547
|
+
"flux3": _build_flux3_video_edit_payload,
|
|
515
548
|
}
|
|
516
549
|
|
|
517
550
|
|
|
@@ -557,14 +590,30 @@ def build_video_edit_payload(
|
|
|
557
590
|
return builder(inputs)
|
|
558
591
|
|
|
559
592
|
|
|
593
|
+
_IMAGE_GENERATE_BUILDERS: dict[str, type[BaseModel]] = {
|
|
594
|
+
"recraftv4_1_vector": RecraftGeneratePayload,
|
|
595
|
+
"recraftv4_1_pro_vector": RecraftGeneratePayload,
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
|
|
560
599
|
def build_image_generate_payload(**values: Any) -> dict[str, Any]:
|
|
561
600
|
"""Validate and build image generation payloads including local media."""
|
|
562
601
|
|
|
563
602
|
image = values.pop("image", None)
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
603
|
+
if image is not None:
|
|
604
|
+
values["image_url"] = media_value(image)
|
|
605
|
+
controls = values.get("controls")
|
|
606
|
+
if isinstance(controls, str):
|
|
607
|
+
try:
|
|
608
|
+
values["controls"] = json.loads(controls)
|
|
609
|
+
except json.JSONDecodeError as exc:
|
|
610
|
+
raise InputParsingError("Unable to parse Recraft controls JSON") from exc
|
|
611
|
+
builder = _IMAGE_GENERATE_BUILDERS.get(
|
|
612
|
+
values.get("model", "zimage"), ImageGeneratePayload
|
|
613
|
+
)
|
|
614
|
+
return builder.model_validate(
|
|
615
|
+
{key: value for key, value in values.items() if value is not None}
|
|
616
|
+
).model_dump(mode="json", exclude_none=True)
|
|
568
617
|
|
|
569
618
|
|
|
570
619
|
def build_image_edit_payload(**values: Any) -> dict[str, Any]:
|
|
@@ -574,7 +623,15 @@ def build_image_edit_payload(**values: Any) -> dict[str, Any]:
|
|
|
574
623
|
return ImageEditPayload(
|
|
575
624
|
**{key: value for key, value in values.items() if value is not None},
|
|
576
625
|
image_urls=[media_value(item) for item in images],
|
|
577
|
-
).model_dump(exclude_none=True)
|
|
626
|
+
).model_dump(mode="json", exclude_none=True)
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def build_image_vectorize_payload(
|
|
630
|
+
*, image: str, callback_url: str | None
|
|
631
|
+
) -> dict[str, Any]:
|
|
632
|
+
return ImageVectorizePayload.model_validate(
|
|
633
|
+
{"image_url": media_value(image), "callback_url": callback_url}
|
|
634
|
+
).model_dump(mode="json", exclude_none=True)
|
|
578
635
|
|
|
579
636
|
|
|
580
637
|
def build_image_upscale_payload(**values: Any) -> dict[str, Any]:
|
|
@@ -594,13 +651,15 @@ def build_video_generate_payload(**values: Any) -> dict[str, Any]:
|
|
|
594
651
|
last_image = values.pop("last_image", None)
|
|
595
652
|
reference_images = values.pop("reference_images", [])
|
|
596
653
|
reference_videos = values.pop("reference_videos", [])
|
|
654
|
+
values = normalize_grok_model(values)
|
|
597
655
|
if values.get("duration") is None:
|
|
598
656
|
model = values.get("model")
|
|
599
657
|
required_duration_defaults = {
|
|
600
|
-
"
|
|
658
|
+
"minimax-h3-turbo": 5,
|
|
659
|
+
"minimax-h3": 5,
|
|
601
660
|
"ltx23": 5,
|
|
602
|
-
"grok": 5,
|
|
603
|
-
"
|
|
661
|
+
"grok-imagine": 5,
|
|
662
|
+
"grok-imagine-1.5": 5,
|
|
604
663
|
}
|
|
605
664
|
values["duration"] = (
|
|
606
665
|
required_duration_defaults.get(model) if isinstance(model, str) else None
|
|
@@ -771,6 +830,8 @@ class ApplicationServices:
|
|
|
771
830
|
seed: int,
|
|
772
831
|
callback_url: str | None,
|
|
773
832
|
execution: ExecutionOptions,
|
|
833
|
+
lora_url: str | None = None,
|
|
834
|
+
controls: dict[str, Any] | str | None = None,
|
|
774
835
|
) -> OperationResult:
|
|
775
836
|
payload = build_image_generate_payload(
|
|
776
837
|
prompt=prompt,
|
|
@@ -781,12 +842,33 @@ class ApplicationServices:
|
|
|
781
842
|
resolution=resolution,
|
|
782
843
|
seed=seed,
|
|
783
844
|
callback_url=callback_url,
|
|
845
|
+
lora_url=lora_url,
|
|
846
|
+
controls=controls,
|
|
784
847
|
)
|
|
785
848
|
return self._execute_async(
|
|
786
849
|
endpoint="/v1/image_generate",
|
|
787
850
|
payload=payload,
|
|
788
851
|
execution=execution,
|
|
789
|
-
fallback_extension=
|
|
852
|
+
fallback_extension=(
|
|
853
|
+
".svg" if model in _IMAGE_GENERATE_BUILDERS else ".png"
|
|
854
|
+
),
|
|
855
|
+
)
|
|
856
|
+
|
|
857
|
+
def execute_image_vectorize(
|
|
858
|
+
self,
|
|
859
|
+
*,
|
|
860
|
+
image: str,
|
|
861
|
+
callback_url: str | None = None,
|
|
862
|
+
execution: ExecutionOptions,
|
|
863
|
+
) -> OperationResult:
|
|
864
|
+
return self._execute_async(
|
|
865
|
+
endpoint="/v1/image_vectorize",
|
|
866
|
+
payload=build_image_vectorize_payload(
|
|
867
|
+
image=image,
|
|
868
|
+
callback_url=callback_url,
|
|
869
|
+
),
|
|
870
|
+
execution=execution,
|
|
871
|
+
fallback_extension=".svg",
|
|
790
872
|
)
|
|
791
873
|
|
|
792
874
|
def execute_image_edit(
|
|
@@ -800,6 +882,7 @@ class ApplicationServices:
|
|
|
800
882
|
seed: int,
|
|
801
883
|
callback_url: str | None,
|
|
802
884
|
execution: ExecutionOptions,
|
|
885
|
+
megapixel_ratio: float = 1.0,
|
|
803
886
|
) -> OperationResult:
|
|
804
887
|
payload = build_image_edit_payload(
|
|
805
888
|
prompt=prompt,
|
|
@@ -807,6 +890,7 @@ class ApplicationServices:
|
|
|
807
890
|
model=model,
|
|
808
891
|
image_size=image_size,
|
|
809
892
|
resolution=resolution,
|
|
893
|
+
megapixel_ratio=megapixel_ratio,
|
|
810
894
|
seed=seed,
|
|
811
895
|
callback_url=callback_url,
|
|
812
896
|
)
|
|
@@ -885,8 +969,6 @@ class ApplicationServices:
|
|
|
885
969
|
duration: int | None,
|
|
886
970
|
resolution: str | None,
|
|
887
971
|
aspect_ratio: str | None,
|
|
888
|
-
lora_high_url: str | None = None,
|
|
889
|
-
lora_low_url: str | None = None,
|
|
890
972
|
reference_images: list[str] | None = None,
|
|
891
973
|
reference_videos: list[str] | None = None,
|
|
892
974
|
image: str | None = None,
|
|
@@ -902,8 +984,6 @@ class ApplicationServices:
|
|
|
902
984
|
duration=duration,
|
|
903
985
|
resolution=resolution,
|
|
904
986
|
aspect_ratio=aspect_ratio,
|
|
905
|
-
lora_high_url=lora_high_url,
|
|
906
|
-
lora_low_url=lora_low_url,
|
|
907
987
|
reference_images=reference_images or [],
|
|
908
988
|
reference_videos=reference_videos or [],
|
|
909
989
|
image=image,
|
|
@@ -966,11 +1046,15 @@ class ApplicationServices:
|
|
|
966
1046
|
task_id: str | None,
|
|
967
1047
|
resolution: str,
|
|
968
1048
|
execution: ExecutionOptions,
|
|
1049
|
+
model: str = "seedvr2",
|
|
1050
|
+
callback_url: str | None = None,
|
|
969
1051
|
) -> OperationResult:
|
|
970
1052
|
payload = build_video_upscale_payload(
|
|
971
1053
|
video=video,
|
|
972
1054
|
video_from_task_id=task_id,
|
|
973
1055
|
resolution=resolution,
|
|
1056
|
+
model=model,
|
|
1057
|
+
callback_url=callback_url,
|
|
974
1058
|
)
|
|
975
1059
|
return self._execute_async(
|
|
976
1060
|
endpoint="/v1/video_upscale",
|
|
@@ -1169,8 +1253,10 @@ class ApplicationServices:
|
|
|
1169
1253
|
path = operation.path
|
|
1170
1254
|
resolved_method = operation.method
|
|
1171
1255
|
resolved_method = resolved_method or "POST"
|
|
1172
|
-
if path
|
|
1256
|
+
if path in {"/v1/video_edit", "/v1/video_generate"}:
|
|
1173
1257
|
normalize_video_edit_content(payload)
|
|
1258
|
+
if path == "/v1/image_vectorize" and isinstance(payload.get("image_url"), str):
|
|
1259
|
+
payload["image_url"] = media_value(payload["image_url"])
|
|
1174
1260
|
if help_schema:
|
|
1175
1261
|
return OperationResult(
|
|
1176
1262
|
value=operation_help(
|
|
@@ -1181,6 +1267,14 @@ class ApplicationServices:
|
|
|
1181
1267
|
schema_source=schema_source,
|
|
1182
1268
|
)
|
|
1183
1269
|
)
|
|
1270
|
+
if path in {"/v1/image_generate", "/v1/image_edit", "/v1/video_generate"}:
|
|
1271
|
+
payload = normalize_grok_model(payload)
|
|
1272
|
+
if path == "/v1/video_generate" and payload.get("model") in get_args(
|
|
1273
|
+
VideoGenerateModel
|
|
1274
|
+
):
|
|
1275
|
+
_VIDEO_GENERATE_ADAPTER.validate_python(payload, extra="ignore")
|
|
1276
|
+
if path == "/v1/image_vectorize":
|
|
1277
|
+
ImageVectorizePayload.model_validate(payload)
|
|
1184
1278
|
if path == "/v1/video_edit":
|
|
1185
1279
|
# Generic callers may send forward-compatible fields that the local
|
|
1186
1280
|
# specialized model does not know yet; validate known semantics
|
|
@@ -1205,7 +1299,12 @@ class ApplicationServices:
|
|
|
1205
1299
|
method=resolved_method,
|
|
1206
1300
|
payload=payload,
|
|
1207
1301
|
execution=execution,
|
|
1208
|
-
fallback_extension=
|
|
1302
|
+
fallback_extension=(
|
|
1303
|
+
".svg"
|
|
1304
|
+
if path == "/v1/image_generate"
|
|
1305
|
+
and payload.get("model") in _IMAGE_GENERATE_BUILDERS
|
|
1306
|
+
else fallback_extension_for_endpoint(path)
|
|
1307
|
+
),
|
|
1209
1308
|
)
|
|
1210
1309
|
)
|
|
1211
1310
|
|
|
@@ -1322,17 +1421,19 @@ def parse_generic_payload(
|
|
|
1322
1421
|
|
|
1323
1422
|
|
|
1324
1423
|
def normalize_video_edit_content(payload: dict[str, Any]) -> None:
|
|
1325
|
-
"""Encode local generic
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1424
|
+
"""Encode local generic video frames and references as data URIs."""
|
|
1425
|
+
|
|
1426
|
+
for key in ("video_url", "image_url", "image_last_url"):
|
|
1427
|
+
value = payload.get(key)
|
|
1428
|
+
if isinstance(value, str):
|
|
1429
|
+
payload[key] = media_value(value)
|
|
1430
|
+
for key in ("reference_image_urls", "reference_video_urls"):
|
|
1431
|
+
values = payload.get(key)
|
|
1432
|
+
if isinstance(values, list):
|
|
1433
|
+
payload[key] = [
|
|
1434
|
+
media_value(value) if isinstance(value, str) else value
|
|
1435
|
+
for value in values
|
|
1436
|
+
]
|
|
1336
1437
|
keyframes = payload.get("keyframes")
|
|
1337
1438
|
if isinstance(keyframes, list):
|
|
1338
1439
|
for keyframe in keyframes:
|
|
@@ -578,6 +578,11 @@ def image_generate(
|
|
|
578
578
|
size: Annotated[str, typer.Option("--size")] = "square",
|
|
579
579
|
style: Annotated[Optional[str], typer.Option("--style")] = None,
|
|
580
580
|
image: Annotated[Optional[str], typer.Option("--image")] = None,
|
|
581
|
+
lora_url: Annotated[Optional[str], typer.Option("--lora-url")] = None,
|
|
582
|
+
controls: Annotated[
|
|
583
|
+
Optional[str],
|
|
584
|
+
typer.Option("--controls", help="Recraft palette controls as JSON."),
|
|
585
|
+
] = None,
|
|
581
586
|
resolution: Annotated[Optional[str], typer.Option("--resolution")] = None,
|
|
582
587
|
seed: Annotated[int, typer.Option("--seed")] = -1,
|
|
583
588
|
callback_url: Annotated[Optional[str], typer.Option("--callback-url")] = None,
|
|
@@ -603,6 +608,8 @@ def image_generate(
|
|
|
603
608
|
image_size=size,
|
|
604
609
|
style=style,
|
|
605
610
|
image=image,
|
|
611
|
+
lora_url=lora_url,
|
|
612
|
+
controls=controls,
|
|
606
613
|
resolution=resolution,
|
|
607
614
|
seed=seed,
|
|
608
615
|
callback_url=callback_url,
|
|
@@ -622,6 +629,7 @@ def image_edit(
|
|
|
622
629
|
model: Annotated[str, typer.Option("--model")] = "flux2",
|
|
623
630
|
size: Annotated[Optional[str], typer.Option("--size")] = None,
|
|
624
631
|
resolution: Annotated[Optional[str], typer.Option("--resolution")] = None,
|
|
632
|
+
megapixel_ratio: Annotated[float, typer.Option("--megapixel-ratio")] = 1.0,
|
|
625
633
|
seed: Annotated[int, typer.Option("--seed")] = -1,
|
|
626
634
|
callback_url: Annotated[Optional[str], typer.Option("--callback-url")] = None,
|
|
627
635
|
wait_option: WaitOption = None,
|
|
@@ -646,6 +654,7 @@ def image_edit(
|
|
|
646
654
|
model=model,
|
|
647
655
|
image_size=size,
|
|
648
656
|
resolution=resolution,
|
|
657
|
+
megapixel_ratio=megapixel_ratio,
|
|
649
658
|
seed=seed,
|
|
650
659
|
callback_url=callback_url,
|
|
651
660
|
execution=runtime.execution_options(),
|
|
@@ -653,6 +662,35 @@ def image_edit(
|
|
|
653
662
|
)
|
|
654
663
|
|
|
655
664
|
|
|
665
|
+
@image_app.command("vectorize")
|
|
666
|
+
def image_vectorize(
|
|
667
|
+
ctx: typer.Context,
|
|
668
|
+
image: Annotated[str, typer.Argument(help="Image URL or local path.")],
|
|
669
|
+
callback_url: Annotated[Optional[str], typer.Option("--callback-url")] = None,
|
|
670
|
+
wait_option: WaitOption = None,
|
|
671
|
+
download: DownloadOption = None,
|
|
672
|
+
output_json: OutputJsonOption = False,
|
|
673
|
+
jq_expr: JqOption = None,
|
|
674
|
+
) -> None:
|
|
675
|
+
"""Convert an image to SVG."""
|
|
676
|
+
|
|
677
|
+
runtime = apply_common_options(
|
|
678
|
+
ctx,
|
|
679
|
+
wait_option=wait_option,
|
|
680
|
+
download=download,
|
|
681
|
+
output_json=output_json,
|
|
682
|
+
jq_expr=jq_expr,
|
|
683
|
+
)
|
|
684
|
+
run_action(
|
|
685
|
+
ctx,
|
|
686
|
+
lambda: runtime.services().execute_image_vectorize(
|
|
687
|
+
image=image,
|
|
688
|
+
callback_url=callback_url,
|
|
689
|
+
execution=runtime.execution_options(),
|
|
690
|
+
),
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
|
|
656
694
|
@image_app.command("upscale")
|
|
657
695
|
def image_upscale(
|
|
658
696
|
ctx: typer.Context,
|
|
@@ -757,14 +795,12 @@ def video_generate(
|
|
|
757
795
|
model: str = "ltx23",
|
|
758
796
|
duration: Optional[int] = None,
|
|
759
797
|
resolution: Optional[str] = None,
|
|
760
|
-
aspect_ratio: Annotated[str, typer.Option("--aspect-ratio")] =
|
|
761
|
-
lora_high_url: Annotated[Optional[str], typer.Option("--lora-high-url")] = None,
|
|
762
|
-
lora_low_url: Annotated[Optional[str], typer.Option("--lora-low-url")] = None,
|
|
798
|
+
aspect_ratio: Annotated[Optional[str], typer.Option("--aspect-ratio")] = None,
|
|
763
799
|
reference_image: Annotated[
|
|
764
800
|
list[str],
|
|
765
801
|
typer.Option(
|
|
766
802
|
"--reference-image",
|
|
767
|
-
help="Wan or Veo reference image URL/local path. Can be repeated.",
|
|
803
|
+
help="MiniMax, Wan or Veo reference image URL/local path. Can be repeated.",
|
|
768
804
|
),
|
|
769
805
|
] = [],
|
|
770
806
|
reference_video: Annotated[
|
|
@@ -801,8 +837,6 @@ def video_generate(
|
|
|
801
837
|
duration=duration,
|
|
802
838
|
resolution=resolution,
|
|
803
839
|
aspect_ratio=aspect_ratio,
|
|
804
|
-
lora_high_url=lora_high_url,
|
|
805
|
-
lora_low_url=lora_low_url,
|
|
806
840
|
reference_images=reference_image,
|
|
807
841
|
reference_videos=reference_video,
|
|
808
842
|
seed=seed,
|
|
@@ -895,8 +929,11 @@ def video_from_image(
|
|
|
895
929
|
model: str = "ltx23",
|
|
896
930
|
duration: Optional[int] = None,
|
|
897
931
|
resolution: Optional[str] = None,
|
|
898
|
-
aspect_ratio: Annotated[str, typer.Option("--aspect-ratio")] =
|
|
932
|
+
aspect_ratio: Annotated[Optional[str], typer.Option("--aspect-ratio")] = None,
|
|
899
933
|
seed: Optional[int] = None,
|
|
934
|
+
generate_audio: Annotated[
|
|
935
|
+
Optional[bool], typer.Option("--generate-audio/--no-generate-audio")
|
|
936
|
+
] = None,
|
|
900
937
|
callback_url: Annotated[Optional[str], typer.Option("--callback-url")] = None,
|
|
901
938
|
wait_option: WaitOption = None,
|
|
902
939
|
download: DownloadOption = None,
|
|
@@ -922,6 +959,7 @@ def video_from_image(
|
|
|
922
959
|
aspect_ratio=aspect_ratio,
|
|
923
960
|
image=image,
|
|
924
961
|
seed=seed,
|
|
962
|
+
generate_audio=generate_audio,
|
|
925
963
|
callback_url=callback_url,
|
|
926
964
|
execution=runtime.execution_options(),
|
|
927
965
|
),
|
|
@@ -937,8 +975,11 @@ def video_first_last(
|
|
|
937
975
|
model: str = "ltx23",
|
|
938
976
|
duration: Optional[int] = None,
|
|
939
977
|
resolution: Optional[str] = None,
|
|
940
|
-
aspect_ratio: Annotated[str, typer.Option("--aspect-ratio")] =
|
|
978
|
+
aspect_ratio: Annotated[Optional[str], typer.Option("--aspect-ratio")] = None,
|
|
941
979
|
seed: Optional[int] = None,
|
|
980
|
+
generate_audio: Annotated[
|
|
981
|
+
Optional[bool], typer.Option("--generate-audio/--no-generate-audio")
|
|
982
|
+
] = None,
|
|
942
983
|
callback_url: Annotated[Optional[str], typer.Option("--callback-url")] = None,
|
|
943
984
|
wait_option: WaitOption = None,
|
|
944
985
|
download: DownloadOption = None,
|
|
@@ -965,6 +1006,7 @@ def video_first_last(
|
|
|
965
1006
|
image=image,
|
|
966
1007
|
last_image=last_image,
|
|
967
1008
|
seed=seed,
|
|
1009
|
+
generate_audio=generate_audio,
|
|
968
1010
|
callback_url=callback_url,
|
|
969
1011
|
execution=runtime.execution_options(),
|
|
970
1012
|
),
|
|
@@ -976,11 +1018,15 @@ def video_upscale(
|
|
|
976
1018
|
ctx: typer.Context,
|
|
977
1019
|
video: Annotated[Optional[str], typer.Option("--video")] = None,
|
|
978
1020
|
task_id: Annotated[Optional[str], typer.Option("--task-id")] = None,
|
|
1021
|
+
model: str = "seedvr2",
|
|
1022
|
+
callback_url: Annotated[Optional[str], typer.Option("--callback-url")] = None,
|
|
979
1023
|
resolution: Annotated[
|
|
980
1024
|
str,
|
|
981
1025
|
typer.Option(
|
|
982
1026
|
"--resolution",
|
|
983
|
-
help=
|
|
1027
|
+
help=(
|
|
1028
|
+
"720p, 1080p, 1440p, or 4k (Topaz only). SeedVR2: up to 20s at 1440p."
|
|
1029
|
+
),
|
|
984
1030
|
),
|
|
985
1031
|
] = "1080p",
|
|
986
1032
|
wait_option: WaitOption = None,
|
|
@@ -990,7 +1036,7 @@ def video_upscale(
|
|
|
990
1036
|
) -> None:
|
|
991
1037
|
"""Start video upscale from a URL/file or task_id.
|
|
992
1038
|
|
|
993
|
-
|
|
1039
|
+
SeedVR2 source videos longer than 20 seconds cannot be upscaled to 1440p.
|
|
994
1040
|
"""
|
|
995
1041
|
|
|
996
1042
|
runtime = apply_common_options(
|
|
@@ -1006,6 +1052,8 @@ def video_upscale(
|
|
|
1006
1052
|
video=video,
|
|
1007
1053
|
task_id=task_id,
|
|
1008
1054
|
resolution=resolution,
|
|
1055
|
+
model=model,
|
|
1056
|
+
callback_url=callback_url,
|
|
1009
1057
|
execution=runtime.execution_options(),
|
|
1010
1058
|
),
|
|
1011
1059
|
)
|