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
38 changes: 37 additions & 1 deletion .sdk.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "8edb506f-a1f6-47a0-bbd1-318c71e84e5a",
"id": "88e585d6-f705-42ee-a9cf-1e80c832f4c3",
"tracked_paths": [
{
"editable": true,
Expand Down Expand Up @@ -289,6 +289,22 @@
"editable": true,
"path": "src/resources/v1/auto-subtitle-generator/resource-client.ts"
},
{
"editable": true,
"path": "src/resources/v1/body-swap/README.md"
},
{
"editable": true,
"path": "src/resources/v1/body-swap/index.ts"
},
{
"editable": false,
"path": "src/resources/v1/body-swap/request-types.ts"
},
{
"editable": true,
"path": "src/resources/v1/body-swap/resource-client.ts"
},
{
"editable": true,
"path": "src/resources/v1/face-detection/README.md"
Expand Down Expand Up @@ -833,6 +849,22 @@
"editable": false,
"path": "src/types/v1-auto-subtitle-generator-create-response.ts"
},
{
"editable": false,
"path": "src/types/v1-body-swap-create-body-assets.ts"
},
{
"editable": false,
"path": "src/types/v1-body-swap-create-body-resolution-enum.ts"
},
{
"editable": false,
"path": "src/types/v1-body-swap-create-body.ts"
},
{
"editable": false,
"path": "src/types/v1-body-swap-create-response.ts"
},
{
"editable": false,
"path": "src/types/v1-face-detection-create-body-assets.ts"
Expand Down Expand Up @@ -1185,6 +1217,10 @@
"editable": false,
"path": "test/v1-auto-subtitle-generator.test.ts"
},
{
"editable": false,
"path": "test/v1-body-swap.test.ts"
},
{
"editable": false,
"path": "test/v1-face-detection.test.ts"
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ Valid values are: `none`, `error`, `warn`, `info`, `debug` (case insensitive). I
- [create](src/resources/v1/auto-subtitle-generator/README.md#create) - Auto Subtitle Generator
- [generate](src/resources/v1/auto-subtitle-generator/README.md#generate) - Auto Subtitle Generator Generate Workflow

### [v1.bodySwap](src/resources/v1/body-swap/README.md)

- [create](src/resources/v1/body-swap/README.md#create) - Body Swap
- [generate](src/resources/v1/body-swap/README.md#generate) - Body Swap Generate Workflow

### [v1.faceDetection](src/resources/v1/face-detection/README.md)

- [create](src/resources/v1/face-detection/README.md#create) - Face Detection
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "magic-hour",
"version": "0.60.0",
"version": "0.61.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
Expand Down
1 change: 1 addition & 0 deletions src/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-photo](resources/v1/face-swap-photo/README.md) - face-swap-photo
- [face-swap](resources/v1/face-swap/README.md) - face-swap
Expand Down
2 changes: 1 addition & 1 deletion src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export enum Environment {
Environment = "https://api.magichour.ai",
MockServer = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.61.1",
MockServer = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.62.0",
}
1 change: 1 addition & 0 deletions src/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 src/resources/v1/ai-image-generator/README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/resources/v1/ai-image-generator/request-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type CreateRequest = {
* - `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
94 changes: 94 additions & 0 deletions src/resources/v1/body-swap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# 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 addition to the parameters listed in the `create` section below, `generate` introduces 3 new parameters:

- `waitForCompletion` (boolean, default true): Whether to wait for the project to complete.
- `downloadOutputs` (boolean, default true): Whether to download the generated files
- `downloadDirectory` (string, optional): Directory to save downloaded files (defaults to current directory)

#### Example Snippet

```typescript
import { Client } from "magic-hour";

const client = new Client({ token: process.env["API_TOKEN"]!! });
const res = await client.v1.bodySwap.generate(
{
assets: {
personFilePath: "/path/to/person.png",
sceneFilePath: "/path/to/scene.png",
},
name: "My Body Swap image",
resolution: "1k",
},
{
waitForCompletion: true,
downloadOutputs: true,
downloadDirectory: ".",
},
);
```

<!-- 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 | `{"personFilePath": "api-assets/id/1234.png", "sceneFilePath": "api-assets/id/5678.png"}` |
| `└─ personFilePath` | ✓ | 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"` |
| `└─ sceneFilePath` | ✓ | 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"` |

#### Example Snippet

```typescript
import { Client } from "magic-hour";

const client = new Client({ token: process.env["API_TOKEN"]!! });
const res = await client.v1.bodySwap.create({
assets: {
personFilePath: "api-assets/id/1234.png",
sceneFilePath: "api-assets/id/5678.png",
},
name: "My Body Swap image",
resolution: "1k",
});
```

#### Response

##### Type

[V1BodySwapCreateResponse](/src/types/v1-body-swap-create-response.ts)

##### Example

```typescript
{"creditsCharged": 100, "frameCost": 100, "id": "cuid-example"}
```
2 changes: 2 additions & 0 deletions src/resources/v1/body-swap/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { CreateRequest } from "./request-types";
export { BodySwapClient } from "./resource-client";
85 changes: 85 additions & 0 deletions src/resources/v1/body-swap/request-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { zodTransform } from "make-api-request-js";
import * as z from "zod";

import {
External$V1BodySwapCreateBodyAssets,
Schemas$V1BodySwapCreateBodyAssets,
V1BodySwapCreateBodyAssets,
} from "magic-hour/types/v1-body-swap-create-body-assets";

/**
* CreateRequest
*/
export type CreateRequest = {
/**
* Person image and scene image for body swap
*/
assets: V1BodySwapCreateBodyAssets;
/**
* Give your image a custom name for easy identification.
*/
name?: string | undefined;
/**
* Output resolution. Determines credits charged for the run.
*/
resolution: "1k" | "2k" | "4k" | "640px";
};

/**
* @internal
* CreateRequest without any key transformation, this is what
* we expect to come in as network data
*/
export type External$CreateRequest = {
assets: External$V1BodySwapCreateBodyAssets;
name?: string | undefined;
resolution: "1k" | "2k" | "4k" | "640px";
};

/**
* Takes network data, validates it, and transforms keys to match typescript object CreateRequest
*/
const SchemaIn$CreateRequest: z.ZodType<
CreateRequest, // output type of this zod object
z.ZodTypeDef,
unknown
> = z
.object({
assets: Schemas$V1BodySwapCreateBodyAssets.in,
name: z.string().optional(),
resolution: z.enum(["1k", "2k", "4k", "640px"]),
})
.transform((obj) => {
return zodTransform(obj, {
assets: "assets",
name: "name",
resolution: "resolution",
});
});

/**
* @internal
* Takes typescript data, validates it, and maps keys to match the expected external object External$CreateRequest
*/
const SchemaOut$CreateRequest: z.ZodType<
External$CreateRequest, // output type of this zod object
z.ZodTypeDef,
CreateRequest // the object to be transformed
> = z
.object({
assets: Schemas$V1BodySwapCreateBodyAssets.out,
name: z.string().optional(),
resolution: z.enum(["1k", "2k", "4k", "640px"]),
})
.transform((obj) => {
return zodTransform(obj, {
assets: "assets",
name: "name",
resolution: "resolution",
});
});

export const Schemas$CreateRequest = {
in: SchemaIn$CreateRequest,
out: SchemaOut$CreateRequest,
};
Loading
Loading