diff --git a/.sdk.json b/.sdk.json index a536e2c..a5ef48d 100644 --- a/.sdk.json +++ b/.sdk.json @@ -1,5 +1,5 @@ { - "id": "adf522eb-8026-4017-8244-0e110c2d9aff", + "id": "df69834c-08cc-4981-8694-57b835dbc30e", "tracked_paths": [ { "editable": true, @@ -161,6 +161,18 @@ "editable": true, "path": "magic_hour/resources/v1/ai_talking_photo/client.py" }, + { + "editable": true, + "path": "magic_hour/resources/v1/ai_ugc_ad/README.md" + }, + { + "editable": true, + "path": "magic_hour/resources/v1/ai_ugc_ad/__init__.py" + }, + { + "editable": true, + "path": "magic_hour/resources/v1/ai_ugc_ad/client.py" + }, { "editable": true, "path": "magic_hour/resources/v1/ai_video_editor/README.md" @@ -525,6 +537,10 @@ "editable": false, "path": "magic_hour/types/models/v1_ai_talking_photo_create_response.py" }, + { + "editable": false, + "path": "magic_hour/types/models/v1_ai_ugc_ad_create_response.py" + }, { "editable": false, "path": "magic_hour/types/models/v1_ai_video_editor_create_response.py" @@ -773,6 +789,14 @@ "editable": false, "path": "magic_hour/types/params/v1_ai_talking_photo_create_body_style.py" }, + { + "editable": false, + "path": "magic_hour/types/params/v1_ai_ugc_ad_create_body.py" + }, + { + "editable": false, + "path": "magic_hour/types/params/v1_ai_ugc_ad_create_body_assets.py" + }, { "editable": false, "path": "magic_hour/types/params/v1_ai_video_editor_create_body.py" @@ -1041,6 +1065,10 @@ "editable": false, "path": "tests/test_v1_ai_talking_photo_client.py" }, + { + "editable": false, + "path": "tests/test_v1_ai_ugc_ad_client.py" + }, { "editable": false, "path": "tests/test_v1_ai_video_editor_client.py" diff --git a/README.md b/README.md index ba805ce..fb7c9ec 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,10 @@ download_urls = result.downloads - [create](magic_hour/resources/v1/ai_talking_photo/README.md#create) - AI Talking Photo - [generate](magic_hour/resources/v1/ai_talking_photo/README.md#generate) - Ai Talking Photo Generate Workflow +### [v1.ai_ugc_ad](magic_hour/resources/v1/ai_ugc_ad/README.md) + +- [create](magic_hour/resources/v1/ai_ugc_ad/README.md#create) - AI UGC Ad Generator + ### [v1.ai_video_editor](magic_hour/resources/v1/ai_video_editor/README.md) - [create](magic_hour/resources/v1/ai_video_editor/README.md#create) - AI Video Editor diff --git a/magic_hour/README.md b/magic_hour/README.md index b838b76..de75fab 100644 --- a/magic_hour/README.md +++ b/magic_hour/README.md @@ -13,6 +13,7 @@ - [ai_meme_generator](resources/v1/ai_meme_generator/README.md) - ai_meme_generator - [ai_qr_code_generator](resources/v1/ai_qr_code_generator/README.md) - ai_qr_code_generator - [ai_talking_photo](resources/v1/ai_talking_photo/README.md) - ai_talking_photo +- [ai_ugc_ad](resources/v1/ai_ugc_ad/README.md) - ai_ugc_ad - [ai_video_editor](resources/v1/ai_video_editor/README.md) - ai_video_editor - [ai_video_translator](resources/v1/ai_video_translator/README.md) - ai_video_translator - [ai_voice_cloner](resources/v1/ai_voice_cloner/README.md) - ai_voice_cloner diff --git a/magic_hour/environment.py b/magic_hour/environment.py index 9f8dbc7..577c01c 100644 --- a/magic_hour/environment.py +++ b/magic_hour/environment.py @@ -6,7 +6,7 @@ class Environment(enum.Enum): """Pre-defined base URLs for the API""" ENVIRONMENT = "https://api.magichour.ai" - MOCK_SERVER = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.87.1" + MOCK_SERVER = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.88.0" def _get_base_url( diff --git a/magic_hour/resources/v1/README.md b/magic_hour/resources/v1/README.md index dbd4948..3888bb1 100644 --- a/magic_hour/resources/v1/README.md +++ b/magic_hour/resources/v1/README.md @@ -13,6 +13,7 @@ - [ai_meme_generator](ai_meme_generator/README.md) - ai_meme_generator - [ai_qr_code_generator](ai_qr_code_generator/README.md) - ai_qr_code_generator - [ai_talking_photo](ai_talking_photo/README.md) - ai_talking_photo +- [ai_ugc_ad](ai_ugc_ad/README.md) - ai_ugc_ad - [ai_video_editor](ai_video_editor/README.md) - ai_video_editor - [ai_video_translator](ai_video_translator/README.md) - ai_video_translator - [ai_voice_cloner](ai_voice_cloner/README.md) - ai_voice_cloner diff --git a/magic_hour/resources/v1/ai_talking_photo/README.md b/magic_hour/resources/v1/ai_talking_photo/README.md index 0f3cc58..c640ae1 100644 --- a/magic_hour/resources/v1/ai_talking_photo/README.md +++ b/magic_hour/resources/v1/ai_talking_photo/README.md @@ -76,19 +76,20 @@ Create a talking photo video from an image and an audio file. #### Parameters -| Parameter | Required | Description | Example | -| -------------------- | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `assets` | ✓ | Provide the assets for creating a talking photo | `{"audio_file_path": "api-assets/id/1234.mp3", "image_file_path": "api-assets/id/1234.png"}` | -| `└─ audio_file_path` | ✓ | The audio file to sync with the image. 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/1234.mp3"` | -| `└─ image_file_path` | ✓ | The source image to animate. 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/1234.png"` | -| `end_seconds` | ✓ | The end time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. | `5.0` | -| `start_seconds` | ✓ | The start time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. | `0.0` | -| `max_resolution` | ✗ | Constrains the larger dimension (height or width) of the output video. Allows you to set a lower resolution than your plan's maximum if desired. The value is capped by your plan's max resolution. | `512` | -| `name` | ✗ | Give your video a custom name for easy identification. | `"My Talking Photo video"` | -| `style` | ✗ | Attributes used to dictate the style of the output | `{"generation_mode": "realistic", "prompt": "A person smiling and speaking naturally to the camera"}` | -| `└─ generation_mode` | ✗ | Controls overall motion style. * `realistic` - Maintains likeness well, high quality, and reliable. * `prompted` - Slightly lower likeness; allows option to prompt scene. **Deprecated values (maintained for backward compatibility):** * `pro` - Deprecated: use `realistic` * `standard` - Deprecated: use `prompted` * `stable` - Deprecated: use `realistic` * `expressive` - Deprecated: use `prompted` | `"realistic"` | -| `└─ intensity` | ✗ | Note: this value is only applicable when generation_mode is `expressive`. The value can include up to 2 decimal places. * Lower values yield more stability but can suppress mouth movement. * Higher values increase motion and expressiveness, with a higher risk of distortion. | `123.0` | -| `└─ prompt` | ✗ | A text prompt to guide the generation. Only applicable when generation_mode is `prompted`. This field is ignored for other modes. | `"A person smiling and speaking naturally to the camera"` | +| Parameter | Required | Deprecated | Description | Example | +| -------------------- | :------: | :--------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `assets` | ✓ | ✗ | Provide the assets for creating a talking photo | `{"audio_file_path": "api-assets/id/1234.mp3", "image_file_path": "api-assets/id/1234.png"}` | +| `└─ audio_file_path` | ✓ | — | The audio file to sync with the image. 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/1234.mp3"` | +| `└─ image_file_path` | ✓ | — | The source image to animate. 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/1234.png"` | +| `end_seconds` | ✓ | ✗ | The end time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. | `5.0` | +| `start_seconds` | ✓ | ✗ | The start time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. | `0.0` | +| `max_resolution` | ✗ | ✓ | Deprecated: use `resolution`. Still accepted as a larger-dimension cap, limited by your plan. Ignored when `resolution` is provided. After plan capping: * Below 1280 maps to `480p` (intermediate values round down). * 1280 or above maps to `720p`. | `123` | +| `name` | ✗ | ✗ | Give your video a custom name for easy identification. | `"My Talking Photo video"` | +| `resolution` | ✗ | ✗ | Output preset. Overrides `max_resolution`. Defaults to 480p in prompted mode; realistic mode uses the mapped plan maximum. | `"480p"` | +| `style` | ✗ | ✗ | Attributes used to dictate the style of the output | `{"generation_mode": "realistic", "prompt": "A person smiling and speaking naturally to the camera"}` | +| `└─ generation_mode` | ✗ | — | Controls overall motion style. * `realistic` - Maintains likeness well, high quality, and reliable. * `prompted` - Slightly lower likeness; allows option to prompt scene. **Deprecated values (maintained for backward compatibility):** * `pro` - Deprecated: use `realistic` * `standard` - Deprecated: use `prompted` * `stable` - Deprecated: use `realistic` * `expressive` - Deprecated: use `prompted` | `"realistic"` | +| `└─ intensity` | ✗ | ✓ | Note: this value is only applicable when generation_mode is `expressive`. The value can include up to 2 decimal places. * Lower values yield more stability but can suppress mouth movement. * Higher values increase motion and expressiveness, with a higher risk of distortion. | `123.0` | +| `└─ prompt` | ✗ | — | A text prompt to guide the generation. Only applicable when generation_mode is `prompted`. This field is ignored for other modes. | `"A person smiling and speaking naturally to the camera"` | #### Synchronous Client @@ -104,8 +105,8 @@ res = client.v1.ai_talking_photo.create( }, end_seconds=5.0, start_seconds=0.0, - max_resolution=512, name="My Talking Photo video", + resolution="480p", ) ``` @@ -123,8 +124,8 @@ res = await client.v1.ai_talking_photo.create( }, end_seconds=5.0, start_seconds=0.0, - max_resolution=512, name="My Talking Photo video", + resolution="480p", ) ``` diff --git a/magic_hour/resources/v1/ai_talking_photo/client.py b/magic_hour/resources/v1/ai_talking_photo/client.py index e00d317..d1c4bc9 100644 --- a/magic_hour/resources/v1/ai_talking_photo/client.py +++ b/magic_hour/resources/v1/ai_talking_photo/client.py @@ -1,4 +1,5 @@ import typing +import typing_extensions from magic_hour.helpers.logger import get_sdk_logger from magic_hour.resources.v1.files.client import AsyncFilesClient, FilesClient @@ -39,6 +40,10 @@ def generate( style: typing.Union[ typing.Optional[params.V1AiTalkingPhotoCreateBodyStyle], type_utils.NotGiven ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, wait_for_completion: bool = True, download_outputs: bool = True, download_directory: typing.Optional[str] = None, @@ -95,6 +100,7 @@ def generate( max_resolution=max_resolution, name=name, style=style, + resolution=resolution, request_options=request_options, ) logger.info(f"AI Talking Photo response: {create_response}") @@ -121,6 +127,10 @@ def create( name: typing.Union[ typing.Optional[str], type_utils.NotGiven ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, style: typing.Union[ typing.Optional[params.V1AiTalkingPhotoCreateBodyStyle], type_utils.NotGiven ] = type_utils.NOT_GIVEN, @@ -134,8 +144,13 @@ def create( POST /v1/ai-talking-photo Args: - max_resolution: Constrains the larger dimension (height or width) of the output video. Allows you to set a lower resolution than your plan's maximum if desired. The value is capped by your plan's max resolution. + max_resolution: Deprecated: use `resolution`. Still accepted as a larger-dimension cap, limited by your plan. Ignored when `resolution` is provided. + + After plan capping: + * Below 1280 maps to `480p` (intermediate values round down). + * 1280 or above maps to `720p`. name: Give your video a custom name for easy identification. + resolution: Output preset. Overrides `max_resolution`. Defaults to 480p in prompted mode; realistic mode uses the mapped plan maximum. style: Attributes used to dictate the style of the output assets: Provide the assets for creating a talking photo end_seconds: The end time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. @@ -158,8 +173,8 @@ def create( }, end_seconds=5.0, start_seconds=0.0, - max_resolution=512, name="My Talking Photo video", + resolution="480p", ) ``` """ @@ -167,6 +182,7 @@ def create( item={ "max_resolution": max_resolution, "name": name, + "resolution": resolution, "style": style, "assets": assets, "end_seconds": end_seconds, @@ -203,6 +219,10 @@ async def generate( style: typing.Union[ typing.Optional[params.V1AiTalkingPhotoCreateBodyStyle], type_utils.NotGiven ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, wait_for_completion: bool = True, download_outputs: bool = True, download_directory: typing.Optional[str] = None, @@ -259,6 +279,7 @@ async def generate( max_resolution=max_resolution, name=name, style=style, + resolution=resolution, request_options=request_options, ) logger.info(f"AI Talking Photo response: {create_response}") @@ -285,6 +306,10 @@ async def create( name: typing.Union[ typing.Optional[str], type_utils.NotGiven ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, style: typing.Union[ typing.Optional[params.V1AiTalkingPhotoCreateBodyStyle], type_utils.NotGiven ] = type_utils.NOT_GIVEN, @@ -298,8 +323,13 @@ async def create( POST /v1/ai-talking-photo Args: - max_resolution: Constrains the larger dimension (height or width) of the output video. Allows you to set a lower resolution than your plan's maximum if desired. The value is capped by your plan's max resolution. + max_resolution: Deprecated: use `resolution`. Still accepted as a larger-dimension cap, limited by your plan. Ignored when `resolution` is provided. + + After plan capping: + * Below 1280 maps to `480p` (intermediate values round down). + * 1280 or above maps to `720p`. name: Give your video a custom name for easy identification. + resolution: Output preset. Overrides `max_resolution`. Defaults to 480p in prompted mode; realistic mode uses the mapped plan maximum. style: Attributes used to dictate the style of the output assets: Provide the assets for creating a talking photo end_seconds: The end time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. @@ -322,8 +352,8 @@ async def create( }, end_seconds=5.0, start_seconds=0.0, - max_resolution=512, name="My Talking Photo video", + resolution="480p", ) ``` """ @@ -331,6 +361,7 @@ async def create( item={ "max_resolution": max_resolution, "name": name, + "resolution": resolution, "style": style, "assets": assets, "end_seconds": end_seconds, diff --git a/magic_hour/resources/v1/ai_ugc_ad/README.md b/magic_hour/resources/v1/ai_ugc_ad/README.md new file mode 100644 index 0000000..e81203b --- /dev/null +++ b/magic_hour/resources/v1/ai_ugc_ad/README.md @@ -0,0 +1,61 @@ +# v1.ai_ugc_ad + +## Module Functions + +### AI UGC Ad Generator + +Create a spoken UGC video from a prepared image and script. Returns a project ID; poll GET /v1/video-projects/{id} for status and downloads. To compose an image, generate the image separately with the Image Editor API and supply its download URL. + +**API Endpoint**: `POST /v1/ai-ugc-ad` + +#### Parameters + +| Parameter | Required | Description | Example | +| ----------------------- | :------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | +| `assets` | ✓ | | `{"image_file_path": "api-assets/id/image.jpg"}` | +| `└─ image_file_path` | ✓ | Prepared image to animate. 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/image.jpg"` | +| `end_seconds` | ✓ | Video duration in seconds. Supported values by model: * kling-3.0: 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 seconds. * ltx-2.5: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 seconds. * veo3.1: 4, 6, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 120, 127, 134, 141 seconds. Free plans are limited to 5 seconds unless a credit pack has been purchased. | `4.0` | +| `script` | ✓ | The words the actor should speak. Character limits apply after trimming: * kling-3.0: 2500 characters. * ltx-2.5: 1804 characters. * veo3.1: 2500 characters. LTX's dialogue wrapper counts toward its model prompt limit. | `"Meet your new everyday essential."` | +| `additional_properties` | ✗ | | `{}` | +| `model` | ✗ | Defaults to kling-3.0 on paid plans and ltx-2.5 on free plans. | `"kling-3.0"` | +| `resolution` | ✗ | Defaults to 720p on paid plans and 480p on free plans. Unsupported model/resolution combinations and resolutions unavailable for your plan are rejected. | `"1080p"` | + +#### Synchronous Client + +```python +from magic_hour import Client +from os import getenv + +client = Client(token=getenv("API_TOKEN")) +res = client.v1.ai_ugc_ad.create( + assets={"image_file_path": "api-assets/id/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", +) +``` + +#### Asynchronous Client + +```python +from magic_hour import AsyncClient +from os import getenv + +client = AsyncClient(token=getenv("API_TOKEN")) +res = await client.v1.ai_ugc_ad.create( + assets={"image_file_path": "api-assets/id/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", +) +``` + +#### Response + +##### Type + +[V1AiUgcAdCreateResponse](/magic_hour/types/models/v1_ai_ugc_ad_create_response.py) + +##### Example + +```python +{"credits_charged": 450, "estimated_frame_cost": 123, "id": "cuid-example"} +``` diff --git a/magic_hour/resources/v1/ai_ugc_ad/__init__.py b/magic_hour/resources/v1/ai_ugc_ad/__init__.py new file mode 100644 index 0000000..1b1cc01 --- /dev/null +++ b/magic_hour/resources/v1/ai_ugc_ad/__init__.py @@ -0,0 +1,4 @@ +from .client import AiUgcAdClient, AsyncAiUgcAdClient + + +__all__ = ["AiUgcAdClient", "AsyncAiUgcAdClient"] diff --git a/magic_hour/resources/v1/ai_ugc_ad/client.py b/magic_hour/resources/v1/ai_ugc_ad/client.py new file mode 100644 index 0000000..2fad5a7 --- /dev/null +++ b/magic_hour/resources/v1/ai_ugc_ad/client.py @@ -0,0 +1,345 @@ +import typing +import typing_extensions + +from magic_hour.helpers.logger import get_sdk_logger +from magic_hour.resources.v1.files.client import AsyncFilesClient, FilesClient +from magic_hour.resources.v1.video_projects.client import ( + AsyncVideoProjectsClient, + VideoProjectsClient, + V1VideoProjectsGetResponseWithDownloads, +) +from magic_hour.types import models, params +from make_api_request import ( + AsyncBaseClient, + RequestOptions, + SyncBaseClient, + default_request_options, + to_encodable, + type_utils, +) + +logger = get_sdk_logger(__name__) + + +class AiUgcAdClient: + def __init__(self, *, base_client: SyncBaseClient): + self._base_client = base_client + + def generate( + self, + *, + assets: params.V1AiUgcAdGenerateBodyAssets, + end_seconds: float, + script: str, + additional_properties: typing.Union[ + typing.Optional[typing.Dict[str, typing.Any]], type_utils.NotGiven + ] = type_utils.NOT_GIVEN, + model: typing.Union[ + typing.Optional[ + typing_extensions.Literal["kling-3.0", "ltx-2.5", "veo3.1"] + ], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + wait_for_completion: bool = True, + download_outputs: bool = True, + download_directory: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> V1VideoProjectsGetResponseWithDownloads: + """ + Generate a UGC ad with automatic image upload, polling, and downloads. + + Accepts the same parameters as create(). The image may be a local path, + URL, or an existing api-assets path. The prepared image is animated + using the supplied script, model, resolution, and duration. + + Args: + assets: Prepared image to animate. + end_seconds: Video duration in seconds, subject to the model's limits. + script: The words the actor should speak. + additional_properties: Additional properties to include in the request. + model: Generation model. Defaults depend on your plan. + resolution: Output resolution. Defaults depend on your plan. + wait_for_completion: Whether to wait for the video project to complete. + download_outputs: Whether to download completed outputs. + download_directory: Output directory, or the current directory if omitted. + request_options: Additional options to customize the create request. + + Returns: + The video project with downloaded paths when downloads are enabled. + + Examples: + ```py + response = client.v1.ai_ugc_ad.generate( + assets={"image_file_path": "path/to/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", + ) + ``` + """ + file_client = FilesClient(base_client=self._base_client) + uploaded_image = file_client.upload_file(file=assets["image_file_path"]) + create_response = self.create( + assets={**assets, "image_file_path": uploaded_image}, + end_seconds=end_seconds, + script=script, + additional_properties=additional_properties, + model=model, + resolution=resolution, + request_options=request_options, + ) + logger.info(f"AI UGC Ad response: {create_response}") + + video_projects_client = VideoProjectsClient(base_client=self._base_client) + return video_projects_client.check_result( + id=create_response.id, + wait_for_completion=wait_for_completion, + download_outputs=download_outputs, + download_directory=download_directory, + ) + + def create( + self, + *, + assets: params.V1AiUgcAdCreateBodyAssets, + end_seconds: float, + script: str, + additional_properties: typing.Union[ + typing.Optional[typing.Dict[str, typing.Any]], type_utils.NotGiven + ] = type_utils.NOT_GIVEN, + model: typing.Union[ + typing.Optional[ + typing_extensions.Literal["kling-3.0", "ltx-2.5", "veo3.1"] + ], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + request_options: typing.Optional[RequestOptions] = None, + ) -> models.V1AiUgcAdCreateResponse: + """ + AI UGC Ad Generator + + Create a spoken UGC video from a prepared image and script. Returns a project ID; poll GET /v1/video-projects/{id} for status and downloads. To compose an image, generate the image separately with the Image Editor API and supply its download URL. + + POST /v1/ai-ugc-ad + + Args: + additional_properties: typing.Dict[str, typing.Any] + model: Defaults to kling-3.0 on paid plans and ltx-2.5 on free plans. + resolution: Defaults to 720p on paid plans and 480p on free plans. Unsupported model/resolution combinations and resolutions unavailable for your plan are rejected. + assets: V1AiUgcAdCreateBodyAssets + end_seconds: Video duration in seconds. Supported values by model: + * kling-3.0: 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 seconds. + * ltx-2.5: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 seconds. + * veo3.1: 4, 6, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 120, 127, 134, 141 seconds. + Free plans are limited to 5 seconds unless a credit pack has been purchased. + script: The words the actor should speak. Character limits apply after trimming: + * kling-3.0: 2500 characters. + * ltx-2.5: 1804 characters. + * veo3.1: 2500 characters. + LTX's dialogue wrapper counts toward its model prompt limit. + request_options: Additional options to customize the HTTP request + + Returns: + Success + + Raises: + ApiError: A custom exception class that provides additional context + for API errors, including the HTTP status code and response body. + + Examples: + ```py + client.v1.ai_ugc_ad.create( + assets={"image_file_path": "api-assets/id/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", + ) + ``` + """ + _json = to_encodable( + item={ + **(additional_properties or {}), + "model": model, + "resolution": resolution, + "assets": assets, + "end_seconds": end_seconds, + "script": script, + }, + dump_with=params._SerializerV1AiUgcAdCreateBody, + ) + return self._base_client.request( + method="POST", + path="/v1/ai-ugc-ad", + auth_names=["bearerAuth"], + json=_json, + cast_to=models.V1AiUgcAdCreateResponse, + request_options=request_options or default_request_options(), + ) + + +class AsyncAiUgcAdClient: + def __init__(self, *, base_client: AsyncBaseClient): + self._base_client = base_client + + async def generate( + self, + *, + assets: params.V1AiUgcAdGenerateBodyAssets, + end_seconds: float, + script: str, + additional_properties: typing.Union[ + typing.Optional[typing.Dict[str, typing.Any]], type_utils.NotGiven + ] = type_utils.NOT_GIVEN, + model: typing.Union[ + typing.Optional[ + typing_extensions.Literal["kling-3.0", "ltx-2.5", "veo3.1"] + ], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + wait_for_completion: bool = True, + download_outputs: bool = True, + download_directory: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> V1VideoProjectsGetResponseWithDownloads: + """ + Generate a UGC ad with automatic image upload, polling, and downloads. + + Accepts the same parameters as create(). The image may be a local path, + URL, or an existing api-assets path. The prepared image is animated + using the supplied script, model, resolution, and duration. + + Args: + assets: Prepared image to animate. + end_seconds: Video duration in seconds, subject to the model's limits. + script: The words the actor should speak. + additional_properties: Additional properties to include in the request. + model: Generation model. Defaults depend on your plan. + resolution: Output resolution. Defaults depend on your plan. + wait_for_completion: Whether to wait for the video project to complete. + download_outputs: Whether to download completed outputs. + download_directory: Output directory, or the current directory if omitted. + request_options: Additional options to customize the create request. + + Returns: + The video project with downloaded paths when downloads are enabled. + + Examples: + ```py + response = await client.v1.ai_ugc_ad.generate( + assets={"image_file_path": "path/to/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", + ) + ``` + """ + file_client = AsyncFilesClient(base_client=self._base_client) + uploaded_image = await file_client.upload_file(file=assets["image_file_path"]) + create_response = await self.create( + assets={**assets, "image_file_path": uploaded_image}, + end_seconds=end_seconds, + script=script, + additional_properties=additional_properties, + model=model, + resolution=resolution, + request_options=request_options, + ) + logger.info(f"AI UGC Ad response: {create_response}") + + video_projects_client = AsyncVideoProjectsClient(base_client=self._base_client) + return await video_projects_client.check_result( + id=create_response.id, + wait_for_completion=wait_for_completion, + download_outputs=download_outputs, + download_directory=download_directory, + ) + + async def create( + self, + *, + assets: params.V1AiUgcAdCreateBodyAssets, + end_seconds: float, + script: str, + additional_properties: typing.Union[ + typing.Optional[typing.Dict[str, typing.Any]], type_utils.NotGiven + ] = type_utils.NOT_GIVEN, + model: typing.Union[ + typing.Optional[ + typing_extensions.Literal["kling-3.0", "ltx-2.5", "veo3.1"] + ], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + resolution: typing.Union[ + typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]], + type_utils.NotGiven, + ] = type_utils.NOT_GIVEN, + request_options: typing.Optional[RequestOptions] = None, + ) -> models.V1AiUgcAdCreateResponse: + """ + AI UGC Ad Generator + + Create a spoken UGC video from a prepared image and script. Returns a project ID; poll GET /v1/video-projects/{id} for status and downloads. To compose an image, generate the image separately with the Image Editor API and supply its download URL. + + POST /v1/ai-ugc-ad + + Args: + additional_properties: typing.Dict[str, typing.Any] + model: Defaults to kling-3.0 on paid plans and ltx-2.5 on free plans. + resolution: Defaults to 720p on paid plans and 480p on free plans. Unsupported model/resolution combinations and resolutions unavailable for your plan are rejected. + assets: V1AiUgcAdCreateBodyAssets + end_seconds: Video duration in seconds. Supported values by model: + * kling-3.0: 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 seconds. + * ltx-2.5: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 seconds. + * veo3.1: 4, 6, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 120, 127, 134, 141 seconds. + Free plans are limited to 5 seconds unless a credit pack has been purchased. + script: The words the actor should speak. Character limits apply after trimming: + * kling-3.0: 2500 characters. + * ltx-2.5: 1804 characters. + * veo3.1: 2500 characters. + LTX's dialogue wrapper counts toward its model prompt limit. + request_options: Additional options to customize the HTTP request + + Returns: + Success + + Raises: + ApiError: A custom exception class that provides additional context + for API errors, including the HTTP status code and response body. + + Examples: + ```py + await client.v1.ai_ugc_ad.create( + assets={"image_file_path": "api-assets/id/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", + ) + ``` + """ + _json = to_encodable( + item={ + **(additional_properties or {}), + "model": model, + "resolution": resolution, + "assets": assets, + "end_seconds": end_seconds, + "script": script, + }, + dump_with=params._SerializerV1AiUgcAdCreateBody, + ) + return await self._base_client.request( + method="POST", + path="/v1/ai-ugc-ad", + auth_names=["bearerAuth"], + json=_json, + cast_to=models.V1AiUgcAdCreateResponse, + request_options=request_options or default_request_options(), + ) diff --git a/magic_hour/resources/v1/ai_ugc_ad/client_test.py b/magic_hour/resources/v1/ai_ugc_ad/client_test.py new file mode 100644 index 0000000..e5aca96 --- /dev/null +++ b/magic_hour/resources/v1/ai_ugc_ad/client_test.py @@ -0,0 +1,146 @@ +from types import SimpleNamespace +from unittest.mock import AsyncMock, Mock, patch + +import pytest +from make_api_request import RequestOptions +from typing_extensions import TypedDict + +from magic_hour.types import params + +from magic_hour.resources.v1.ai_ugc_ad.client import ( + AiUgcAdClient, + AsyncAiUgcAdClient, +) + + +class GenerateOptions(TypedDict, total=False): + wait_for_completion: bool + download_outputs: bool + download_directory: str + + +@pytest.mark.parametrize("custom_options", [False, True]) +def test_generate_uploads_image_and_returns_video_result(custom_options: bool) -> None: + base_client = Mock() + base_client.request.return_value = SimpleNamespace(id="ugc-123") + client = AiUgcAdClient(base_client=base_client) + assets: params.V1AiUgcAdGenerateBodyAssets = {"image_file_path": "local/image.jpg"} + result = object() + options: GenerateOptions = ( + dict( + wait_for_completion=False, + download_outputs=False, + download_directory="outputs", + ) + if custom_options + else {} + ) + request_options: RequestOptions = {"timeout": 30} + + with ( + patch( + "magic_hour.resources.v1.ai_ugc_ad.client.FilesClient.upload_file", + return_value="api-assets/image.jpg", + ) as upload, + patch( + "magic_hour.resources.v1.ai_ugc_ad.client.VideoProjectsClient.check_result", + return_value=result, + ) as check_result, + ): + response = client.generate( + assets=assets, + end_seconds=4, + script="Try our product.", + model="veo3.1", + resolution="1080p", + additional_properties={"extra_option": True}, + request_options=request_options, + **options, + ) + + assert response is result + upload.assert_called_once_with(file="local/image.jpg") + assert assets == {"image_file_path": "local/image.jpg"} + sent = base_client.request.call_args.kwargs + assert sent["path"] == "/v1/ai-ugc-ad" + assert sent["json"] == { + "assets": {"image_file_path": "api-assets/image.jpg"}, + "end_seconds": 4, + "script": "Try our product.", + "model": "veo3.1", + "resolution": "1080p", + "extra_option": True, + } + assert sent["request_options"] is request_options + check_result.assert_called_once_with( + id="ugc-123", + wait_for_completion=not custom_options, + download_outputs=not custom_options, + download_directory="outputs" if custom_options else None, + ) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("custom_options", [False, True]) +async def test_async_generate_uploads_image_and_returns_video_result( + custom_options: bool, +) -> None: + base_client = AsyncMock() + base_client.request.return_value = SimpleNamespace(id="ugc-123") + client = AsyncAiUgcAdClient(base_client=base_client) + assets: params.V1AiUgcAdGenerateBodyAssets = {"image_file_path": "local/image.jpg"} + result = object() + options: GenerateOptions = ( + dict( + wait_for_completion=False, + download_outputs=False, + download_directory="outputs", + ) + if custom_options + else {} + ) + request_options: RequestOptions = {"timeout": 30} + + with ( + patch( + "magic_hour.resources.v1.ai_ugc_ad.client.AsyncFilesClient.upload_file", + new_callable=AsyncMock, + return_value="api-assets/image.jpg", + ) as upload, + patch( + "magic_hour.resources.v1.ai_ugc_ad.client.AsyncVideoProjectsClient.check_result", + new_callable=AsyncMock, + return_value=result, + ) as check_result, + ): + response = await client.generate( + assets=assets, + end_seconds=4, + script="Try our product.", + model="veo3.1", + resolution="1080p", + additional_properties={"extra_option": True}, + request_options=request_options, + **options, + ) + + assert response is result + upload.assert_awaited_once_with(file="local/image.jpg") + assert assets == {"image_file_path": "local/image.jpg"} + sent = base_client.request.call_args.kwargs + assert sent["path"] == "/v1/ai-ugc-ad" + assert sent["json"] == { + "assets": {"image_file_path": "api-assets/image.jpg"}, + "end_seconds": 4, + "script": "Try our product.", + "model": "veo3.1", + "resolution": "1080p", + "extra_option": True, + } + assert sent["request_options"] is request_options + check_result.assert_awaited_once_with( + id="ugc-123", + wait_for_completion=not custom_options, + download_outputs=not custom_options, + download_directory="outputs" if custom_options else None, + ) diff --git a/magic_hour/resources/v1/ai_video_editor/README.md b/magic_hour/resources/v1/ai_video_editor/README.md index 075e480..2d159ec 100644 --- a/magic_hour/resources/v1/ai_video_editor/README.md +++ b/magic_hour/resources/v1/ai_video_editor/README.md @@ -84,7 +84,7 @@ Create the same Video Editor you can make in the browser, but programmatically, **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/ai_video_editor/client.py b/magic_hour/resources/v1/ai_video_editor/client.py index 04c7d07..5c22336 100644 --- a/magic_hour/resources/v1/ai_video_editor/client.py +++ b/magic_hour/resources/v1/ai_video_editor/client.py @@ -159,7 +159,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -359,7 +359,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/resources/v1/ai_video_translator/README.md b/magic_hour/resources/v1/ai_video_translator/README.md index 7d799f5..1e544d7 100644 --- a/magic_hour/resources/v1/ai_video_translator/README.md +++ b/magic_hour/resources/v1/ai_video_translator/README.md @@ -44,7 +44,7 @@ Create the same Video Translator you can make in the browser, but programmatical **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/ai_video_translator/client.py b/magic_hour/resources/v1/ai_video_translator/client.py index 6d473ae..fc9a7b9 100644 --- a/magic_hour/resources/v1/ai_video_translator/client.py +++ b/magic_hour/resources/v1/ai_video_translator/client.py @@ -216,7 +216,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -472,7 +472,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/resources/v1/audio_to_video/README.md b/magic_hour/resources/v1/audio_to_video/README.md index 3121269..70c89c5 100644 --- a/magic_hour/resources/v1/audio_to_video/README.md +++ b/magic_hour/resources/v1/audio_to_video/README.md @@ -92,7 +92,7 @@ Create the same Audio To Video you can make in the browser, but programmatically **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/audio_to_video/client.py b/magic_hour/resources/v1/audio_to_video/client.py index daa5e42..d295bfe 100644 --- a/magic_hour/resources/v1/audio_to_video/client.py +++ b/magic_hour/resources/v1/audio_to_video/client.py @@ -154,7 +154,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -350,7 +350,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/resources/v1/character_replace/README.md b/magic_hour/resources/v1/character_replace/README.md index 6f0d3fd..fe4a16c 100644 --- a/magic_hour/resources/v1/character_replace/README.md +++ b/magic_hour/resources/v1/character_replace/README.md @@ -92,7 +92,7 @@ Create the same Character Replace you can make in the browser, but programmatica **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/character_replace/client.py b/magic_hour/resources/v1/character_replace/client.py index bffcd31..399e00e 100644 --- a/magic_hour/resources/v1/character_replace/client.py +++ b/magic_hour/resources/v1/character_replace/client.py @@ -169,7 +169,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -385,7 +385,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/resources/v1/client.py b/magic_hour/resources/v1/client.py index 2a469b9..75f779f 100644 --- a/magic_hour/resources/v1/client.py +++ b/magic_hour/resources/v1/client.py @@ -39,6 +39,7 @@ AiTalkingPhotoClient, AsyncAiTalkingPhotoClient, ) +from magic_hour.resources.v1.ai_ugc_ad import AiUgcAdClient, AsyncAiUgcAdClient from magic_hour.resources.v1.ai_video_editor import ( AiVideoEditorClient, AsyncAiVideoEditorClient, @@ -166,6 +167,7 @@ def __init__(self, *, base_client: SyncBaseClient): self.ai_video_translator = AiVideoTranslatorClient( base_client=self._base_client ) + self.ai_ugc_ad = AiUgcAdClient(base_client=self._base_client) class AsyncV1Client: @@ -229,3 +231,4 @@ def __init__(self, *, base_client: AsyncBaseClient): self.ai_video_translator = AsyncAiVideoTranslatorClient( base_client=self._base_client ) + self.ai_ugc_ad = AsyncAiUgcAdClient(base_client=self._base_client) diff --git a/magic_hour/resources/v1/face_swap/README.md b/magic_hour/resources/v1/face_swap/README.md index b21670e..94bfada 100644 --- a/magic_hour/resources/v1/face_swap/README.md +++ b/magic_hour/resources/v1/face_swap/README.md @@ -94,7 +94,7 @@ Create the same Face Swap you can make in the browser, but programmatically, so **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/face_swap/client.py b/magic_hour/resources/v1/face_swap/client.py index a533ebe..f436ff0 100644 --- a/magic_hour/resources/v1/face_swap/client.py +++ b/magic_hour/resources/v1/face_swap/client.py @@ -170,7 +170,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -393,7 +393,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/resources/v1/image_to_video/README.md b/magic_hour/resources/v1/image_to_video/README.md index ce6f5ec..7b47428 100644 --- a/magic_hour/resources/v1/image_to_video/README.md +++ b/magic_hour/resources/v1/image_to_video/README.md @@ -82,7 +82,7 @@ Create the same Image To Video you can make in the browser, but programmatically **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ @@ -94,22 +94,22 @@ For detailed examples, see the [product page](https://magichour.ai/products/imag #### Parameters -| Parameter | Required | Deprecated | Description | Example | -| ------------------------ | :------: | :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -| `assets` | ✓ | ✗ | Provide the assets for image-to-video. | `{"end_image_file_path": "api-assets/id/1234.png", "image_file_path": "api-assets/id/1234.png"}` | -| `└─ end_image_file_path` | ✗ | — | The image to use as the last frame of the video. * **`gemini-omni-1.1`**: Supports 360p, 720p, 1080p, 4k. * **`kling-2.6`**: Supports 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. * **`minimax-h3`**: Not supported * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. Requires a duration of 8 seconds or less. * **`veo3.1-lite`**: Supports 720p, 1080p. Requires a duration of 8 seconds or less. * **`wan-2.2`**: Not supported * **`wan-3.0`**: Supports 480p, 720p, 1080p. | `"api-assets/id/1234.png"` | -| `└─ 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/1234.png"` | -| `end_seconds` | ✓ | ✗ | The total duration of the output video in seconds. Supported durations depend on the chosen model: * **`gemini-omni-1.1`**: any integer from 3 to 10 * **`kling-2.6`**: 5, 10 * **`kling-3.0`**: any integer from 3 to 15 * **`ltx-2.5`**: any integer from 1 to 60 * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`veo3.1-lite`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`wan-2.2`**: 3, 4, 5, 6, 7, 8, 9, 10, 15 * **`wan-3.0`**: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30 | `5.0` | -| `audio` | ✗ | ✗ | Whether to include audio in the video. Defaults to `false` if not specified. Audio support varies by model: * **`gemini-omni-1.1`**: Not supported * **`kling-2.6`**: Not supported * **`kling-3.0`**: Toggle-able: audio adds extra credits when enabled * **`ltx-2.5`**: Toggle-able: no additional credits for audio * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled * **`veo3.1-lite`**: Toggle-able: audio adds extra credits when enabled * **`wan-2.2`**: Not supported * **`wan-3.0`**: Toggle-able: no additional credits for audio | `True` | -| `height` | ✗ | ✓ | `height` is deprecated and no longer influences the output video's resolution. This field is retained only for backward compatibility and will be removed in a future release. | `123` | -| `model` | ✗ | ✗ | The AI model to use for video generation. * `default`: uses our currently recommended model for general use. For paid tiers, defaults to `kling-3.0`. For free tiers, it defaults to `ltx-2.5`. * `gemini-omni-1.1`: Best for precise short clips, first/last frames, and high-resolution output. * `kling-2.6`: Best for action, motion blur, and controlled camera moves. * `kling-3.0`: Best for cinematic stories, references, and optional audio. * `ltx-2.5`: Fastest for general scenes, long clips, audio, and rapid iteration. * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. * `veo3.1-lite`: Balanced realism and audio at a lower cost than Veo 3.1. * `wan-2.2`: Best for physical motion, action, and camera movement. * `wan-3.0`: High-quality video with native audio, long clips, and end-frame control. If you specify the deprecated model value that includes the `-audio` suffix, this will be the same as included `audio` as `true`. | `"ltx-2.5"` | -| `name` | ✗ | ✗ | Give your video a custom name for easy identification. | `"My Image To Video video"` | -| `resolution` | ✗ | ✗ | Controls the output video resolution. Defaults to `720p` on paid tiers and `480p` on free tiers. * **`gemini-omni-1.1`**: Supports 360p, 720p, 1080p, 4k. * **`kling-2.6`**: Supports 720p, 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. * **`veo3.1-lite`**: Supports 720p, 1080p. * **`wan-2.2`**: Supports 480p, 720p, 1080p. * **`wan-3.0`**: Supports 480p, 720p, 1080p. | `"480p"` | -| `style` | ✗ | ✗ | Attributed used to dictate the style of the output | `{"prompt": "a dog running"}` | -| `└─ 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` | -| `└─ prompt` | ✗ | — | The prompt used for the video. | `"a dog running"` | -| `└─ 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"` | -| `width` | ✗ | ✓ | `width` is deprecated and no longer influences the output video's resolution. This field is retained only for backward compatibility and will be removed in a future release. | `123` | +| Parameter | Required | Deprecated | Description | Example | +| ------------------------ | :------: | :--------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| `assets` | ✓ | ✗ | Provide the assets for image-to-video. | `{"end_image_file_path": "api-assets/id/1234.png", "image_file_path": "api-assets/id/1234.png"}` | +| `└─ end_image_file_path` | ✗ | — | The image to use as the last frame of the video. * **`gemini-omni-1.1`**: Supports 360p, 720p, 1080p, 4k. * **`kling-2.6`**: Supports 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. Requires a duration of 8 seconds or less. * **`veo3.1-lite`**: Supports 720p, 1080p. Requires a duration of 8 seconds or less. * **`wan-2.2`**: Not supported * **`wan-3.0`**: Supports 480p, 720p, 1080p. | `"api-assets/id/1234.png"` | +| `└─ 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). See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. | `"api-assets/id/1234.png"` | +| `end_seconds` | ✓ | ✗ | The total duration of the output video in seconds. Supported durations depend on the chosen model: * **`gemini-omni-1.1`**: any integer from 3 to 10 * **`kling-2.6`**: 5, 10 * **`kling-3.0`**: any integer from 3 to 15 * **`ltx-2.5`**: any integer from 1 to 60 * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`veo3.1-lite`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`wan-2.2`**: 3, 4, 5, 6, 7, 8, 9, 10, 15 * **`wan-3.0`**: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30 | `5.0` | +| `audio` | ✗ | ✗ | Whether to include audio in the video. Defaults to `false` if not specified. Audio support varies by model: * **`gemini-omni-1.1`**: Not supported * **`kling-2.6`**: Not supported * **`kling-3.0`**: Toggle-able: audio adds extra credits when enabled * **`ltx-2.5`**: Toggle-able: no additional credits for audio * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled * **`veo3.1-lite`**: Toggle-able: audio adds extra credits when enabled * **`wan-2.2`**: Not supported * **`wan-3.0`**: Toggle-able: no additional credits for audio | `True` | +| `height` | ✗ | ✓ | `height` is deprecated and no longer influences the output video's resolution. This field is retained only for backward compatibility and will be removed in a future release. | `123` | +| `model` | ✗ | ✗ | The AI model to use for video generation. * `default`: uses our currently recommended model for general use. For paid tiers, defaults to `kling-3.0`. For free tiers, it defaults to `ltx-2.5`. * `gemini-omni-1.1`: Best for precise short clips, first/last frames, and high-resolution output. * `kling-2.6`: Best for action, motion blur, and controlled camera moves. * `kling-3.0`: Best for cinematic stories, references, and optional audio. * `ltx-2.5`: Fastest for general scenes, long clips, audio, and rapid iteration. * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. * `veo3.1-lite`: Balanced realism and audio at a lower cost than Veo 3.1. * `wan-2.2`: Best for physical motion, action, and camera movement. * `wan-3.0`: High-quality video with native audio, long clips, and end-frame control. If you specify the deprecated model value that includes the `-audio` suffix, this will be the same as included `audio` as `true`. | `"ltx-2.5"` | +| `name` | ✗ | ✗ | Give your video a custom name for easy identification. | `"My Image To Video video"` | +| `resolution` | ✗ | ✗ | Controls the output video resolution. Defaults to `720p` on paid tiers and `480p` on free tiers. * **`gemini-omni-1.1`**: Supports 360p, 720p, 1080p, 4k. * **`kling-2.6`**: Supports 720p, 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. * **`veo3.1-lite`**: Supports 720p, 1080p. * **`wan-2.2`**: Supports 480p, 720p, 1080p. * **`wan-3.0`**: Supports 480p, 720p, 1080p. | `"480p"` | +| `style` | ✗ | ✗ | Attributed used to dictate the style of the output | `{"prompt": "a dog running"}` | +| `└─ 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` | +| `└─ prompt` | ✗ | — | The prompt used for the video. | `"a dog running"` | +| `└─ 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"` | +| `width` | ✗ | ✓ | `width` is deprecated and no longer influences the output video's resolution. This field is retained only for backward compatibility and will be removed in a future release. | `123` | #### Synchronous Client diff --git a/magic_hour/resources/v1/image_to_video/client.py b/magic_hour/resources/v1/image_to_video/client.py index 4d2bbd5..ffb7fa7 100644 --- a/magic_hour/resources/v1/image_to_video/client.py +++ b/magic_hour/resources/v1/image_to_video/client.py @@ -50,6 +50,7 @@ def generate( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -177,6 +178,7 @@ def create( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -224,7 +226,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -245,6 +247,7 @@ def create( * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio + * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled @@ -265,6 +268,7 @@ def create( * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. + * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. @@ -283,6 +287,7 @@ def create( * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. @@ -304,6 +309,7 @@ def create( * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 + * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 @@ -403,6 +409,7 @@ async def generate( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -515,6 +522,7 @@ async def create( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -562,7 +570,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -583,6 +591,7 @@ async def create( * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio + * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled @@ -603,6 +612,7 @@ async def create( * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. + * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. @@ -621,6 +631,7 @@ async def create( * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. @@ -642,6 +653,7 @@ async def create( * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 + * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 diff --git a/magic_hour/resources/v1/lip_sync/README.md b/magic_hour/resources/v1/lip_sync/README.md index 0c78c2d..ccd4f3f 100644 --- a/magic_hour/resources/v1/lip_sync/README.md +++ b/magic_hour/resources/v1/lip_sync/README.md @@ -98,7 +98,7 @@ Create the same Lip Sync you can make in the browser, but programmatically, so y **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/lip_sync/client.py b/magic_hour/resources/v1/lip_sync/client.py index 3e53ec9..97d8602 100644 --- a/magic_hour/resources/v1/lip_sync/client.py +++ b/magic_hour/resources/v1/lip_sync/client.py @@ -169,7 +169,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -389,7 +389,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/resources/v1/text_to_video/README.md b/magic_hour/resources/v1/text_to_video/README.md index a180257..8281409 100644 --- a/magic_hour/resources/v1/text_to_video/README.md +++ b/magic_hour/resources/v1/text_to_video/README.md @@ -84,7 +84,7 @@ Create the same Text To Video you can make in the browser, but programmatically, **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ @@ -96,19 +96,19 @@ For detailed examples, see the [product page](https://magichour.ai/products/text #### Parameters -| Parameter | Required | Deprecated | Description | Example | -| ----------------- | :------: | :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -| `end_seconds` | ✓ | ✗ | The total duration of the output video in seconds. Supported durations depend on the chosen model: * **`gemini-omni-1.1`**: any integer from 3 to 10 * **`kling-2.6`**: 5, 10 * **`kling-3.0`**: any integer from 3 to 15 * **`ltx-2.5`**: any integer from 1 to 60 * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`veo3.1-lite`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`wan-2.2`**: 3, 4, 5, 6, 7, 8, 9, 10, 15 * **`wan-3.0`**: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30 | `5.0` | -| `style` | ✓ | ✗ | | `{"prompt": "a dog running"}` | -| `└─ prompt` | ✓ | — | The prompt used for the video. | `"a dog running"` | -| `└─ 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"` | -| `aspect_ratio` | ✗ | ✗ | Determines the aspect ratio of the output video. * **`gemini-omni-1.1`**: Supports 16:9, 9:16. * **`kling-2.6`**: Supports 9:16, 16:9, 1:1. * **`kling-3.0`**: Supports 9:16, 16:9, 1:1. * **`ltx-2.5`**: Supports 9:16, 16:9, 1:1. * **`minimax-h3`**: Supports 16:9, 9:16, 1:1. * **`seedance-1.5`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0-mini`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.5`**: Supports 9:16, 16:9, 1:1. * **`veo3.1`**: Supports 9:16, 16:9. * **`veo3.1-lite`**: Supports 9:16, 16:9. * **`wan-2.2`**: Supports 9:16, 16:9, 1:1. * **`wan-3.0`**: Supports 16:9, 9:16, 1:1. | `"16:9"` | -| `audio` | ✗ | ✗ | Whether to include audio in the video. Defaults to `false` if not specified. Audio support varies by model: * **`gemini-omni-1.1`**: Not supported * **`kling-2.6`**: Not supported * **`kling-3.0`**: Toggle-able: audio adds extra credits when enabled * **`ltx-2.5`**: Toggle-able: no additional credits for audio * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled * **`veo3.1-lite`**: Toggle-able: audio adds extra credits when enabled * **`wan-2.2`**: Not supported * **`wan-3.0`**: Toggle-able: no additional credits for audio | `True` | -| `model` | ✗ | ✗ | The AI model to use for video generation. * `default`: uses our currently recommended model for general use. For paid tiers, defaults to `kling-3.0`. For free tiers, it defaults to `ltx-2.5`. * `gemini-omni-1.1`: Best for precise short clips, first/last frames, and high-resolution output. * `kling-2.6`: Best for action, motion blur, and controlled camera moves. * `kling-3.0`: Best for cinematic stories, references, and optional audio. * `ltx-2.5`: Fastest for general scenes, long clips, audio, and rapid iteration. * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. * `veo3.1-lite`: Balanced realism and audio at a lower cost than Veo 3.1. * `wan-2.2`: Best for physical motion, action, and camera movement. * `wan-3.0`: High-quality video with native audio, long clips, and end-frame control. If you specify the deprecated model value that includes the `-audio` suffix, this will be the same as included `audio` as `true`. | `"ltx-2.5"` | -| `name` | ✗ | ✗ | Give your video a custom name for easy identification. | `"My Text To Video video"` | -| `orientation` | ✗ | ✓ | Deprecated. Use `aspect_ratio` instead. | `"landscape"` | -| `references` | ✗ | ✗ | Reference media for video generation. Name references without @ and refer to them as @name in style.prompt. Maximum 10 references total. Supported models and reference media: * **`kling-3.0`**: Supports images, videos. * **`minimax-h3`**: Supports images, videos, audio. * **`seedance-2.0`**: Supports images, videos, audio. * **`seedance-2.0-mini`**: Supports images, videos, audio. * **`seedance-2.5`**: Supports images, videos, audio. * **`wan-3.0`**: Supports images, videos, audio. | `[{"file_path": "api-assets/id/1234.png", "name": "hero"}]` | -| `resolution` | ✗ | ✗ | Controls the output video resolution. Defaults to `720p` on paid tiers and `480p` on free tiers. * **`gemini-omni-1.1`**: Supports 360p, 720p, 1080p, 4k. * **`kling-2.6`**: Supports 720p, 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. * **`veo3.1-lite`**: Supports 720p, 1080p. * **`wan-2.2`**: Supports 480p, 720p, 1080p. * **`wan-3.0`**: Supports 480p, 720p, 1080p. | `"480p"` | +| Parameter | Required | Deprecated | Description | Example | +| ----------------- | :------: | :--------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | +| `end_seconds` | ✓ | ✗ | The total duration of the output video in seconds. Supported durations depend on the chosen model: * **`gemini-omni-1.1`**: any integer from 3 to 10 * **`kling-2.6`**: 5, 10 * **`kling-3.0`**: any integer from 3 to 15 * **`ltx-2.5`**: any integer from 1 to 60 * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`veo3.1-lite`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 * **`wan-2.2`**: 3, 4, 5, 6, 7, 8, 9, 10, 15 * **`wan-3.0`**: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30 | `5.0` | +| `style` | ✓ | ✗ | | `{"prompt": "a dog running"}` | +| `└─ prompt` | ✓ | — | The prompt used for the video. | `"a dog running"` | +| `└─ 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"` | +| `aspect_ratio` | ✗ | ✗ | Provide `aspect_ratio` to set the video’s aspect ratio. Determines the aspect ratio of the output video. * **`gemini-omni-1.1`**: Supports 16:9, 9:16. * **`kling-2.6`**: Supports 9:16, 16:9, 1:1. * **`kling-3.0`**: Supports 9:16, 16:9, 1:1. * **`ltx-2.5`**: Supports 9:16, 16:9, 1:1. * **`minimax-h3`**: Supports 16:9, 9:16, 1:1. * **`seedance-1.5`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0-fast`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0-mini`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.5`**: Supports 9:16, 16:9, 1:1. * **`veo3.1`**: Supports 9:16, 16:9. * **`veo3.1-lite`**: Supports 9:16, 16:9. * **`wan-2.2`**: Supports 9:16, 16:9, 1:1. * **`wan-3.0`**: Supports 16:9, 9:16, 1:1. | `"16:9"` | +| `audio` | ✗ | ✗ | Whether to include audio in the video. Defaults to `false` if not specified. Audio support varies by model: * **`gemini-omni-1.1`**: Not supported * **`kling-2.6`**: Not supported * **`kling-3.0`**: Toggle-able: audio adds extra credits when enabled * **`ltx-2.5`**: Toggle-able: no additional credits for audio * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled * **`veo3.1-lite`**: Toggle-able: audio adds extra credits when enabled * **`wan-2.2`**: Not supported * **`wan-3.0`**: Toggle-able: no additional credits for audio | `True` | +| `model` | ✗ | ✗ | The AI model to use for video generation. * `default`: uses our currently recommended model for general use. For paid tiers, defaults to `kling-3.0`. For free tiers, it defaults to `ltx-2.5`. * `gemini-omni-1.1`: Best for precise short clips, first/last frames, and high-resolution output. * `kling-2.6`: Best for action, motion blur, and controlled camera moves. * `kling-3.0`: Best for cinematic stories, references, and optional audio. * `ltx-2.5`: Fastest for general scenes, long clips, audio, and rapid iteration. * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. * `veo3.1-lite`: Balanced realism and audio at a lower cost than Veo 3.1. * `wan-2.2`: Best for physical motion, action, and camera movement. * `wan-3.0`: High-quality video with native audio, long clips, and end-frame control. If you specify the deprecated model value that includes the `-audio` suffix, this will be the same as included `audio` as `true`. | `"ltx-2.5"` | +| `name` | ✗ | ✗ | Give your video a custom name for easy identification. | `"My Text To Video video"` | +| `orientation` | ✗ | ✓ | Deprecated. Use `aspect_ratio` instead. | `"landscape"` | +| `references` | ✗ | ✗ | Reference media for video generation. Name references without @ and refer to them as @name in style.prompt. Maximum 10 references total. Supported models and reference media: * **`gemini-omni-1.1`**: Supports images, videos. Up to 13 references. * **`kling-3.0`**: Supports images, videos. * **`minimax-h3`**: Supports images, videos, audio. * **`seedance-2.0`**: Supports images, videos, audio. * **`seedance-2.0-fast`**: Supports images, videos, audio. * **`seedance-2.0-mini`**: Supports images, videos, audio. * **`seedance-2.5`**: Supports images, videos, audio. * **`veo3.1`**: Supports images. Up to 3 references. Requires `end_seconds` of 8. * **`wan-3.0`**: Supports images, videos, audio. | `[{"file_path": "api-assets/id/1234.png", "name": "hero"}]` | +| `resolution` | ✗ | ✗ | Controls the output video resolution. Defaults to `720p` on paid tiers and `480p` on free tiers. * **`gemini-omni-1.1`**: Supports 360p, 720p, 1080p, 4k. * **`kling-2.6`**: Supports 720p, 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. * **`veo3.1-lite`**: Supports 720p, 1080p. * **`wan-2.2`**: Supports 480p, 720p, 1080p. * **`wan-3.0`**: Supports 480p, 720p, 1080p. | `"480p"` | #### Synchronous Client diff --git a/magic_hour/resources/v1/text_to_video/client.py b/magic_hour/resources/v1/text_to_video/client.py index a80496c..a6b671e 100644 --- a/magic_hour/resources/v1/text_to_video/client.py +++ b/magic_hour/resources/v1/text_to_video/client.py @@ -50,6 +50,7 @@ def generate( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -175,6 +176,7 @@ def create( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -226,7 +228,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -237,7 +239,7 @@ def create( POST /v1/text-to-video Args: - aspect_ratio: Determines the aspect ratio of the output video. + aspect_ratio: Provide `aspect_ratio` to set the video’s aspect ratio. Determines the aspect ratio of the output video. * **`gemini-omni-1.1`**: Supports 16:9, 9:16. * **`kling-2.6`**: Supports 9:16, 16:9, 1:1. @@ -246,6 +248,7 @@ def create( * **`minimax-h3`**: Supports 16:9, 9:16, 1:1. * **`seedance-1.5`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0`**: Supports 9:16, 16:9, 1:1. + * **`seedance-2.0-fast`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0-mini`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.5`**: Supports 9:16, 16:9, 1:1. * **`veo3.1`**: Supports 9:16, 16:9. @@ -263,6 +266,7 @@ def create( * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio + * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled @@ -280,6 +284,7 @@ def create( * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. + * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. @@ -293,11 +298,14 @@ def create( references: Reference media for video generation. Name references without @ and refer to them as @name in style.prompt. Maximum 10 references total. Supported models and reference media: + * **`gemini-omni-1.1`**: Supports images, videos. Up to 13 references. * **`kling-3.0`**: Supports images, videos. * **`minimax-h3`**: Supports images, videos, audio. * **`seedance-2.0`**: Supports images, videos, audio. + * **`seedance-2.0-fast`**: Supports images, videos, audio. * **`seedance-2.0-mini`**: Supports images, videos, audio. * **`seedance-2.5`**: Supports images, videos, audio. + * **`veo3.1`**: Supports images. Up to 3 references. Requires `end_seconds` of 8. * **`wan-3.0`**: Supports images, videos, audio. resolution: Controls the output video resolution. Defaults to `720p` on paid tiers and `480p` on free tiers. @@ -308,6 +316,7 @@ def create( * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. @@ -324,6 +333,7 @@ def create( * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 + * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 @@ -423,6 +433,7 @@ async def generate( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -533,6 +544,7 @@ async def create( "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -584,7 +596,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -595,7 +607,7 @@ async def create( POST /v1/text-to-video Args: - aspect_ratio: Determines the aspect ratio of the output video. + aspect_ratio: Provide `aspect_ratio` to set the video’s aspect ratio. Determines the aspect ratio of the output video. * **`gemini-omni-1.1`**: Supports 16:9, 9:16. * **`kling-2.6`**: Supports 9:16, 16:9, 1:1. @@ -604,6 +616,7 @@ async def create( * **`minimax-h3`**: Supports 16:9, 9:16, 1:1. * **`seedance-1.5`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0`**: Supports 9:16, 16:9, 1:1. + * **`seedance-2.0-fast`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0-mini`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.5`**: Supports 9:16, 16:9, 1:1. * **`veo3.1`**: Supports 9:16, 16:9. @@ -621,6 +634,7 @@ async def create( * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio + * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled @@ -638,6 +652,7 @@ async def create( * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. + * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. @@ -651,11 +666,14 @@ async def create( references: Reference media for video generation. Name references without @ and refer to them as @name in style.prompt. Maximum 10 references total. Supported models and reference media: + * **`gemini-omni-1.1`**: Supports images, videos. Up to 13 references. * **`kling-3.0`**: Supports images, videos. * **`minimax-h3`**: Supports images, videos, audio. * **`seedance-2.0`**: Supports images, videos, audio. + * **`seedance-2.0-fast`**: Supports images, videos, audio. * **`seedance-2.0-mini`**: Supports images, videos, audio. * **`seedance-2.5`**: Supports images, videos, audio. + * **`veo3.1`**: Supports images. Up to 3 references. Requires `end_seconds` of 8. * **`wan-3.0`**: Supports images, videos, audio. resolution: Controls the output video resolution. Defaults to `720p` on paid tiers and `480p` on free tiers. @@ -666,6 +684,7 @@ async def create( * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. @@ -682,6 +701,7 @@ async def create( * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 + * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 diff --git a/magic_hour/resources/v1/video_to_video/README.md b/magic_hour/resources/v1/video_to_video/README.md index 5634fe5..0250c48 100644 --- a/magic_hour/resources/v1/video_to_video/README.md +++ b/magic_hour/resources/v1/video_to_video/README.md @@ -98,7 +98,7 @@ Create the same Video To Video you can make in the browser, but programmatically **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type -- Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes +- Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost**\ diff --git a/magic_hour/resources/v1/video_to_video/client.py b/magic_hour/resources/v1/video_to_video/client.py index 4fb550f..7706651 100644 --- a/magic_hour/resources/v1/video_to_video/client.py +++ b/magic_hour/resources/v1/video_to_video/client.py @@ -170,7 +170,7 @@ def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** @@ -399,7 +399,7 @@ async def create( **Key options** - Inputs: usually a file, sometimes a YouTube link, depending on project type - - Resolution: free users are limited to 576px; higher plans unlock HD and larger sizes + - Resolution: output size and plan requirements vary by workflow and model. Some workflows derive output size from the input video. - Extra fields: e.g. `face_swap_mode`, `start_seconds`/`end_seconds`, or a text prompt **Cost** diff --git a/magic_hour/types/models/__init__.py b/magic_hour/types/models/__init__.py index cbda749..77419c7 100644 --- a/magic_hour/types/models/__init__.py +++ b/magic_hour/types/models/__init__.py @@ -18,6 +18,7 @@ from .v1_ai_meme_generator_create_response import V1AiMemeGeneratorCreateResponse from .v1_ai_qr_code_generator_create_response import V1AiQrCodeGeneratorCreateResponse from .v1_ai_talking_photo_create_response import V1AiTalkingPhotoCreateResponse +from .v1_ai_ugc_ad_create_response import V1AiUgcAdCreateResponse from .v1_ai_video_editor_create_response import V1AiVideoEditorCreateResponse from .v1_ai_video_translator_create_response import V1AiVideoTranslatorCreateResponse from .v1_ai_voice_cloner_create_response import V1AiVoiceClonerCreateResponse @@ -87,6 +88,7 @@ "V1AiMemeGeneratorCreateResponse", "V1AiQrCodeGeneratorCreateResponse", "V1AiTalkingPhotoCreateResponse", + "V1AiUgcAdCreateResponse", "V1AiVideoEditorCreateResponse", "V1AiVideoTranslatorCreateResponse", "V1AiVoiceClonerCreateResponse", diff --git a/magic_hour/types/models/v1_ai_ugc_ad_create_response.py b/magic_hour/types/models/v1_ai_ugc_ad_create_response.py new file mode 100644 index 0000000..22da801 --- /dev/null +++ b/magic_hour/types/models/v1_ai_ugc_ad_create_response.py @@ -0,0 +1,35 @@ +import pydantic + + +class V1AiUgcAdCreateResponse(pydantic.BaseModel): + """ + Success + """ + + model_config = pydantic.ConfigDict( + arbitrary_types_allowed=True, + populate_by_name=True, + ) + + credits_charged: int = pydantic.Field( + alias="credits_charged", + ) + """ + The amount of credits deducted from your account to generate the video. If the status is not 'complete', this value is an estimate and may be adjusted upon completion based on the actual FPS of the output video. + + If video generation fails, credits will be refunded, and this field will be updated to include the refund. + """ + estimated_frame_cost: int = pydantic.Field( + alias="estimated_frame_cost", + ) + """ + Deprecated: Previously represented the number of frames (original name of our credit system) used for video generation. Use 'credits_charged' instead. + + The amount of frames used to generate the video. If the status is not 'complete', the cost is an estimate and will be adjusted when the video completes. + """ + id: str = pydantic.Field( + alias="id", + ) + """ + Unique ID of the video. Use it with the [Get video Project API](https://docs.magichour.ai/api-reference/video-projects/get-video-details) to fetch status and downloads. + """ diff --git a/magic_hour/types/params/__init__.py b/magic_hour/types/params/__init__.py index ff6b10b..a2a38e8 100644 --- a/magic_hour/types/params/__init__.py +++ b/magic_hour/types/params/__init__.py @@ -111,6 +111,15 @@ _SerializerV1AiTalkingPhotoCreateBodyStyle, ) from .v1_ai_talking_photo_generate_body_assets import V1AiTalkingPhotoGenerateBodyAssets +from .v1_ai_ugc_ad_create_body import ( + V1AiUgcAdCreateBody, + _SerializerV1AiUgcAdCreateBody, +) +from .v1_ai_ugc_ad_create_body_assets import ( + V1AiUgcAdCreateBodyAssets, + _SerializerV1AiUgcAdCreateBodyAssets, +) +from .v1_ai_ugc_ad_generate_body_assets import V1AiUgcAdGenerateBodyAssets from .v1_ai_video_editor_create_body import ( V1AiVideoEditorCreateBody, _SerializerV1AiVideoEditorCreateBody, @@ -393,6 +402,9 @@ "V1AiTalkingPhotoCreateBodyAssets", "V1AiTalkingPhotoCreateBodyStyle", "V1AiTalkingPhotoGenerateBodyAssets", + "V1AiUgcAdCreateBody", + "V1AiUgcAdCreateBodyAssets", + "V1AiUgcAdGenerateBodyAssets", "V1AiVideoEditorCreateBody", "V1AiVideoEditorCreateBodyAssets", "V1AiVideoEditorCreateBodyStyle", @@ -491,6 +503,8 @@ "_SerializerV1AiTalkingPhotoCreateBody", "_SerializerV1AiTalkingPhotoCreateBodyAssets", "_SerializerV1AiTalkingPhotoCreateBodyStyle", + "_SerializerV1AiUgcAdCreateBody", + "_SerializerV1AiUgcAdCreateBodyAssets", "_SerializerV1AiVideoEditorCreateBody", "_SerializerV1AiVideoEditorCreateBodyAssets", "_SerializerV1AiVideoEditorCreateBodyStyle", diff --git a/magic_hour/types/params/v1_ai_talking_photo_create_body.py b/magic_hour/types/params/v1_ai_talking_photo_create_body.py index 3eeb8d8..58926e9 100644 --- a/magic_hour/types/params/v1_ai_talking_photo_create_body.py +++ b/magic_hour/types/params/v1_ai_talking_photo_create_body.py @@ -29,7 +29,11 @@ class V1AiTalkingPhotoCreateBody(typing_extensions.TypedDict): max_resolution: typing_extensions.NotRequired[int] """ - Constrains the larger dimension (height or width) of the output video. Allows you to set a lower resolution than your plan's maximum if desired. The value is capped by your plan's max resolution. + Deprecated: use `resolution`. Still accepted as a larger-dimension cap, limited by your plan. Ignored when `resolution` is provided. + + After plan capping: + * Below 1280 maps to `480p` (intermediate values round down). + * 1280 or above maps to `720p`. """ name: typing_extensions.NotRequired[str] @@ -37,6 +41,11 @@ class V1AiTalkingPhotoCreateBody(typing_extensions.TypedDict): Give your video a custom name for easy identification. """ + resolution: typing_extensions.NotRequired[typing_extensions.Literal["480p", "720p"]] + """ + Output preset. Overrides `max_resolution`. Defaults to 480p in prompted mode; realistic mode uses the mapped plan maximum. + """ + start_seconds: typing_extensions.Required[float] """ The start time of the input audio in seconds. Maximum clip length depends on style.generation_mode: realistic 300s, prompted 45s. @@ -68,6 +77,9 @@ class _SerializerV1AiTalkingPhotoCreateBody(pydantic.BaseModel): alias="max_resolution", default=None ) name: typing.Optional[str] = pydantic.Field(alias="name", default=None) + resolution: typing.Optional[typing_extensions.Literal["480p", "720p"]] = ( + pydantic.Field(alias="resolution", default=None) + ) start_seconds: float = pydantic.Field( alias="start_seconds", ) diff --git a/magic_hour/types/params/v1_ai_ugc_ad_create_body.py b/magic_hour/types/params/v1_ai_ugc_ad_create_body.py new file mode 100644 index 0000000..3a3801e --- /dev/null +++ b/magic_hour/types/params/v1_ai_ugc_ad_create_body.py @@ -0,0 +1,77 @@ +import pydantic +import typing +import typing_extensions + +from .v1_ai_ugc_ad_create_body_assets import ( + V1AiUgcAdCreateBodyAssets, + _SerializerV1AiUgcAdCreateBodyAssets, +) + + +class V1AiUgcAdCreateBody(typing_extensions.TypedDict, total=False): + """ + V1AiUgcAdCreateBody + """ + + assets: typing_extensions.Required[V1AiUgcAdCreateBodyAssets] + + end_seconds: typing_extensions.Required[float] + """ + Video duration in seconds. Supported values by model: + * kling-3.0: 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 seconds. + * ltx-2.5: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60 seconds. + * veo3.1: 4, 6, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 106, 113, 120, 127, 134, 141 seconds. + Free plans are limited to 5 seconds unless a credit pack has been purchased. + """ + + model: typing_extensions.NotRequired[ + typing_extensions.Literal["kling-3.0", "ltx-2.5", "veo3.1"] + ] + """ + Defaults to kling-3.0 on paid plans and ltx-2.5 on free plans. + """ + + resolution: typing_extensions.NotRequired[ + typing_extensions.Literal["1080p", "480p", "720p"] + ] + """ + Defaults to 720p on paid plans and 480p on free plans. Unsupported model/resolution combinations and resolutions unavailable for your plan are rejected. + """ + + script: typing_extensions.Required[str] + """ + The words the actor should speak. Character limits apply after trimming: + * kling-3.0: 2500 characters. + * ltx-2.5: 1804 characters. + * veo3.1: 2500 characters. + LTX's dialogue wrapper counts toward its model prompt limit. + """ + + +class _SerializerV1AiUgcAdCreateBody(pydantic.BaseModel): + """ + Serializer for V1AiUgcAdCreateBody handling case conversions + and file omissions as dictated by the API + """ + + model_config = pydantic.ConfigDict( + populate_by_name=True, + extra="allow", + ) + __pydantic_extra__: typing.Dict[str, typing.Any] + + assets: _SerializerV1AiUgcAdCreateBodyAssets = pydantic.Field( + alias="assets", + ) + end_seconds: float = pydantic.Field( + alias="end_seconds", + ) + model: typing.Optional[ + typing_extensions.Literal["kling-3.0", "ltx-2.5", "veo3.1"] + ] = pydantic.Field(alias="model", default=None) + resolution: typing.Optional[typing_extensions.Literal["1080p", "480p", "720p"]] = ( + pydantic.Field(alias="resolution", default=None) + ) + script: str = pydantic.Field( + alias="script", + ) diff --git a/magic_hour/types/params/v1_ai_ugc_ad_create_body_assets.py b/magic_hour/types/params/v1_ai_ugc_ad_create_body_assets.py new file mode 100644 index 0000000..594f8e3 --- /dev/null +++ b/magic_hour/types/params/v1_ai_ugc_ad_create_body_assets.py @@ -0,0 +1,36 @@ +import pydantic +import typing +import typing_extensions + + +class V1AiUgcAdCreateBodyAssets(typing_extensions.TypedDict, total=False): + """ + V1AiUgcAdCreateBodyAssets + """ + + image_file_path: typing_extensions.Required[str] + """ + Prepared image to animate. 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). + + See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details. + + """ + + +class _SerializerV1AiUgcAdCreateBodyAssets(pydantic.BaseModel): + """ + Serializer for V1AiUgcAdCreateBodyAssets handling case conversions + and file omissions as dictated by the API + """ + + model_config = pydantic.ConfigDict( + populate_by_name=True, + extra="allow", + ) + __pydantic_extra__: typing.Dict[str, typing.Any] + + image_file_path: str = pydantic.Field( + alias="image_file_path", + ) diff --git a/magic_hour/types/params/v1_ai_ugc_ad_generate_body_assets.py b/magic_hour/types/params/v1_ai_ugc_ad_generate_body_assets.py new file mode 100644 index 0000000..647da28 --- /dev/null +++ b/magic_hour/types/params/v1_ai_ugc_ad_generate_body_assets.py @@ -0,0 +1,11 @@ +import typing_extensions + + +class V1AiUgcAdGenerateBodyAssets(typing_extensions.TypedDict, total=False): + """Provide the prepared image for UGC ad generation.""" + + image_file_path: typing_extensions.Required[str] + """ + Prepared image to animate. Accepts a local image path or a direct URL. + Paths beginning with `api-assets` are already uploaded and reused as is. + """ diff --git a/magic_hour/types/params/v1_image_to_video_create_body.py b/magic_hour/types/params/v1_image_to_video_create_body.py index 2c58db6..0c31aad 100644 --- a/magic_hour/types/params/v1_image_to_video_create_body.py +++ b/magic_hour/types/params/v1_image_to_video_create_body.py @@ -34,6 +34,7 @@ class V1ImageToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio + * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled @@ -54,6 +55,7 @@ class V1ImageToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 + * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 @@ -86,6 +88,7 @@ class V1ImageToVideoCreateBody(typing_extensions.TypedDict): "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -107,6 +110,7 @@ class V1ImageToVideoCreateBody(typing_extensions.TypedDict): * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. + * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. @@ -135,6 +139,7 @@ class V1ImageToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. @@ -191,6 +196,7 @@ class _SerializerV1ImageToVideoCreateBody(pydantic.BaseModel): "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", diff --git a/magic_hour/types/params/v1_image_to_video_create_body_assets.py b/magic_hour/types/params/v1_image_to_video_create_body_assets.py index 14b1bfc..79da854 100644 --- a/magic_hour/types/params/v1_image_to_video_create_body_assets.py +++ b/magic_hour/types/params/v1_image_to_video_create_body_assets.py @@ -16,9 +16,10 @@ class V1ImageToVideoCreateBodyAssets(typing_extensions.TypedDict): * **`kling-2.6`**: Supports 1080p. * **`kling-3.0`**: Supports 720p, 1080p, 4k. * **`ltx-2.5`**: Supports 480p, 720p, 1080p. - * **`minimax-h3`**: Not supported + * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. Requires a duration of 8 seconds or less. diff --git a/magic_hour/types/params/v1_text_to_video_create_body.py b/magic_hour/types/params/v1_text_to_video_create_body.py index 40cbacb..215bc33 100644 --- a/magic_hour/types/params/v1_text_to_video_create_body.py +++ b/magic_hour/types/params/v1_text_to_video_create_body.py @@ -21,7 +21,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): typing_extensions.Literal["16:9", "1:1", "9:16"] ] """ - Determines the aspect ratio of the output video. + Provide `aspect_ratio` to set the video’s aspect ratio. Determines the aspect ratio of the output video. * **`gemini-omni-1.1`**: Supports 16:9, 9:16. * **`kling-2.6`**: Supports 9:16, 16:9, 1:1. @@ -30,6 +30,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: Supports 16:9, 9:16, 1:1. * **`seedance-1.5`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0`**: Supports 9:16, 16:9, 1:1. + * **`seedance-2.0-fast`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.0-mini`**: Supports 9:16, 16:9, 1:1. * **`seedance-2.5`**: Supports 9:16, 16:9, 1:1. * **`veo3.1`**: Supports 9:16, 16:9. @@ -51,6 +52,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: Toggle-able: no additional credits for audio * **`seedance-1.5`**: Toggle-able: audio adds extra credits when enabled * **`seedance-2.0`**: Toggle-able: no additional credits for audio + * **`seedance-2.0-fast`**: Toggle-able: no additional credits for audio * **`seedance-2.0-mini`**: Toggle-able: no additional credits for audio * **`seedance-2.5`**: Toggle-able: no additional credits for audio * **`veo3.1`**: Toggle-able: audio adds extra credits when enabled @@ -71,6 +73,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: any integer from 1 to 30 * **`seedance-1.5`**: any integer from 4 to 12 * **`seedance-2.0`**: any integer from 4 to 15 + * **`seedance-2.0-fast`**: any integer from 4 to 15 * **`seedance-2.0-mini`**: any integer from 4 to 15 * **`seedance-2.5`**: any integer from 4 to 30 * **`veo3.1`**: 4, 6, 8, 16, 24, 32, 40, 48, 56 @@ -96,6 +99,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", @@ -117,6 +121,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): * `minimax-h3`: Great for reference-driven clips with native audio and longer durations. * `seedance-1.5`: Best for smooth, consistent motion with an end frame. * `seedance-2.0`: Best for reference-led clips with precise subject control. + * `seedance-2.0-fast`: Fast reference-led clips with consistent motion and audio. * `seedance-2.0-mini`: Faster reference-led clips with consistent motion and audio. * `seedance-2.5`: Best for premium realism, detail, and natural motion. * `veo3.1`: Best for romantic interactions and expressive action, with realistic detail. @@ -146,11 +151,14 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): Reference media for video generation. Name references without @ and refer to them as @name in style.prompt. Maximum 10 references total. Supported models and reference media: + * **`gemini-omni-1.1`**: Supports images, videos. Up to 13 references. * **`kling-3.0`**: Supports images, videos. * **`minimax-h3`**: Supports images, videos, audio. * **`seedance-2.0`**: Supports images, videos, audio. + * **`seedance-2.0-fast`**: Supports images, videos, audio. * **`seedance-2.0-mini`**: Supports images, videos, audio. * **`seedance-2.5`**: Supports images, videos, audio. + * **`veo3.1`**: Supports images. Up to 3 references. Requires `end_seconds` of 8. * **`wan-3.0`**: Supports images, videos, audio. """ @@ -167,6 +175,7 @@ class V1TextToVideoCreateBody(typing_extensions.TypedDict): * **`minimax-h3`**: Supports 480p, 720p, 1080p. * **`seedance-1.5`**: Supports 480p, 720p, 1080p. * **`seedance-2.0`**: Supports 480p, 720p, 1080p, 4k. + * **`seedance-2.0-fast`**: Supports 480p, 720p. * **`seedance-2.0-mini`**: Supports 480p, 720p. * **`seedance-2.5`**: Supports 480p, 720p, 1080p. * **`veo3.1`**: Supports 720p, 1080p. @@ -212,6 +221,7 @@ class _SerializerV1TextToVideoCreateBody(pydantic.BaseModel): "seedance", "seedance-1.5", "seedance-2.0", + "seedance-2.0-fast", "seedance-2.0-mini", "seedance-2.5", "sora-2", diff --git a/pyproject.toml b/pyproject.toml index a4faa4b..a418f8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "magic_hour" -version = "0.87.1" +version = "0.88.0" description = "Python SDK for Magic Hour API" readme = "README.md" authors = [] diff --git a/tests/test_v1_ai_talking_photo_client.py b/tests/test_v1_ai_talking_photo_client.py index 0bccb6b..df72d7c 100644 --- a/tests/test_v1_ai_talking_photo_client.py +++ b/tests/test_v1_ai_talking_photo_client.py @@ -33,8 +33,9 @@ def test_create_200_success_all_params() -> None: }, end_seconds=5.0, start_seconds=0.0, - max_resolution=512, + max_resolution=123, name="My Talking Photo video", + resolution="480p", style={ "generation_mode": "realistic", "intensity": 123.45, @@ -79,8 +80,9 @@ async def test_await_create_200_success_all_params() -> None: }, end_seconds=5.0, start_seconds=0.0, - max_resolution=512, + max_resolution=123, name="My Talking Photo video", + resolution="480p", style={ "generation_mode": "realistic", "intensity": 123.45, diff --git a/tests/test_v1_ai_ugc_ad_client.py b/tests/test_v1_ai_ugc_ad_client.py new file mode 100644 index 0000000..b861dd0 --- /dev/null +++ b/tests/test_v1_ai_ugc_ad_client.py @@ -0,0 +1,77 @@ +import pydantic +import pytest + +from magic_hour import AsyncClient, Client +from magic_hour.environment import Environment +from magic_hour.types import models + + +def test_create_200_success_all_params() -> None: + """Tests a POST request to the /v1/ai-ugc-ad endpoint. + + Operation: create + Test Case ID: success_all_params + Expected Status: 200 + Mode: Synchronous execution + + Response : models.V1AiUgcAdCreateResponse + + Validates: + - Authentication requirements are satisfied + - All required input parameters are properly handled + - Response status code is correct + - Response data matches expected schema + + This test uses example data to verify the endpoint behavior. + """ + # tests calling sync method with example data + client = Client(token="API_TOKEN", environment=Environment.MOCK_SERVER) + response = client.v1.ai_ugc_ad.create( + assets={"image_file_path": "api-assets/id/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", + model="kling-3.0", + resolution="1080p", + ) + try: + pydantic.TypeAdapter(models.V1AiUgcAdCreateResponse).validate_python(response) + is_valid_response_schema = True + except pydantic.ValidationError: + is_valid_response_schema = False + assert is_valid_response_schema, "failed response type check" + + +@pytest.mark.asyncio +async def test_await_create_200_success_all_params() -> None: + """Tests a POST request to the /v1/ai-ugc-ad endpoint. + + Operation: create + Test Case ID: success_all_params + Expected Status: 200 + Mode: Asynchronous execution + + Response : models.V1AiUgcAdCreateResponse + + Validates: + - Authentication requirements are satisfied + - All required input parameters are properly handled + - Response status code is correct + - Response data matches expected schema + + This test uses example data to verify the endpoint behavior. + """ + # tests calling async method with example data + client = AsyncClient(token="API_TOKEN", environment=Environment.MOCK_SERVER) + response = await client.v1.ai_ugc_ad.create( + assets={"image_file_path": "api-assets/id/image.jpg"}, + end_seconds=4.0, + script="Meet your new everyday essential.", + model="kling-3.0", + resolution="1080p", + ) + try: + pydantic.TypeAdapter(models.V1AiUgcAdCreateResponse).validate_python(response) + is_valid_response_schema = True + except pydantic.ValidationError: + is_valid_response_schema = False + assert is_valid_response_schema, "failed response type check"