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.

Files changed (94) hide show
  1. magic_hour/README.md +35 -0
  2. magic_hour/core/base_client.py +6 -5
  3. magic_hour/core/query.py +12 -6
  4. magic_hour/core/request.py +3 -3
  5. magic_hour/core/response.py +18 -14
  6. magic_hour/core/utils.py +3 -3
  7. magic_hour/environment.py +1 -1
  8. magic_hour/helpers/__init__.py +3 -0
  9. magic_hour/helpers/download.py +75 -0
  10. magic_hour/resources/v1/README.md +33 -0
  11. magic_hour/resources/v1/ai_clothes_changer/README.md +73 -0
  12. magic_hour/resources/v1/ai_clothes_changer/client.py +146 -0
  13. magic_hour/resources/v1/ai_face_editor/README.md +110 -0
  14. magic_hour/resources/v1/ai_face_editor/client.py +168 -0
  15. magic_hour/resources/v1/ai_gif_generator/README.md +59 -0
  16. magic_hour/resources/v1/ai_gif_generator/client.py +119 -0
  17. magic_hour/resources/v1/ai_headshot_generator/README.md +60 -0
  18. magic_hour/resources/v1/ai_headshot_generator/client.py +140 -0
  19. magic_hour/resources/v1/ai_image_editor/README.md +64 -0
  20. magic_hour/resources/v1/ai_image_editor/client.py +136 -0
  21. magic_hour/resources/v1/ai_image_generator/README.md +66 -0
  22. magic_hour/resources/v1/ai_image_generator/client.py +139 -0
  23. magic_hour/resources/v1/ai_image_upscaler/README.md +67 -0
  24. magic_hour/resources/v1/ai_image_upscaler/client.py +150 -0
  25. magic_hour/resources/v1/ai_meme_generator/README.md +71 -0
  26. magic_hour/resources/v1/ai_meme_generator/client.py +127 -0
  27. magic_hour/resources/v1/ai_photo_editor/README.md +98 -7
  28. magic_hour/resources/v1/ai_photo_editor/client.py +174 -0
  29. magic_hour/resources/v1/ai_qr_code_generator/README.md +63 -0
  30. magic_hour/resources/v1/ai_qr_code_generator/client.py +123 -0
  31. magic_hour/resources/v1/ai_talking_photo/README.md +74 -0
  32. magic_hour/resources/v1/ai_talking_photo/client.py +170 -0
  33. magic_hour/resources/v1/animation/README.md +100 -0
  34. magic_hour/resources/v1/animation/client.py +218 -0
  35. magic_hour/resources/v1/auto_subtitle_generator/README.md +69 -0
  36. magic_hour/resources/v1/auto_subtitle_generator/client.py +178 -0
  37. magic_hour/resources/v1/face_detection/README.md +59 -0
  38. magic_hour/resources/v1/face_detection/__init__.py +10 -2
  39. magic_hour/resources/v1/face_detection/client.py +179 -0
  40. magic_hour/resources/v1/face_swap/README.md +105 -8
  41. magic_hour/resources/v1/face_swap/client.py +242 -0
  42. magic_hour/resources/v1/face_swap_photo/README.md +84 -0
  43. magic_hour/resources/v1/face_swap_photo/client.py +172 -0
  44. magic_hour/resources/v1/files/README.md +6 -0
  45. magic_hour/resources/v1/files/client.py +350 -0
  46. magic_hour/resources/v1/files/client_test.py +414 -0
  47. magic_hour/resources/v1/files/upload_urls/README.md +8 -0
  48. magic_hour/resources/v1/image_background_remover/README.md +68 -0
  49. magic_hour/resources/v1/image_background_remover/client.py +130 -0
  50. magic_hour/resources/v1/image_projects/README.md +8 -0
  51. magic_hour/resources/v1/image_projects/__init__.py +10 -2
  52. magic_hour/resources/v1/image_projects/client.py +138 -0
  53. magic_hour/resources/v1/image_projects/client_test.py +527 -0
  54. magic_hour/resources/v1/image_to_video/README.md +77 -9
  55. magic_hour/resources/v1/image_to_video/client.py +186 -0
  56. magic_hour/resources/v1/lip_sync/README.md +87 -9
  57. magic_hour/resources/v1/lip_sync/client.py +210 -0
  58. magic_hour/resources/v1/photo_colorizer/README.md +59 -0
  59. magic_hour/resources/v1/photo_colorizer/client.py +130 -0
  60. magic_hour/resources/v1/text_to_video/README.md +68 -0
  61. magic_hour/resources/v1/text_to_video/client.py +151 -0
  62. magic_hour/resources/v1/video_projects/README.md +8 -0
  63. magic_hour/resources/v1/video_projects/__init__.py +10 -2
  64. magic_hour/resources/v1/video_projects/client.py +137 -0
  65. magic_hour/resources/v1/video_projects/client_test.py +527 -0
  66. magic_hour/resources/v1/video_to_video/README.md +98 -10
  67. magic_hour/resources/v1/video_to_video/client.py +222 -0
  68. magic_hour/types/params/__init__.py +58 -0
  69. magic_hour/types/params/v1_ai_clothes_changer_generate_body_assets.py +33 -0
  70. magic_hour/types/params/v1_ai_face_editor_generate_body_assets.py +17 -0
  71. magic_hour/types/params/v1_ai_headshot_generator_generate_body_assets.py +17 -0
  72. magic_hour/types/params/v1_ai_image_editor_generate_body_assets.py +17 -0
  73. magic_hour/types/params/v1_ai_image_upscaler_generate_body_assets.py +17 -0
  74. magic_hour/types/params/v1_ai_photo_editor_generate_body_assets.py +17 -0
  75. magic_hour/types/params/v1_ai_talking_photo_generate_body_assets.py +26 -0
  76. magic_hour/types/params/v1_animation_generate_body_assets.py +39 -0
  77. magic_hour/types/params/v1_auto_subtitle_generator_generate_body_assets.py +17 -0
  78. magic_hour/types/params/v1_face_detection_generate_body_assets.py +17 -0
  79. magic_hour/types/params/v1_face_swap_create_body.py +12 -0
  80. magic_hour/types/params/v1_face_swap_create_body_style.py +33 -0
  81. magic_hour/types/params/v1_face_swap_generate_body_assets.py +56 -0
  82. magic_hour/types/params/v1_face_swap_generate_body_assets_face_mappings_item.py +25 -0
  83. magic_hour/types/params/v1_face_swap_photo_generate_body_assets.py +47 -0
  84. magic_hour/types/params/v1_face_swap_photo_generate_body_assets_face_mappings_item.py +25 -0
  85. magic_hour/types/params/v1_image_background_remover_generate_body_assets.py +27 -0
  86. magic_hour/types/params/v1_image_to_video_generate_body_assets.py +17 -0
  87. magic_hour/types/params/v1_lip_sync_generate_body_assets.py +36 -0
  88. magic_hour/types/params/v1_photo_colorizer_generate_body_assets.py +17 -0
  89. magic_hour/types/params/v1_video_to_video_generate_body_assets.py +27 -0
  90. magic_hour-0.36.0.dist-info/METADATA +303 -0
  91. {magic_hour-0.35.0.dist-info → magic_hour-0.36.0.dist-info}/RECORD +93 -65
  92. magic_hour-0.35.0.dist-info/METADATA +0 -166
  93. {magic_hour-0.35.0.dist-info → magic_hour-0.36.0.dist-info}/LICENSE +0 -0
  94. {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
  *,