> ## Documentation Index
> Fetch the complete documentation index at: https://docs.magichour.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Face Swap Video API

> Replace faces in videos with frame-by-frame precision and temporal consistency.

export const ToolSection = ({type = "image", outputs = [], title = "", productSlug = "", apiSlug = ""}) => <>
    <CardGroup cols={2}>
      <Card title={`${title} API reference`} icon="webhook" horizontal href={`/api-reference/${type}-projects/${apiSlug}`}>
        Request fields, responses, and examples
      </Card>
      <Card title="API quickstart" icon="forward-fast" horizontal href="/get-started/quick-start">
        Install an SDK and complete your first generation
      </Card>
    </CardGroup>

    <p>
      Check <a href="/billing/overview">API pricing</a> and <a href="/api-reference/models">model credit costs</a>, then <a href={`https://magichour.ai/developer?tab=api-keys&ref=docs-tool-${apiSlug}&utm_source=docs&utm_medium=referral&utm_campaign=tools`}>create an API key</a>.
    </p>
    <p>
      To try {title} without code, use the <a href={`https://magichour.ai/products/${productSlug}${productSlug.includes("?") ? "&" : "?"}utm_source=docs&utm_medium=referral&utm_campaign=tools`}>browser tool</a>.
    </p>

    {outputs && outputs.length > 0 && <Tabs>
        {outputs.map((output, idx) => <Tab key={idx} title={`Example Output ${idx + 1}`}>
            <Frame>
              {type === "video" ? <video controls preload="metadata" playsInline className="rounded-lg h-80" src={`${output.src}#t=0.001`} type={`${output.src?.endsWith("mp4") ? 'video/mp4' : "video/webm"}`}>
                </video> : type === "audio" ? <audio controls preload="metadata" className="w-full" src={output.src}>
                  Your browser does not support the audio element.
                </audio> : <img height="320" className="rounded-lg h-80" src={output.src} alt={`${title} example output ${idx + 1}`} />}
            </Frame>
          </Tab>)}
      </Tabs>}

  </>;

## Overview

Face Swap Video replaces faces in videos with frame-by-frame precision and temporal consistency. The API swaps faces throughout video sequences while maintaining natural expressions, head movements, and lighting for realistic results.

**Processing:** See recent [typical API-job times](/api-reference/processing-times). Jobs run
asynchronously, and duration varies with the input, selected settings, and queue load.

<ToolSection
  title="Face Swap Video"
  productSlug="face-swap/video"
  apiSlug="face-swap-video"
  type="video"
  outputs={[
{
  src: "https://videos.magichour.ai/clttqdcuq000fqp36h8i8bapl/video.mp4",
},
{
  src: "https://videos.magichour.ai/cltw1ygmc0027rck4x1lrmrqs/video.mp4",
},
]}
/>

## How It Works

1. **Provide a source face** - Upload an image containing the face you want to use
2. **Provide a target video** - Upload the video where you want to swap the face
3. **Set start/end times** - Define which portion of the video to process
4. **API processes frame-by-frame** - AI swaps the face consistently across all frames
5. **Download the result** - Retrieve your face-swapped video

## Use Cases

* **Entertainment content** - Create viral videos and memes
* Try alternate faces for a scene.
* **Film and media** - Character replacement in post-production
* **Personalized experiences** - Custom video messages and greetings
* **Marketing** - Create personalized ad experiences

## Best Practices

### Source Face Image

<Tip>
  **Use a clear, high-quality face photo** - The better your source image, the better the swap
  quality.
</Tip>

* **Front-facing or slight angle** - Avoid extreme profile shots
* **Good lighting** - Even lighting with no harsh shadows
* **High resolution** - At least 512x512 pixels for the face area
* **Neutral expression** - Works best for most video expressions
* **No obstructions** - Avoid sunglasses, masks, or hair covering face

### Target Video Requirements

* **Clear face visibility** - Face should be clearly visible in the video
* **Stable lighting** - Consistent lighting throughout produces best results
* **One primary face** - Works best when targeting a single person
* **Moderate motion** - Extreme head movements may affect quality

### Multiple faces and versions

The default `assets.face_swap_mode="all-faces"` uses one `image_file_path` to replace every detected face. To target particular people, use `individual-faces` with up to five `face_mappings`, obtained using the [face detection API](/api-reference/files/get-face-detection-details).

`style.version="default"` follows the recommended version over time. Set `v1` or `v2` when you need a specific version. Deprecated `width` and `height` fields do not control output resolution.

### Video Segment Selection

| Factor     | Recommendation                              |
| :--------- | :------------------------------------------ |
| Duration   | Start with 5-10 seconds to test quality     |
| Face size  | Larger faces in frame = better results      |
| Motion     | Moderate movement works best                |
| Occlusions | Avoid frames where face is partially hidden |

## Code Examples

### Basic Face Swap

<CodeGroup>
  ```python Python theme={null}
  from magic_hour import Client
  import os

  client = Client(token=os.getenv("MAGIC_HOUR_API_KEY"))

  result = client.v1.face_swap.generate(
      assets={
          "image_file_path": "https://raw.githubusercontent.com/runshouse/Sample_Assets/main/tomcruise.png",
          "video_file_path": "https://raw.githubusercontent.com/runshouse/Sample_Assets/main/obamamicdrop.mov",
          "video_source": "file"
      },
      start_seconds=0,
      end_seconds=2,
      name="Tom Cruise Face Swap",
      wait_for_completion=True,
      download_outputs=True,
      download_directory="."
  )

  if result.status == "complete":
      print(f"✅ Face swap complete!")
      print(f"Downloaded to: {result.downloaded_paths}")
      print(f"Credits charged: {result.credits_charged}")
  else:
      print(f"Job ended with status: {result.status}")
      if result.error:
          print(f"Error: {result.error.message}")
  ```

  ```javascript Node.js theme={null}
  import { Client } from "magic-hour";

  const client = new Client({ token: process.env.MAGIC_HOUR_API_KEY });

  const result = await client.v1.faceSwap.generate(
    {
      assets: {
        imageFilePath: "https://raw.githubusercontent.com/runshouse/Sample_Assets/main/tomcruise.png",
        videoFilePath:
          "https://raw.githubusercontent.com/runshouse/Sample_Assets/main/obamamicdrop.mov",
        videoSource: "file",
      },
      startSeconds: 0,
      endSeconds: 2,
      name: "Tom Cruise Face Swap",
    },
    {
      waitForCompletion: true,
      downloadOutputs: true,
      downloadDirectory: ".",
    }
  );

  if (result.status === "complete") {
    console.log(`✅ Face swap complete!`);
    console.log(`Downloaded to: ${result.downloadedPaths}`);
  } else {
    console.error(`Job ended with status: ${result.status}`);
    if (result.error) console.error(result.error.message);
  }
  ```
</CodeGroup>

## Pricing

Face Swap Video uses credits based on video duration and frame rate — credits are only charged for the frames that actually render:

| Factor     | Impact                      |
| :--------- | :-------------------------- |
| Duration   | More seconds = more credits |
| Frame rate | Higher FPS = more credits   |
| Resolution | Affects quality, not cost   |

The create response returns an estimated `credits_charged`; the final amount can change after rendering based on the actual output frame rate. Check the completed job's `credits_charged` for the exact cost.

## Error Handling

When a render fails, the video project returns `status="error"` with an `error` object containing `code` and `message`. For example, `no_source_face` means the source needs a detectable face. Check `result.error.message` for guidance; canceled jobs can have no error object. Request failures are reported separately as HTTP errors. See [Get Video Details](/api-reference/video-projects/get-video-details).

<Tip>
  **Try this in our Google Colab Cookbook:** [Run this API with sample
  code](https://colab.research.google.com/drive/1NTHL_lr_s-qBJ-mSecSXPzRLi9_V5JiU?usp=sharing). Just
  add your API key.
</Tip>

## API Reference

<Card title="Face Swap Video API Reference" icon="webhook" href="/api-reference/video-projects/face-swap-video">
  View full API specification
</Card>

## Related Tools

<CardGroup cols={2}>
  <Card title="Character Replace" icon="user" href="/tools/video/character-replace">
    Replace an entire person throughout a video
  </Card>

  <Card title="Face Swap Photo" icon="image" href="/tools/image/face-swap-photo">
    Swap faces in static images
  </Card>

  <Card title="Lip Sync" icon="lips" href="/tools/video/lip-sync">
    Sync audio with video lip movements
  </Card>
</CardGroup>
