magic_hour 0.34.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 (97) 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 -12
  41. magic_hour/resources/v1/face_swap/client.py +262 -28
  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 +210 -8
  56. magic_hour/resources/v1/lip_sync/README.md +87 -13
  57. magic_hour/resources/v1/lip_sync/client.py +230 -28
  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 -14
  67. magic_hour/resources/v1/video_to_video/client.py +242 -28
  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 +24 -14
  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_create_body.py +14 -6
  87. magic_hour/types/params/v1_image_to_video_generate_body_assets.py +17 -0
  88. magic_hour/types/params/v1_lip_sync_create_body.py +12 -14
  89. magic_hour/types/params/v1_lip_sync_generate_body_assets.py +36 -0
  90. magic_hour/types/params/v1_photo_colorizer_generate_body_assets.py +17 -0
  91. magic_hour/types/params/v1_video_to_video_create_body.py +12 -14
  92. magic_hour/types/params/v1_video_to_video_generate_body_assets.py +27 -0
  93. magic_hour-0.36.0.dist-info/METADATA +303 -0
  94. {magic_hour-0.34.0.dist-info → magic_hour-0.36.0.dist-info}/RECORD +96 -68
  95. magic_hour-0.34.0.dist-info/METADATA +0 -166
  96. {magic_hour-0.34.0.dist-info → magic_hour-0.36.0.dist-info}/LICENSE +0 -0
  97. {magic_hour-0.34.0.dist-info → magic_hour-0.36.0.dist-info}/WHEEL +0 -0
@@ -1,3 +1,66 @@
1
+ # v1_image_to_video
2
+
3
+ ## Module Functions
4
+
5
+ <!-- CUSTOM DOCS START -->
6
+
7
+ ### Image To Video 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.image_to_video.generate(
35
+ assets={"image_file_path": "/path/to/1234.png"},
36
+ end_seconds=5.0,
37
+ name="Image To Video video",
38
+ resolution="720p",
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.image_to_video.generate(
53
+ assets={"image_file_path": "/path/to/1234.png"},
54
+ end_seconds=5.0,
55
+ name="Image To Video video",
56
+ resolution="720p",
57
+ wait_for_completion=True,
58
+ download_outputs=True,
59
+ download_directory="outputs"
60
+ )
61
+ ```
62
+
63
+ <!-- CUSTOM DOCS END -->
1
64
 
2
65
  ### Image-to-Video <a name="create"></a>
3
66
 
@@ -10,15 +73,19 @@ Get more information about this mode at our [product page](https://magichour.ai/
10
73
 
11
74
  #### Parameters
12
75
 
13
- | Parameter | Required | Description | Example |
14
- |-----------|:--------:|-------------|--------|
15
- | `assets` | ✓ | Provide the assets for image-to-video. | `{"image_file_path": "api-assets/id/1234.png"}` |
16
- | `end_seconds` | ✓ | The total duration of the output video in seconds. | `5.0` |
17
- | `height` | | This field does not affect the output video's resolution. The video's orientation will match that of the input image. It is retained solely for backward compatibility and will be deprecated in the future. | `123` |
18
- | `name` | ✗ | The name of video. This value is mainly used for your own identification of the video. | `"Image To Video video"` |
19
- | `resolution` | ✗ | Controls the output video resolution. Defaults to `720p` if not specified. 480p and 720p are available on Creator, Pro, or Business tiers. However, 1080p require Pro or Business tier. **Options:** - `480p` - Supports only 5 or 10 second videos. Output: 24fps. Cost: 120 credits per 5 seconds. - `720p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 300 credits per 5 seconds. - `1080p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 600 credits per 5 seconds. | `"720p"` |
20
- | `style` | ✗ | Attributed used to dictate the style of the output | `{"prompt": "a dog running"}` |
21
- | `width` | ✗ | This field does not affect the output video's resolution. The video's orientation will match that of the input image. It is retained solely for backward compatibility and will be deprecated in the future. | `123` |
76
+ | Parameter | Required | Deprecated | Description | Example |
77
+ |-----------|:--------:|:----------:|-------------|--------|
78
+ | `assets` | ✓ | ✗ | Provide the assets for image-to-video. | `{"image_file_path": "api-assets/id/1234.png"}` |
79
+ | `└─ image_file_path` | ✓ | — | The path of the image file. 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"` |
80
+ | `end_seconds` | | | The total duration of the output video in seconds. | `5.0` |
81
+ | `height` | ✗ | ✓ | `height` is deprecated and no longer influences the output video's resolution. Output resolution is determined by the **minimum** of: - The resolution of the input video - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details. This field is retained only for backward compatibility and will be removed in a future release. | `123` |
82
+ | `name` | ✗ | | The name of video. This value is mainly used for your own identification of the video. | `"Image To Video video"` |
83
+ | `resolution` | ✗ | | Controls the output video resolution. Defaults to `720p` if not specified. 480p and 720p are available on Creator, Pro, or Business tiers. However, 1080p require Pro or Business tier. **Options:** - `480p` - Supports only 5 or 10 second videos. Output: 24fps. Cost: 120 credits per 5 seconds. - `720p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 300 credits per 5 seconds. - `1080p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 600 credits per 5 seconds. | `"720p"` |
84
+ | `style` | ✗ | | Attributed used to dictate the style of the output | `{"prompt": "a dog running"}` |
85
+ | `└─ high_quality` | ✗ | ✓ | Deprecated: Please use `resolution` instead. For backward compatibility, * `false` maps to 720p resolution * `true` maps to 1080p resolution This field will be removed in a future version. Use the `resolution` field to directly specify the resolution. | `True` |
86
+ | `└─ prompt` | ✗ | — | The prompt used for the video. | `"a dog running"` |
87
+ | `└─ quality_mode` | ✗ | ✓ | DEPRECATED: Please use `resolution` field instead. For backward compatibility: * `quick` maps to 720p resolution * `studio` maps to 1080p resolution This field will be removed in a future version. Use the `resolution` field to directly to specify the resolution. | `"quick"` |
88
+ | `width` | ✗ | ✓ | `width` is deprecated and no longer influences the output video's resolution. Output resolution is determined by the **minimum** of: - The resolution of the input video - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details. This field is retained only for backward compatibility and will be removed in a future release. | `123` |
22
89
 
23
90
  #### Synchronous Client
24
91
 
@@ -59,3 +126,4 @@ res = await client.v1.image_to_video.create(
59
126
 
60
127
  ##### Example
61
128
  `{"credits_charged": 450, "estimated_frame_cost": 450, "id": "cuid-example"}`
129
+
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import typing
2
3
  import typing_extensions
3
4
 
@@ -9,13 +10,110 @@ from magic_hour.core import (
9
10
  to_encodable,
10
11
  type_utils,
11
12
  )
13
+ from magic_hour.resources.v1.files.client import AsyncFilesClient, FilesClient
14
+ from magic_hour.resources.v1.video_projects.client import (
15
+ AsyncVideoProjectsClient,
16
+ VideoProjectsClient,
17
+ )
12
18
  from magic_hour.types import models, params
13
19
 
14
20
 
21
+ logging.basicConfig(level=logging.INFO)
22
+ logger = logging.getLogger(__name__)
23
+
24
+
15
25
  class ImageToVideoClient:
16
26
  def __init__(self, *, base_client: SyncBaseClient):
17
27
  self._base_client = base_client
18
28
 
29
+ def generate(
30
+ self,
31
+ *,
32
+ assets: params.V1ImageToVideoGenerateBodyAssets,
33
+ end_seconds: float,
34
+ height: typing.Union[
35
+ typing.Optional[int], type_utils.NotGiven
36
+ ] = type_utils.NOT_GIVEN,
37
+ name: typing.Union[
38
+ typing.Optional[str], type_utils.NotGiven
39
+ ] = type_utils.NOT_GIVEN,
40
+ resolution: typing.Union[
41
+ typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]],
42
+ type_utils.NotGiven,
43
+ ] = type_utils.NOT_GIVEN,
44
+ style: typing.Union[
45
+ typing.Optional[params.V1ImageToVideoCreateBodyStyle], type_utils.NotGiven
46
+ ] = type_utils.NOT_GIVEN,
47
+ width: typing.Union[
48
+ typing.Optional[int], type_utils.NotGiven
49
+ ] = type_utils.NOT_GIVEN,
50
+ wait_for_completion: bool = True,
51
+ download_outputs: bool = True,
52
+ download_directory: typing.Optional[str] = None,
53
+ request_options: typing.Optional[RequestOptions] = None,
54
+ ):
55
+ """
56
+ Generate image-to-video (alias for create with additional functionality).
57
+
58
+ Create a Image To Video video. The estimated frame cost is calculated using 30 FPS. This amount is deducted from your account balance when a video is queued. Once the video is complete, the cost will be updated based on the actual number of frames rendered.
59
+
60
+ Args:
61
+ height: `height` is deprecated and no longer influences the output video's resolution.
62
+ name: The name of video. This value is mainly used for your own identification of the video.
63
+ resolution: Controls the output video resolution. Defaults to `720p` if not specified.
64
+ style: Attributed used to dictate the style of the output
65
+ width: `width` is deprecated and no longer influences the output video's resolution.
66
+ assets: Provide the assets for image-to-video.
67
+ end_seconds: The total duration of the output video in seconds.
68
+ wait_for_completion: Whether to wait for the video project to complete
69
+ download_outputs: Whether to download the outputs
70
+ download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
71
+ request_options: Additional options to customize the HTTP request
72
+
73
+ Returns:
74
+ V1VideoProjectsGetResponseWithDownloads: The response from the Image-to-Video API with the downloaded paths if `download_outputs` is True.
75
+
76
+ Examples:
77
+ ```py
78
+ response = client.v1.image_to_video.generate(
79
+ assets={"image_file_path": "path/to/image.png"},
80
+ end_seconds=5.0,
81
+ resolution="720p",
82
+ wait_for_completion=True,
83
+ download_outputs=True,
84
+ download_directory="outputs/",
85
+ )
86
+ ```
87
+ """
88
+
89
+ file_client = FilesClient(base_client=self._base_client)
90
+
91
+ # Upload image file
92
+ image_file_path = assets["image_file_path"]
93
+ assets["image_file_path"] = file_client.upload_file(file=image_file_path)
94
+
95
+ create_response = self.create(
96
+ assets=assets,
97
+ end_seconds=end_seconds,
98
+ height=height,
99
+ name=name,
100
+ resolution=resolution,
101
+ style=style,
102
+ width=width,
103
+ request_options=request_options,
104
+ )
105
+ logger.info(f"Image-to-Video response: {create_response}")
106
+
107
+ video_projects_client = VideoProjectsClient(base_client=self._base_client)
108
+ response = video_projects_client.check_result(
109
+ id=create_response.id,
110
+ wait_for_completion=wait_for_completion,
111
+ download_outputs=download_outputs,
112
+ download_directory=download_directory,
113
+ )
114
+
115
+ return response
116
+
19
117
  def create(
20
118
  self,
21
119
  *,
@@ -50,9 +148,13 @@ class ImageToVideoClient:
50
148
  POST /v1/image-to-video
51
149
 
52
150
  Args:
53
- height: This field does not affect the output video's resolution. The video's orientation will match that of the input image.
151
+ height: `height` is deprecated and no longer influences the output video's resolution.
152
+
153
+ Output resolution is determined by the **minimum** of:
154
+ - The resolution of the input video
155
+ - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details.
54
156
 
55
- It is retained solely for backward compatibility and will be deprecated in the future.
157
+ This field is retained only for backward compatibility and will be removed in a future release.
56
158
  name: The name of video. This value is mainly used for your own identification of the video.
57
159
  resolution: Controls the output video resolution. Defaults to `720p` if not specified.
58
160
 
@@ -63,9 +165,13 @@ class ImageToVideoClient:
63
165
  - `720p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 300 credits per 5 seconds.
64
166
  - `1080p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 600 credits per 5 seconds.
65
167
  style: Attributed used to dictate the style of the output
66
- width: This field does not affect the output video's resolution. The video's orientation will match that of the input image.
168
+ width: `width` is deprecated and no longer influences the output video's resolution.
67
169
 
68
- It is retained solely for backward compatibility and will be deprecated in the future.
170
+ Output resolution is determined by the **minimum** of:
171
+ - The resolution of the input video
172
+ - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details.
173
+
174
+ This field is retained only for backward compatibility and will be removed in a future release.
69
175
  assets: Provide the assets for image-to-video.
70
176
  end_seconds: The total duration of the output video in seconds.
71
177
  request_options: Additional options to customize the HTTP request
@@ -113,6 +219,94 @@ class AsyncImageToVideoClient:
113
219
  def __init__(self, *, base_client: AsyncBaseClient):
114
220
  self._base_client = base_client
115
221
 
222
+ async def generate(
223
+ self,
224
+ *,
225
+ assets: params.V1ImageToVideoGenerateBodyAssets,
226
+ end_seconds: float,
227
+ height: typing.Union[
228
+ typing.Optional[int], type_utils.NotGiven
229
+ ] = type_utils.NOT_GIVEN,
230
+ name: typing.Union[
231
+ typing.Optional[str], type_utils.NotGiven
232
+ ] = type_utils.NOT_GIVEN,
233
+ resolution: typing.Union[
234
+ typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]],
235
+ type_utils.NotGiven,
236
+ ] = type_utils.NOT_GIVEN,
237
+ style: typing.Union[
238
+ typing.Optional[params.V1ImageToVideoCreateBodyStyle], type_utils.NotGiven
239
+ ] = type_utils.NOT_GIVEN,
240
+ width: typing.Union[
241
+ typing.Optional[int], type_utils.NotGiven
242
+ ] = type_utils.NOT_GIVEN,
243
+ wait_for_completion: bool = True,
244
+ download_outputs: bool = True,
245
+ download_directory: typing.Optional[str] = None,
246
+ request_options: typing.Optional[RequestOptions] = None,
247
+ ):
248
+ """
249
+ Generate image-to-video (alias for create with additional functionality).
250
+
251
+ Create a Image To Video video. The estimated frame cost is calculated using 30 FPS. This amount is deducted from your account balance when a video is queued. Once the video is complete, the cost will be updated based on the actual number of frames rendered.
252
+
253
+ Args:
254
+ height: `height` is deprecated and no longer influences the output video's resolution.
255
+ name: The name of video. This value is mainly used for your own identification of the video.
256
+ resolution: Controls the output video resolution. Defaults to `720p` if not specified.
257
+ style: Attributed used to dictate the style of the output
258
+ width: `width` is deprecated and no longer influences the output video's resolution.
259
+ assets: Provide the assets for image-to-video.
260
+ end_seconds: The total duration of the output video in seconds.
261
+ wait_for_completion: Whether to wait for the video project to complete
262
+ download_outputs: Whether to download the outputs
263
+ download_directory: The directory to download the outputs to. If not provided, the outputs will be downloaded to the current working directory
264
+ request_options: Additional options to customize the HTTP request
265
+
266
+ Returns:
267
+ V1VideoProjectsGetResponseWithDownloads: The response from the Image-to-Video API with the downloaded paths if `download_outputs` is True.
268
+
269
+ Examples:
270
+ ```py
271
+ response = await client.v1.image_to_video.generate(
272
+ assets={"image_file_path": "path/to/image.png"},
273
+ end_seconds=5.0,
274
+ resolution="720p",
275
+ wait_for_completion=True,
276
+ download_outputs=True,
277
+ download_directory="outputs/",
278
+ )
279
+ ```
280
+ """
281
+
282
+ file_client = AsyncFilesClient(base_client=self._base_client)
283
+
284
+ # Upload image file
285
+ image_file_path = assets["image_file_path"]
286
+ assets["image_file_path"] = await file_client.upload_file(file=image_file_path)
287
+
288
+ create_response = await self.create(
289
+ assets=assets,
290
+ end_seconds=end_seconds,
291
+ height=height,
292
+ name=name,
293
+ resolution=resolution,
294
+ style=style,
295
+ width=width,
296
+ request_options=request_options,
297
+ )
298
+ logger.info(f"Image-to-Video response: {create_response}")
299
+
300
+ video_projects_client = AsyncVideoProjectsClient(base_client=self._base_client)
301
+ response = await video_projects_client.check_result(
302
+ id=create_response.id,
303
+ wait_for_completion=wait_for_completion,
304
+ download_outputs=download_outputs,
305
+ download_directory=download_directory,
306
+ )
307
+
308
+ return response
309
+
116
310
  async def create(
117
311
  self,
118
312
  *,
@@ -147,9 +341,13 @@ class AsyncImageToVideoClient:
147
341
  POST /v1/image-to-video
148
342
 
149
343
  Args:
150
- height: This field does not affect the output video's resolution. The video's orientation will match that of the input image.
344
+ height: `height` is deprecated and no longer influences the output video's resolution.
345
+
346
+ Output resolution is determined by the **minimum** of:
347
+ - The resolution of the input video
348
+ - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details.
151
349
 
152
- It is retained solely for backward compatibility and will be deprecated in the future.
350
+ This field is retained only for backward compatibility and will be removed in a future release.
153
351
  name: The name of video. This value is mainly used for your own identification of the video.
154
352
  resolution: Controls the output video resolution. Defaults to `720p` if not specified.
155
353
 
@@ -160,9 +358,13 @@ class AsyncImageToVideoClient:
160
358
  - `720p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 300 credits per 5 seconds.
161
359
  - `1080p` - Supports videos between 5-60 seconds. Output: 30fps. Cost: 600 credits per 5 seconds.
162
360
  style: Attributed used to dictate the style of the output
163
- width: This field does not affect the output video's resolution. The video's orientation will match that of the input image.
361
+ width: `width` is deprecated and no longer influences the output video's resolution.
362
+
363
+ Output resolution is determined by the **minimum** of:
364
+ - The resolution of the input video
365
+ - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details.
164
366
 
165
- It is retained solely for backward compatibility and will be deprecated in the future.
367
+ This field is retained only for backward compatibility and will be removed in a future release.
166
368
  assets: Provide the assets for image-to-video.
167
369
  end_seconds: The total duration of the output video in seconds.
168
370
  request_options: Additional options to customize the HTTP request
@@ -1,3 +1,76 @@
1
+ # v1_lip_sync
2
+
3
+ ## Module Functions
4
+
5
+ <!-- CUSTOM DOCS START -->
6
+
7
+ ### Lip Sync 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.lip_sync.generate(
35
+ assets={
36
+ "audio_file_path": "/path/to/1234.mp3",
37
+ "video_file_path": "/path/to/1234.mp4",
38
+ "video_source": "file",
39
+ },
40
+ end_seconds=15.0,
41
+ start_seconds=0.0,
42
+ max_fps_limit=12.0,
43
+ name="Lip Sync video",
44
+ wait_for_completion=True,
45
+ download_outputs=True,
46
+ download_directory="outputs"
47
+ )
48
+ ```
49
+
50
+ #### Asynchronous Client
51
+
52
+ ```python
53
+ from magic_hour import AsyncClient
54
+ from os import getenv
55
+
56
+ client = AsyncClient(token=getenv("API_TOKEN"))
57
+ res = await client.v1.lip_sync.generate(
58
+ assets={
59
+ "audio_file_path": "/path/to/1234.mp3",
60
+ "video_file_path": "/path/to/1234.mp4",
61
+ "video_source": "file",
62
+ },
63
+ end_seconds=15.0,
64
+ start_seconds=0.0,
65
+ max_fps_limit=12.0,
66
+ name="Lip Sync video",
67
+ wait_for_completion=True,
68
+ download_outputs=True,
69
+ download_directory="outputs"
70
+ )
71
+ ```
72
+
73
+ <!-- CUSTOM DOCS END -->
1
74
 
2
75
  ### Lip Sync <a name="create"></a>
3
76
 
@@ -10,15 +83,19 @@ Get more information about this mode at our [product page](https://magichour.ai/
10
83
 
11
84
  #### Parameters
12
85
 
13
- | Parameter | Required | Description | Example |
14
- |-----------|:--------:|-------------|--------|
15
- | `assets` | ✓ | Provide the assets for lip-sync. For video, The `video_source` field determines whether `video_file_path` or `youtube_url` field is used | `{"audio_file_path": "api-assets/id/1234.mp3", "video_file_path": "api-assets/id/1234.mp4", "video_source": "file"}` |
16
- | `end_seconds` | ✓ | The end time of the input video in seconds. This value is used to trim the input video. The value must be greater than 0.1, and more than the start_seconds. | `15.0` |
17
- | `start_seconds` | | The start time of the input video in seconds. This value is used to trim the input video. The value must be greater than 0. | `0.0` |
18
- | `height` | | Used to determine the dimensions of the output video. * If height is provided, width will also be required. The larger value between width and height will be used to determine the maximum output resolution while maintaining the original aspect ratio. * If both height and width are omitted, the video will be resized according to your subscription's maximum resolution, while preserving aspect ratio. Note: if the video's original resolution is less than the maximum, the video will not be resized. See our [pricing page](https://magichour.ai/pricing) for more details. | `960` |
19
- | `max_fps_limit` | ✗ | Defines the maximum FPS (frames per second) for the output video. If the input video's FPS is lower than this limit, the output video will retain the input FPS. This is useful for reducing unnecessary frame usage in scenarios where high FPS is not required. | `12.0` |
20
- | `name` | ✗ | The name of video. This value is mainly used for your own identification of the video. | `"Lip Sync video"` |
21
- | `width` | | Used to determine the dimensions of the output video. * If width is provided, height will also be required. The larger value between width and height will be used to determine the maximum output resolution while maintaining the original aspect ratio. * If both height and width are omitted, the video will be resized according to your subscription's maximum resolution, while preserving aspect ratio. Note: if the video's original resolution is less than the maximum, the video will not be resized. See our [pricing page](https://magichour.ai/pricing) for more details. | `512` |
86
+ | Parameter | Required | Deprecated | Description | Example |
87
+ |-----------|:--------:|:----------:|-------------|--------|
88
+ | `assets` | ✓ | ✗ | Provide the assets for lip-sync. For video, The `video_source` field determines whether `video_file_path` or `youtube_url` field is used | `{"audio_file_path": "api-assets/id/1234.mp3", "video_file_path": "api-assets/id/1234.mp4", "video_source": "file"}` |
89
+ | `└─ audio_file_path` | ✓ | — | The path of the audio file. 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.mp3"` |
90
+ | `└─ video_file_path` | | | Required if `video_source` is `file`. 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.mp4"` |
91
+ | `└─ video_source` | | | | `"file"` |
92
+ | `└─ youtube_url` | ✗ | | Using a youtube video as the input source. This field is required if `video_source` is `youtube` | `"http://www.example.com"` |
93
+ | `end_seconds` | ✓ | ✗ | The end time of the input video in seconds. This value is used to trim the input video. The value must be greater than 0.1, and more than the start_seconds. | `15.0` |
94
+ | `start_seconds` | | | The start time of the input video in seconds. This value is used to trim the input video. The value must be greater than 0. | `0.0` |
95
+ | `height` | ✗ | ✓ | `height` is deprecated and no longer influences the output video's resolution. Output resolution is determined by the **minimum** of: - The resolution of the input video - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details. This field is retained only for backward compatibility and will be removed in a future release. | `123` |
96
+ | `max_fps_limit` | ✗ | ✗ | Defines the maximum FPS (frames per second) for the output video. If the input video's FPS is lower than this limit, the output video will retain the input FPS. This is useful for reducing unnecessary frame usage in scenarios where high FPS is not required. | `12.0` |
97
+ | `name` | ✗ | ✗ | The name of video. This value is mainly used for your own identification of the video. | `"Lip Sync video"` |
98
+ | `width` | ✗ | ✓ | `width` is deprecated and no longer influences the output video's resolution. Output resolution is determined by the **minimum** of: - The resolution of the input video - The maximum resolution allowed by your subscription tier. See our [pricing page](https://magichour.ai/pricing) for more details. This field is retained only for backward compatibility and will be removed in a future release. | `123` |
22
99
 
23
100
  #### Synchronous Client
24
101
 
@@ -35,10 +112,8 @@ res = client.v1.lip_sync.create(
35
112
  },
36
113
  end_seconds=15.0,
37
114
  start_seconds=0.0,
38
- height=960,
39
115
  max_fps_limit=12.0,
40
116
  name="Lip Sync video",
41
- width=512,
42
117
  )
43
118
 
44
119
  ```
@@ -58,10 +133,8 @@ res = await client.v1.lip_sync.create(
58
133
  },
59
134
  end_seconds=15.0,
60
135
  start_seconds=0.0,
61
- height=960,
62
136
  max_fps_limit=12.0,
63
137
  name="Lip Sync video",
64
- width=512,
65
138
  )
66
139
 
67
140
  ```
@@ -73,3 +146,4 @@ res = await client.v1.lip_sync.create(
73
146
 
74
147
  ##### Example
75
148
  `{"credits_charged": 450, "estimated_frame_cost": 450, "id": "cuid-example"}`
149
+