magic_hour 0.35.0__py3-none-any.whl → 0.36.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of magic_hour might be problematic. Click here for more details.
- magic_hour/README.md +35 -0
- magic_hour/core/base_client.py +6 -5
- magic_hour/core/query.py +12 -6
- magic_hour/core/request.py +3 -3
- magic_hour/core/response.py +18 -14
- magic_hour/core/utils.py +3 -3
- magic_hour/environment.py +1 -1
- magic_hour/helpers/__init__.py +3 -0
- magic_hour/helpers/download.py +75 -0
- magic_hour/resources/v1/README.md +33 -0
- magic_hour/resources/v1/ai_clothes_changer/README.md +73 -0
- magic_hour/resources/v1/ai_clothes_changer/client.py +146 -0
- magic_hour/resources/v1/ai_face_editor/README.md +110 -0
- magic_hour/resources/v1/ai_face_editor/client.py +168 -0
- magic_hour/resources/v1/ai_gif_generator/README.md +59 -0
- magic_hour/resources/v1/ai_gif_generator/client.py +119 -0
- magic_hour/resources/v1/ai_headshot_generator/README.md +60 -0
- magic_hour/resources/v1/ai_headshot_generator/client.py +140 -0
- magic_hour/resources/v1/ai_image_editor/README.md +64 -0
- magic_hour/resources/v1/ai_image_editor/client.py +136 -0
- magic_hour/resources/v1/ai_image_generator/README.md +66 -0
- magic_hour/resources/v1/ai_image_generator/client.py +139 -0
- magic_hour/resources/v1/ai_image_upscaler/README.md +67 -0
- magic_hour/resources/v1/ai_image_upscaler/client.py +150 -0
- magic_hour/resources/v1/ai_meme_generator/README.md +71 -0
- magic_hour/resources/v1/ai_meme_generator/client.py +127 -0
- magic_hour/resources/v1/ai_photo_editor/README.md +98 -7
- magic_hour/resources/v1/ai_photo_editor/client.py +174 -0
- magic_hour/resources/v1/ai_qr_code_generator/README.md +63 -0
- magic_hour/resources/v1/ai_qr_code_generator/client.py +123 -0
- magic_hour/resources/v1/ai_talking_photo/README.md +74 -0
- magic_hour/resources/v1/ai_talking_photo/client.py +170 -0
- magic_hour/resources/v1/animation/README.md +100 -0
- magic_hour/resources/v1/animation/client.py +218 -0
- magic_hour/resources/v1/auto_subtitle_generator/README.md +69 -0
- magic_hour/resources/v1/auto_subtitle_generator/client.py +178 -0
- magic_hour/resources/v1/face_detection/README.md +59 -0
- magic_hour/resources/v1/face_detection/__init__.py +10 -2
- magic_hour/resources/v1/face_detection/client.py +179 -0
- magic_hour/resources/v1/face_swap/README.md +105 -8
- magic_hour/resources/v1/face_swap/client.py +242 -0
- magic_hour/resources/v1/face_swap_photo/README.md +84 -0
- magic_hour/resources/v1/face_swap_photo/client.py +172 -0
- magic_hour/resources/v1/files/README.md +6 -0
- magic_hour/resources/v1/files/client.py +350 -0
- magic_hour/resources/v1/files/client_test.py +414 -0
- magic_hour/resources/v1/files/upload_urls/README.md +8 -0
- magic_hour/resources/v1/image_background_remover/README.md +68 -0
- magic_hour/resources/v1/image_background_remover/client.py +130 -0
- magic_hour/resources/v1/image_projects/README.md +8 -0
- magic_hour/resources/v1/image_projects/__init__.py +10 -2
- magic_hour/resources/v1/image_projects/client.py +138 -0
- magic_hour/resources/v1/image_projects/client_test.py +527 -0
- magic_hour/resources/v1/image_to_video/README.md +77 -9
- magic_hour/resources/v1/image_to_video/client.py +186 -0
- magic_hour/resources/v1/lip_sync/README.md +87 -9
- magic_hour/resources/v1/lip_sync/client.py +210 -0
- magic_hour/resources/v1/photo_colorizer/README.md +59 -0
- magic_hour/resources/v1/photo_colorizer/client.py +130 -0
- magic_hour/resources/v1/text_to_video/README.md +68 -0
- magic_hour/resources/v1/text_to_video/client.py +151 -0
- magic_hour/resources/v1/video_projects/README.md +8 -0
- magic_hour/resources/v1/video_projects/__init__.py +10 -2
- magic_hour/resources/v1/video_projects/client.py +137 -0
- magic_hour/resources/v1/video_projects/client_test.py +527 -0
- magic_hour/resources/v1/video_to_video/README.md +98 -10
- magic_hour/resources/v1/video_to_video/client.py +222 -0
- magic_hour/types/params/__init__.py +58 -0
- magic_hour/types/params/v1_ai_clothes_changer_generate_body_assets.py +33 -0
- magic_hour/types/params/v1_ai_face_editor_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_ai_headshot_generator_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_ai_image_editor_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_ai_image_upscaler_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_ai_photo_editor_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_ai_talking_photo_generate_body_assets.py +26 -0
- magic_hour/types/params/v1_animation_generate_body_assets.py +39 -0
- magic_hour/types/params/v1_auto_subtitle_generator_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_face_detection_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_face_swap_create_body.py +12 -0
- magic_hour/types/params/v1_face_swap_create_body_style.py +33 -0
- magic_hour/types/params/v1_face_swap_generate_body_assets.py +56 -0
- magic_hour/types/params/v1_face_swap_generate_body_assets_face_mappings_item.py +25 -0
- magic_hour/types/params/v1_face_swap_photo_generate_body_assets.py +47 -0
- magic_hour/types/params/v1_face_swap_photo_generate_body_assets_face_mappings_item.py +25 -0
- magic_hour/types/params/v1_image_background_remover_generate_body_assets.py +27 -0
- magic_hour/types/params/v1_image_to_video_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_lip_sync_generate_body_assets.py +36 -0
- magic_hour/types/params/v1_photo_colorizer_generate_body_assets.py +17 -0
- magic_hour/types/params/v1_video_to_video_generate_body_assets.py +27 -0
- magic_hour-0.36.0.dist-info/METADATA +303 -0
- {magic_hour-0.35.0.dist-info → magic_hour-0.36.0.dist-info}/RECORD +93 -65
- magic_hour-0.35.0.dist-info/METADATA +0 -166
- {magic_hour-0.35.0.dist-info → magic_hour-0.36.0.dist-info}/LICENSE +0 -0
- {magic_hour-0.35.0.dist-info → magic_hour-0.36.0.dist-info}/WHEEL +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import typing
|
|
2
3
|
|
|
3
4
|
from magic_hour.core import (
|
|
@@ -8,13 +9,87 @@ from magic_hour.core import (
|
|
|
8
9
|
to_encodable,
|
|
9
10
|
type_utils,
|
|
10
11
|
)
|
|
12
|
+
from magic_hour.resources.v1.files.client import AsyncFilesClient, FilesClient
|
|
13
|
+
from magic_hour.resources.v1.image_projects.client import (
|
|
14
|
+
AsyncImageProjectsClient,
|
|
15
|
+
ImageProjectsClient,
|
|
16
|
+
)
|
|
11
17
|
from magic_hour.types import models, params
|
|
12
18
|
|
|
13
19
|
|
|
20
|
+
logging.basicConfig(level=logging.INFO)
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
14
24
|
class AiHeadshotGeneratorClient:
|
|
15
25
|
def __init__(self, *, base_client: SyncBaseClient):
|
|
16
26
|
self._base_client = base_client
|
|
17
27
|
|
|
28
|
+
def generate(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
assets: params.V1AiHeadshotGeneratorGenerateBodyAssets,
|
|
32
|
+
name: typing.Union[
|
|
33
|
+
typing.Optional[str], type_utils.NotGiven
|
|
34
|
+
] = type_utils.NOT_GIVEN,
|
|
35
|
+
style: typing.Union[
|
|
36
|
+
typing.Optional[params.V1AiHeadshotGeneratorCreateBodyStyle],
|
|
37
|
+
type_utils.NotGiven,
|
|
38
|
+
] = type_utils.NOT_GIVEN,
|
|
39
|
+
wait_for_completion: bool = True,
|
|
40
|
+
download_outputs: bool = True,
|
|
41
|
+
download_directory: typing.Optional[str] = None,
|
|
42
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
Generate headshot (alias for create with additional functionality).
|
|
46
|
+
|
|
47
|
+
Generate professional headshots using AI. Each headshot costs 5 credits.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
name: The name of image. This value is mainly used for your own identification of the image.
|
|
51
|
+
assets: Provide the assets for headshot generation
|
|
52
|
+
style: Headshot generation parameters
|
|
53
|
+
wait_for_completion: Whether to wait for the image project to complete
|
|
54
|
+
download_outputs: Whether to download the outputs
|
|
55
|
+
download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
|
|
56
|
+
request_options: Additional options to customize the HTTP request
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
V1ImageProjectsGetResponseWithDownloads: The response from the AI Headshot Generator API with the downloaded paths if `download_outputs` is True.
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
```py
|
|
63
|
+
response = client.v1.ai_headshot_generator.generate(
|
|
64
|
+
assets={"image_file_path": "path/to/person.jpg"},
|
|
65
|
+
name="Professional Headshot",
|
|
66
|
+
wait_for_completion=True,
|
|
67
|
+
download_outputs=True,
|
|
68
|
+
download_directory="outputs/",
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
file_client = FilesClient(base_client=self._base_client)
|
|
74
|
+
|
|
75
|
+
image_file_path = assets["image_file_path"]
|
|
76
|
+
assets["image_file_path"] = file_client.upload_file(file=image_file_path)
|
|
77
|
+
|
|
78
|
+
create_response = self.create(
|
|
79
|
+
assets=assets, style=style, name=name, request_options=request_options
|
|
80
|
+
)
|
|
81
|
+
logger.info(f"AI Headshot Generator response: {create_response}")
|
|
82
|
+
|
|
83
|
+
image_projects_client = ImageProjectsClient(base_client=self._base_client)
|
|
84
|
+
response = image_projects_client.check_result(
|
|
85
|
+
id=create_response.id,
|
|
86
|
+
wait_for_completion=wait_for_completion,
|
|
87
|
+
download_outputs=download_outputs,
|
|
88
|
+
download_directory=download_directory,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return response
|
|
92
|
+
|
|
18
93
|
def create(
|
|
19
94
|
self,
|
|
20
95
|
*,
|
|
@@ -74,6 +149,71 @@ class AsyncAiHeadshotGeneratorClient:
|
|
|
74
149
|
def __init__(self, *, base_client: AsyncBaseClient):
|
|
75
150
|
self._base_client = base_client
|
|
76
151
|
|
|
152
|
+
async def generate(
|
|
153
|
+
self,
|
|
154
|
+
*,
|
|
155
|
+
assets: params.V1AiHeadshotGeneratorGenerateBodyAssets,
|
|
156
|
+
name: typing.Union[
|
|
157
|
+
typing.Optional[str], type_utils.NotGiven
|
|
158
|
+
] = type_utils.NOT_GIVEN,
|
|
159
|
+
style: typing.Union[
|
|
160
|
+
typing.Optional[params.V1AiHeadshotGeneratorCreateBodyStyle],
|
|
161
|
+
type_utils.NotGiven,
|
|
162
|
+
] = type_utils.NOT_GIVEN,
|
|
163
|
+
wait_for_completion: bool = True,
|
|
164
|
+
download_outputs: bool = True,
|
|
165
|
+
download_directory: typing.Optional[str] = None,
|
|
166
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
167
|
+
):
|
|
168
|
+
"""
|
|
169
|
+
Generate headshot (alias for create with additional functionality).
|
|
170
|
+
|
|
171
|
+
Generate professional headshots using AI. Each headshot costs 5 credits.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
name: The name of image. This value is mainly used for your own identification of the image.
|
|
175
|
+
assets: Provide the assets for headshot generation
|
|
176
|
+
style: Headshot generation parameters
|
|
177
|
+
wait_for_completion: Whether to wait for the image project to complete
|
|
178
|
+
download_outputs: Whether to download the outputs
|
|
179
|
+
download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
|
|
180
|
+
request_options: Additional options to customize the HTTP request
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
V1ImageProjectsGetResponseWithDownloads: The response from the AI Headshot Generator API with the downloaded paths if `download_outputs` is True.
|
|
184
|
+
|
|
185
|
+
Examples:
|
|
186
|
+
```py
|
|
187
|
+
response = await client.v1.ai_headshot_generator.generate(
|
|
188
|
+
assets={"image_file_path": "path/to/person.jpg"},
|
|
189
|
+
name="Professional Headshot",
|
|
190
|
+
wait_for_completion=True,
|
|
191
|
+
download_outputs=True,
|
|
192
|
+
download_directory="outputs/",
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
file_client = AsyncFilesClient(base_client=self._base_client)
|
|
198
|
+
|
|
199
|
+
image_file_path = assets["image_file_path"]
|
|
200
|
+
assets["image_file_path"] = await file_client.upload_file(file=image_file_path)
|
|
201
|
+
|
|
202
|
+
create_response = await self.create(
|
|
203
|
+
assets=assets, style=style, name=name, request_options=request_options
|
|
204
|
+
)
|
|
205
|
+
logger.info(f"AI Headshot Generator response: {create_response}")
|
|
206
|
+
|
|
207
|
+
image_projects_client = AsyncImageProjectsClient(base_client=self._base_client)
|
|
208
|
+
response = await image_projects_client.check_result(
|
|
209
|
+
id=create_response.id,
|
|
210
|
+
wait_for_completion=wait_for_completion,
|
|
211
|
+
download_outputs=download_outputs,
|
|
212
|
+
download_directory=download_directory,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
return response
|
|
216
|
+
|
|
77
217
|
async def create(
|
|
78
218
|
self,
|
|
79
219
|
*,
|
|
@@ -1,3 +1,64 @@
|
|
|
1
|
+
# v1_ai_image_editor
|
|
2
|
+
|
|
3
|
+
## Module Functions
|
|
4
|
+
|
|
5
|
+
<!-- CUSTOM DOCS START -->
|
|
6
|
+
|
|
7
|
+
### Ai Image Editor Generate Workflow <a name="generate"></a>
|
|
8
|
+
|
|
9
|
+
The workflow performs the following action
|
|
10
|
+
|
|
11
|
+
1. upload local assets to Magic Hour storage. So you can pass in a local path instead of having to upload files yourself
|
|
12
|
+
2. trigger a generation
|
|
13
|
+
3. poll for a completion status. This is configurable
|
|
14
|
+
4. if success, download the output to local directory
|
|
15
|
+
|
|
16
|
+
> [!TIP]
|
|
17
|
+
> This is the recommended way to use the SDK unless you have specific needs where it is necessary to split up the actions.
|
|
18
|
+
|
|
19
|
+
#### Parameters
|
|
20
|
+
|
|
21
|
+
In Additional to the parameters listed in the `.create` section below, `.generate` introduces 3 new parameters:
|
|
22
|
+
|
|
23
|
+
- `wait_for_completion` (bool, default True): Whether to wait for the project to complete.
|
|
24
|
+
- `download_outputs` (bool, default True): Whether to download the generated files
|
|
25
|
+
- `download_directory` (str, optional): Directory to save downloaded files (defaults to current directory)
|
|
26
|
+
|
|
27
|
+
#### Synchronous Client
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from magic_hour import Client
|
|
31
|
+
from os import getenv
|
|
32
|
+
|
|
33
|
+
client = Client(token=getenv("API_TOKEN"))
|
|
34
|
+
res = client.v1.ai_image_editor.generate(
|
|
35
|
+
assets={"image_file_path": "/path/to/1234.png"},
|
|
36
|
+
style={"prompt": "Give me sunglasses"},
|
|
37
|
+
name="Ai Image Editor image",
|
|
38
|
+
wait_for_completion=True,
|
|
39
|
+
download_outputs=True,
|
|
40
|
+
download_directory="outputs"
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Asynchronous Client
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from magic_hour import AsyncClient
|
|
48
|
+
from os import getenv
|
|
49
|
+
|
|
50
|
+
client = AsyncClient(token=getenv("API_TOKEN"))
|
|
51
|
+
res = await client.v1.ai_image_editor.generate(
|
|
52
|
+
assets={"image_file_path": "/path/to/1234.png"},
|
|
53
|
+
style={"prompt": "Give me sunglasses"},
|
|
54
|
+
name="Ai Image Editor image",
|
|
55
|
+
wait_for_completion=True,
|
|
56
|
+
download_outputs=True,
|
|
57
|
+
download_directory="outputs"
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
<!-- CUSTOM DOCS END -->
|
|
1
62
|
|
|
2
63
|
### AI Image Editor <a name="create"></a>
|
|
3
64
|
|
|
@@ -10,7 +71,9 @@ Edit images with AI. Each edit costs 50 credits.
|
|
|
10
71
|
| Parameter | Required | Description | Example |
|
|
11
72
|
|-----------|:--------:|-------------|--------|
|
|
12
73
|
| `assets` | ✓ | Provide the assets for image edit | `{"image_file_path": "api-assets/id/1234.png"}` |
|
|
74
|
+
| `└─ image_file_path` | ✓ | The image used in the edit. This value is either - a direct URL to the video file - `file_path` field from the response of the [upload urls API](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls). Please refer to the [Input File documentation](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) to learn more. | `"api-assets/id/1234.png"` |
|
|
13
75
|
| `style` | ✓ | | `{"prompt": "Give me sunglasses"}` |
|
|
76
|
+
| `└─ prompt` | ✓ | The prompt used to edit the image. | `"Give me sunglasses"` |
|
|
14
77
|
| `name` | ✗ | The name of image. This value is mainly used for your own identification of the image. | `"Ai Image Editor image"` |
|
|
15
78
|
|
|
16
79
|
#### Synchronous Client
|
|
@@ -50,3 +113,4 @@ res = await client.v1.ai_image_editor.create(
|
|
|
50
113
|
|
|
51
114
|
##### Example
|
|
52
115
|
`{"credits_charged": 50, "frame_cost": 50, "id": "cuid-example"}`
|
|
116
|
+
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import typing
|
|
2
3
|
|
|
3
4
|
from magic_hour.core import (
|
|
@@ -8,13 +9,85 @@ from magic_hour.core import (
|
|
|
8
9
|
to_encodable,
|
|
9
10
|
type_utils,
|
|
10
11
|
)
|
|
12
|
+
from magic_hour.resources.v1.files.client import AsyncFilesClient, FilesClient
|
|
13
|
+
from magic_hour.resources.v1.image_projects.client import (
|
|
14
|
+
AsyncImageProjectsClient,
|
|
15
|
+
ImageProjectsClient,
|
|
16
|
+
)
|
|
11
17
|
from magic_hour.types import models, params
|
|
12
18
|
|
|
13
19
|
|
|
20
|
+
logging.basicConfig(level=logging.INFO)
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
14
24
|
class AiImageEditorClient:
|
|
15
25
|
def __init__(self, *, base_client: SyncBaseClient):
|
|
16
26
|
self._base_client = base_client
|
|
17
27
|
|
|
28
|
+
def generate(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
assets: params.V1AiImageEditorGenerateBodyAssets,
|
|
32
|
+
style: params.V1AiImageEditorCreateBodyStyle,
|
|
33
|
+
name: typing.Union[
|
|
34
|
+
typing.Optional[str], type_utils.NotGiven
|
|
35
|
+
] = type_utils.NOT_GIVEN,
|
|
36
|
+
wait_for_completion: bool = True,
|
|
37
|
+
download_outputs: bool = True,
|
|
38
|
+
download_directory: typing.Optional[str] = None,
|
|
39
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
40
|
+
):
|
|
41
|
+
"""
|
|
42
|
+
Generate edited image (alias for create with additional functionality).
|
|
43
|
+
|
|
44
|
+
Edit image using AI. Each edit costs 5 credits.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
name: The name of image. This value is mainly used for your own identification of the image.
|
|
48
|
+
assets: Provide the assets for image editor
|
|
49
|
+
style: Image editing parameters
|
|
50
|
+
wait_for_completion: Whether to wait for the image project to complete
|
|
51
|
+
download_outputs: Whether to download the outputs
|
|
52
|
+
download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
|
|
53
|
+
request_options: Additional options to customize the HTTP request
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
V1ImageProjectsGetResponseWithDownloads: The response from the AI Image Editor API with the downloaded paths if `download_outputs` is True.
|
|
57
|
+
|
|
58
|
+
Examples:
|
|
59
|
+
```py
|
|
60
|
+
response = client.v1.ai_image_editor.generate(
|
|
61
|
+
assets={"image_file_path": "path/to/image.png"},
|
|
62
|
+
style={"prompt": "Add a sunset background"},
|
|
63
|
+
name="Edited Image",
|
|
64
|
+
wait_for_completion=True,
|
|
65
|
+
download_outputs=True,
|
|
66
|
+
download_directory="outputs/",
|
|
67
|
+
)
|
|
68
|
+
```
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
file_client = FilesClient(base_client=self._base_client)
|
|
72
|
+
|
|
73
|
+
image_file_path = assets["image_file_path"]
|
|
74
|
+
assets["image_file_path"] = file_client.upload_file(file=image_file_path)
|
|
75
|
+
|
|
76
|
+
create_response = self.create(
|
|
77
|
+
assets=assets, style=style, name=name, request_options=request_options
|
|
78
|
+
)
|
|
79
|
+
logger.info(f"AI Image Editor response: {create_response}")
|
|
80
|
+
|
|
81
|
+
image_projects_client = ImageProjectsClient(base_client=self._base_client)
|
|
82
|
+
response = image_projects_client.check_result(
|
|
83
|
+
id=create_response.id,
|
|
84
|
+
wait_for_completion=wait_for_completion,
|
|
85
|
+
download_outputs=download_outputs,
|
|
86
|
+
download_directory=download_directory,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return response
|
|
90
|
+
|
|
18
91
|
def create(
|
|
19
92
|
self,
|
|
20
93
|
*,
|
|
@@ -72,6 +145,69 @@ class AsyncAiImageEditorClient:
|
|
|
72
145
|
def __init__(self, *, base_client: AsyncBaseClient):
|
|
73
146
|
self._base_client = base_client
|
|
74
147
|
|
|
148
|
+
async def generate(
|
|
149
|
+
self,
|
|
150
|
+
*,
|
|
151
|
+
assets: params.V1AiImageEditorGenerateBodyAssets,
|
|
152
|
+
style: params.V1AiImageEditorCreateBodyStyle,
|
|
153
|
+
name: typing.Union[
|
|
154
|
+
typing.Optional[str], type_utils.NotGiven
|
|
155
|
+
] = type_utils.NOT_GIVEN,
|
|
156
|
+
wait_for_completion: bool = True,
|
|
157
|
+
download_outputs: bool = True,
|
|
158
|
+
download_directory: typing.Optional[str] = None,
|
|
159
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
160
|
+
):
|
|
161
|
+
"""
|
|
162
|
+
Generate edited image (alias for create with additional functionality).
|
|
163
|
+
|
|
164
|
+
Edit image using AI. Each edit costs 5 credits.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
name: The name of image. This value is mainly used for your own identification of the image.
|
|
168
|
+
assets: Provide the assets for image editor
|
|
169
|
+
style: Image editing parameters
|
|
170
|
+
wait_for_completion: Whether to wait for the image project to complete
|
|
171
|
+
download_outputs: Whether to download the outputs
|
|
172
|
+
download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
|
|
173
|
+
request_options: Additional options to customize the HTTP request
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
V1ImageProjectsGetResponseWithDownloads: The response from the AI Image Editor API with the downloaded paths if `download_outputs` is True.
|
|
177
|
+
|
|
178
|
+
Examples:
|
|
179
|
+
```py
|
|
180
|
+
response = await client.v1.ai_image_editor.generate(
|
|
181
|
+
assets={"image_file_path": "path/to/image.png"},
|
|
182
|
+
style={"prompt": "Add a sunset background"},
|
|
183
|
+
name="Edited Image",
|
|
184
|
+
wait_for_completion=True,
|
|
185
|
+
download_outputs=True,
|
|
186
|
+
download_directory="outputs/",
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
file_client = AsyncFilesClient(base_client=self._base_client)
|
|
192
|
+
|
|
193
|
+
image_file_path = assets["image_file_path"]
|
|
194
|
+
assets["image_file_path"] = await file_client.upload_file(file=image_file_path)
|
|
195
|
+
|
|
196
|
+
create_response = await self.create(
|
|
197
|
+
assets=assets, style=style, name=name, request_options=request_options
|
|
198
|
+
)
|
|
199
|
+
logger.info(f"AI Image Editor response: {create_response}")
|
|
200
|
+
|
|
201
|
+
image_projects_client = AsyncImageProjectsClient(base_client=self._base_client)
|
|
202
|
+
response = await image_projects_client.check_result(
|
|
203
|
+
id=create_response.id,
|
|
204
|
+
wait_for_completion=wait_for_completion,
|
|
205
|
+
download_outputs=download_outputs,
|
|
206
|
+
download_directory=download_directory,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
return response
|
|
210
|
+
|
|
75
211
|
async def create(
|
|
76
212
|
self,
|
|
77
213
|
*,
|
|
@@ -1,3 +1,66 @@
|
|
|
1
|
+
# v1_ai_image_generator
|
|
2
|
+
|
|
3
|
+
## Module Functions
|
|
4
|
+
|
|
5
|
+
<!-- CUSTOM DOCS START -->
|
|
6
|
+
|
|
7
|
+
### Ai Image Generator Generate Workflow <a name="generate"></a>
|
|
8
|
+
|
|
9
|
+
The workflow performs the following action
|
|
10
|
+
|
|
11
|
+
1. upload local assets to Magic Hour storage. So you can pass in a local path instead of having to upload files yourself
|
|
12
|
+
2. trigger a generation
|
|
13
|
+
3. poll for a completion status. This is configurable
|
|
14
|
+
4. if success, download the output to local directory
|
|
15
|
+
|
|
16
|
+
> [!TIP]
|
|
17
|
+
> This is the recommended way to use the SDK unless you have specific needs where it is necessary to split up the actions.
|
|
18
|
+
|
|
19
|
+
#### Parameters
|
|
20
|
+
|
|
21
|
+
In Additional to the parameters listed in the `.create` section below, `.generate` introduces 3 new parameters:
|
|
22
|
+
|
|
23
|
+
- `wait_for_completion` (bool, default True): Whether to wait for the project to complete.
|
|
24
|
+
- `download_outputs` (bool, default True): Whether to download the generated files
|
|
25
|
+
- `download_directory` (str, optional): Directory to save downloaded files (defaults to current directory)
|
|
26
|
+
|
|
27
|
+
#### Synchronous Client
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from magic_hour import Client
|
|
31
|
+
from os import getenv
|
|
32
|
+
|
|
33
|
+
client = Client(token=getenv("API_TOKEN"))
|
|
34
|
+
res = client.v1.ai_image_generator.generate(
|
|
35
|
+
image_count=1,
|
|
36
|
+
orientation="landscape",
|
|
37
|
+
style={"prompt": "Cool image", "tool": "ai-anime-generator"},
|
|
38
|
+
name="Ai Image image",
|
|
39
|
+
wait_for_completion=True,
|
|
40
|
+
download_outputs=True,
|
|
41
|
+
download_directory="outputs"
|
|
42
|
+
)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Asynchronous Client
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from magic_hour import AsyncClient
|
|
49
|
+
from os import getenv
|
|
50
|
+
|
|
51
|
+
client = AsyncClient(token=getenv("API_TOKEN"))
|
|
52
|
+
res = await client.v1.ai_image_generator.generate(
|
|
53
|
+
image_count=1,
|
|
54
|
+
orientation="landscape",
|
|
55
|
+
style={"prompt": "Cool image", "tool": "ai-anime-generator"},
|
|
56
|
+
name="Ai Image image",
|
|
57
|
+
wait_for_completion=True,
|
|
58
|
+
download_outputs=True,
|
|
59
|
+
download_directory="outputs"
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
<!-- CUSTOM DOCS END -->
|
|
1
64
|
|
|
2
65
|
### AI Images <a name="create"></a>
|
|
3
66
|
|
|
@@ -12,6 +75,8 @@ Create an AI image. Each image costs 5 credits.
|
|
|
12
75
|
| `image_count` | ✓ | Number of images to generate. | `1` |
|
|
13
76
|
| `orientation` | ✓ | The orientation of the output image(s). | `"landscape"` |
|
|
14
77
|
| `style` | ✓ | The art style to use for image generation. | `{"prompt": "Cool image", "tool": "ai-anime-generator"}` |
|
|
78
|
+
| `└─ prompt` | ✓ | The prompt used for the image(s). | `"Cool image"` |
|
|
79
|
+
| `└─ tool` | ✗ | The art style to use for image generation. Defaults to 'general' if not provided. | `"ai-anime-generator"` |
|
|
15
80
|
| `name` | ✗ | The name of image. This value is mainly used for your own identification of the image. | `"Ai Image image"` |
|
|
16
81
|
|
|
17
82
|
#### Synchronous Client
|
|
@@ -53,3 +118,4 @@ res = await client.v1.ai_image_generator.create(
|
|
|
53
118
|
|
|
54
119
|
##### Example
|
|
55
120
|
`{"credits_charged": 5, "frame_cost": 5, "id": "cuid-example"}`
|
|
121
|
+
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import typing
|
|
2
3
|
import typing_extensions
|
|
3
4
|
|
|
@@ -9,13 +10,86 @@ from magic_hour.core import (
|
|
|
9
10
|
to_encodable,
|
|
10
11
|
type_utils,
|
|
11
12
|
)
|
|
13
|
+
from magic_hour.resources.v1.image_projects.client import (
|
|
14
|
+
AsyncImageProjectsClient,
|
|
15
|
+
ImageProjectsClient,
|
|
16
|
+
)
|
|
12
17
|
from magic_hour.types import models, params
|
|
13
18
|
|
|
14
19
|
|
|
20
|
+
logging.basicConfig(level=logging.INFO)
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
15
24
|
class AiImageGeneratorClient:
|
|
16
25
|
def __init__(self, *, base_client: SyncBaseClient):
|
|
17
26
|
self._base_client = base_client
|
|
18
27
|
|
|
28
|
+
def generate(
|
|
29
|
+
self,
|
|
30
|
+
*,
|
|
31
|
+
image_count: int,
|
|
32
|
+
orientation: typing_extensions.Literal["landscape", "portrait", "square"],
|
|
33
|
+
style: params.V1AiImageGeneratorCreateBodyStyle,
|
|
34
|
+
name: typing.Union[
|
|
35
|
+
typing.Optional[str], type_utils.NotGiven
|
|
36
|
+
] = type_utils.NOT_GIVEN,
|
|
37
|
+
wait_for_completion: bool = True,
|
|
38
|
+
download_outputs: bool = True,
|
|
39
|
+
download_directory: typing.Optional[str] = None,
|
|
40
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
41
|
+
):
|
|
42
|
+
"""
|
|
43
|
+
Generate AI images (alias for create with additional functionality).
|
|
44
|
+
|
|
45
|
+
Create AI images with text prompts. Each image costs 5 credits.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
name: The name of image. This value is mainly used for your own identification of the image.
|
|
49
|
+
image_count: Number of images to generate.
|
|
50
|
+
orientation: The orientation of the output image(s).
|
|
51
|
+
style: The art style to use for image generation.
|
|
52
|
+
wait_for_completion: Whether to wait for the image project to complete
|
|
53
|
+
download_outputs: Whether to download the outputs
|
|
54
|
+
download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
|
|
55
|
+
request_options: Additional options to customize the HTTP request
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
V1ImageProjectsGetResponseWithDownloads: The response from the AI Image Generator API with the downloaded paths if `download_outputs` is True.
|
|
59
|
+
|
|
60
|
+
Examples:
|
|
61
|
+
```py
|
|
62
|
+
response = client.v1.ai_image_generator.generate(
|
|
63
|
+
image_count=1,
|
|
64
|
+
orientation="landscape",
|
|
65
|
+
style={"prompt": "Cool image", "tool": "ai-anime-generator"},
|
|
66
|
+
name="Generated Image",
|
|
67
|
+
wait_for_completion=True,
|
|
68
|
+
download_outputs=True,
|
|
69
|
+
download_directory="outputs/",
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
create_response = self.create(
|
|
75
|
+
image_count=image_count,
|
|
76
|
+
orientation=orientation,
|
|
77
|
+
style=style,
|
|
78
|
+
name=name,
|
|
79
|
+
request_options=request_options,
|
|
80
|
+
)
|
|
81
|
+
logger.info(f"AI Image Generator response: {create_response}")
|
|
82
|
+
|
|
83
|
+
image_projects_client = ImageProjectsClient(base_client=self._base_client)
|
|
84
|
+
response = image_projects_client.check_result(
|
|
85
|
+
id=create_response.id,
|
|
86
|
+
wait_for_completion=wait_for_completion,
|
|
87
|
+
download_outputs=download_outputs,
|
|
88
|
+
download_directory=download_directory,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return response
|
|
92
|
+
|
|
19
93
|
def create(
|
|
20
94
|
self,
|
|
21
95
|
*,
|
|
@@ -81,6 +155,71 @@ class AsyncAiImageGeneratorClient:
|
|
|
81
155
|
def __init__(self, *, base_client: AsyncBaseClient):
|
|
82
156
|
self._base_client = base_client
|
|
83
157
|
|
|
158
|
+
async def generate(
|
|
159
|
+
self,
|
|
160
|
+
*,
|
|
161
|
+
image_count: int,
|
|
162
|
+
orientation: typing_extensions.Literal["landscape", "portrait", "square"],
|
|
163
|
+
style: params.V1AiImageGeneratorCreateBodyStyle,
|
|
164
|
+
name: typing.Union[
|
|
165
|
+
typing.Optional[str], type_utils.NotGiven
|
|
166
|
+
] = type_utils.NOT_GIVEN,
|
|
167
|
+
wait_for_completion: bool = True,
|
|
168
|
+
download_outputs: bool = True,
|
|
169
|
+
download_directory: typing.Optional[str] = None,
|
|
170
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
171
|
+
):
|
|
172
|
+
"""
|
|
173
|
+
Generate AI images (alias for create with additional functionality).
|
|
174
|
+
|
|
175
|
+
Create AI images with text prompts. Each image costs 5 credits.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
name: The name of image. This value is mainly used for your own identification of the image.
|
|
179
|
+
image_count: Number of images to generate.
|
|
180
|
+
orientation: The orientation of the output image(s).
|
|
181
|
+
style: The art style to use for image generation.
|
|
182
|
+
wait_for_completion: Whether to wait for the image project to complete
|
|
183
|
+
download_outputs: Whether to download the outputs
|
|
184
|
+
download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
|
|
185
|
+
request_options: Additional options to customize the HTTP request
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
V1ImageProjectsGetResponseWithDownloads: The response from the AI Image Generator API with the downloaded paths if `download_outputs` is True.
|
|
189
|
+
|
|
190
|
+
Examples:
|
|
191
|
+
```py
|
|
192
|
+
response = await client.v1.ai_image_generator.generate(
|
|
193
|
+
image_count=1,
|
|
194
|
+
orientation="landscape",
|
|
195
|
+
style={"prompt": "Cool image", "tool": "ai-anime-generator"},
|
|
196
|
+
name="Generated Image",
|
|
197
|
+
wait_for_completion=True,
|
|
198
|
+
download_outputs=True,
|
|
199
|
+
download_directory="outputs/",
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
create_response = await self.create(
|
|
205
|
+
image_count=image_count,
|
|
206
|
+
orientation=orientation,
|
|
207
|
+
style=style,
|
|
208
|
+
name=name,
|
|
209
|
+
request_options=request_options,
|
|
210
|
+
)
|
|
211
|
+
logger.info(f"AI Image Generator response: {create_response}")
|
|
212
|
+
|
|
213
|
+
image_projects_client = AsyncImageProjectsClient(base_client=self._base_client)
|
|
214
|
+
response = await image_projects_client.check_result(
|
|
215
|
+
id=create_response.id,
|
|
216
|
+
wait_for_completion=wait_for_completion,
|
|
217
|
+
download_outputs=download_outputs,
|
|
218
|
+
download_directory=download_directory,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
return response
|
|
222
|
+
|
|
84
223
|
async def create(
|
|
85
224
|
self,
|
|
86
225
|
*,
|