Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion .sdk.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "a99332c4-395a-42e0-8a2d-833989f9bf84",
"id": "1be4520e-0bec-4a18-81cf-2488a9d303f8",
"tracked_paths": [
{
"editable": true,
Expand Down Expand Up @@ -209,6 +209,18 @@
"editable": true,
"path": "magic_hour/resources/v1/auto_subtitle_generator/client.py"
},
{
"editable": true,
"path": "magic_hour/resources/v1/body_swap/README.md"
},
{
"editable": true,
"path": "magic_hour/resources/v1/body_swap/__init__.py"
},
{
"editable": true,
"path": "magic_hour/resources/v1/body_swap/client.py"
},
{
"editable": true,
"path": "magic_hour/resources/v1/client.py"
Expand Down Expand Up @@ -453,6 +465,10 @@
"editable": false,
"path": "magic_hour/types/models/v1_auto_subtitle_generator_create_response.py"
},
{
"editable": false,
"path": "magic_hour/types/models/v1_body_swap_create_response.py"
},
{
"editable": false,
"path": "magic_hour/types/models/v1_face_detection_create_response.py"
Expand Down Expand Up @@ -689,6 +705,14 @@
"editable": false,
"path": "magic_hour/types/params/v1_auto_subtitle_generator_create_body_style_custom_config.py"
},
{
"editable": false,
"path": "magic_hour/types/params/v1_body_swap_create_body.py"
},
{
"editable": false,
"path": "magic_hour/types/params/v1_body_swap_create_body_assets.py"
},
{
"editable": false,
"path": "magic_hour/types/params/v1_face_detection_create_body.py"
Expand Down Expand Up @@ -865,6 +889,10 @@
"editable": false,
"path": "tests/test_v1_auto_subtitle_generator_client.py"
},
{
"editable": false,
"path": "tests/test_v1_body_swap_client.py"
},
{
"editable": false,
"path": "tests/test_v1_face_detection_client.py"
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ download_urls = result.downloads
- [create](magic_hour/resources/v1/auto_subtitle_generator/README.md#create) - Auto Subtitle Generator
- [generate](magic_hour/resources/v1/auto_subtitle_generator/README.md#generate) - Auto Subtitle Generator Generate Workflow

### [v1.body_swap](magic_hour/resources/v1/body_swap/README.md)

- [create](magic_hour/resources/v1/body_swap/README.md#create) - Body Swap
- [generate](magic_hour/resources/v1/body_swap/README.md#generate) - Body Swap Generate Workflow

### [v1.face_detection](magic_hour/resources/v1/face_detection/README.md)

- [create](magic_hour/resources/v1/face_detection/README.md#create) - Face Detection
Expand Down
1 change: 1 addition & 0 deletions magic_hour/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- [animation](resources/v1/animation/README.md) - animation
- [audio_projects](resources/v1/audio_projects/README.md) - audio_projects
- [auto_subtitle_generator](resources/v1/auto_subtitle_generator/README.md) - auto_subtitle_generator
- [body_swap](resources/v1/body_swap/README.md) - body_swap
- [face_detection](resources/v1/face_detection/README.md) - face_detection
- [face_swap](resources/v1/face_swap/README.md) - face_swap
- [face_swap_photo](resources/v1/face_swap_photo/README.md) - face_swap_photo
Expand Down
2 changes: 1 addition & 1 deletion magic_hour/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.61.1"
MOCK_SERVER = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.62.0"


def _get_base_url(
Expand Down
1 change: 1 addition & 0 deletions magic_hour/resources/v1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- [animation](animation/README.md) - animation
- [audio_projects](audio_projects/README.md) - audio_projects
- [auto_subtitle_generator](auto_subtitle_generator/README.md) - auto_subtitle_generator
- [body_swap](body_swap/README.md) - body_swap
- [face_detection](face_detection/README.md) - face_detection
- [face_swap](face_swap/README.md) - face_swap
- [face_swap_photo](face_swap_photo/README.md) - face_swap_photo
Expand Down
24 changes: 12 additions & 12 deletions magic_hour/resources/v1/ai_image_generator/README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions magic_hour/resources/v1/ai_image_generator/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def create(
- `nano-banana-2` - from 100 credits/image
- Supported resolutions: 640px, 1k, 2k, 4k
- Available for tiers: free, creator, pro, business
- Image count allowed: 1, 2, 3, 4
- Image count allowed: 1, 4, 9, 16
- `nano-banana-pro` - from 150 credits/image
- Supported resolutions: 1k, 2k, 4k
- Available for tiers: creator, pro, business
Expand Down Expand Up @@ -432,7 +432,7 @@ async def create(
- `nano-banana-2` - from 100 credits/image
- Supported resolutions: 640px, 1k, 2k, 4k
- Available for tiers: free, creator, pro, business
- Image count allowed: 1, 2, 3, 4
- Image count allowed: 1, 4, 9, 16
- `nano-banana-pro` - from 150 credits/image
- Supported resolutions: 1k, 2k, 4k
- Available for tiers: creator, pro, business
Expand Down
129 changes: 129 additions & 0 deletions magic_hour/resources/v1/body_swap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# v1.body_swap

## Module Functions

<!-- CUSTOM DOCS START -->

### Body Swap Generate Workflow <a name="generate"></a>

The workflow performs the following action

1. upload local assets to Magic Hour storage. So you can pass in a local path instead of having to upload files yourself
2. trigger a generation
3. poll for a completion status. This is configurable
4. if success, download the output to local directory

> [!TIP]
> This is the recommended way to use the SDK unless you have specific needs where it is necessary to split up the actions.

#### Parameters

In Additional to the parameters listed in the `.create` section below, `.generate` introduces 3 new parameters:

- `wait_for_completion` (bool, default True): Whether to wait for the project to complete.
- `download_outputs` (bool, default True): Whether to download the generated files
- `download_directory` (str, optional): Directory to save downloaded files (defaults to current directory)

#### Synchronous Client

```python
from magic_hour import Client
from os import getenv

client = Client(token=getenv("API_TOKEN"))
res = client.v1.body_swap.generate(
assets={
"person_file_path": "/path/to/person.png",
"scene_file_path": "/path/to/scene.png",
},
resolution="1k",
name="My Body Swap image",
wait_for_completion=True,
download_outputs=True,
download_directory=".",
)
```

#### Asynchronous Client

```python
from magic_hour import AsyncClient
from os import getenv

client = AsyncClient(token=getenv("API_TOKEN"))
res = await client.v1.body_swap.generate(
assets={
"person_file_path": "/path/to/person.png",
"scene_file_path": "/path/to/scene.png",
},
resolution="1k",
name="My Body Swap image",
wait_for_completion=True,
download_outputs=True,
download_directory=".",
)
```

<!-- CUSTOM DOCS END -->

### Body Swap <a name="create"></a>

Swap a person into a scene image using Nano Banana 2. Credits depend on `resolution` (from 100 credits at 640px upward).

**API Endpoint**: `POST /v1/body-swap`

#### Parameters

| Parameter | Required | Description | Example |
| --------------------- | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `assets` | ✓ | Person image and scene image for body swap | `{"person_file_path": "api-assets/id/1234.png", "scene_file_path": "api-assets/id/5678.png"}` |
| `└─ person_file_path` | ✓ | Image of the person to place into the scene. 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"` |
| `└─ scene_file_path` | ✓ | Target scene image (background). 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/5678.png"` |
| `resolution` | ✓ | Output resolution. Determines credits charged for the run. | `"1k"` |
| `name` | ✗ | Give your image a custom name for easy identification. | `"My Body Swap image"` |

#### Synchronous Client

```python
from magic_hour import Client
from os import getenv

client = Client(token=getenv("API_TOKEN"))
res = client.v1.body_swap.create(
assets={
"person_file_path": "api-assets/id/1234.png",
"scene_file_path": "api-assets/id/5678.png",
},
resolution="1k",
name="My Body Swap image",
)
```

#### Asynchronous Client

```python
from magic_hour import AsyncClient
from os import getenv

client = AsyncClient(token=getenv("API_TOKEN"))
res = await client.v1.body_swap.create(
assets={
"person_file_path": "api-assets/id/1234.png",
"scene_file_path": "api-assets/id/5678.png",
},
resolution="1k",
name="My Body Swap image",
)
```

#### Response

##### Type

[V1BodySwapCreateResponse](/magic_hour/types/models/v1_body_swap_create_response.py)

##### Example

```python
{"credits_charged": 100, "frame_cost": 100, "id": "cuid-example"}
```
4 changes: 4 additions & 0 deletions magic_hour/resources/v1/body_swap/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .client import AsyncBodySwapClient, BodySwapClient


__all__ = ["AsyncBodySwapClient", "BodySwapClient"]
Loading
Loading