MiniMax H3 Open Weights | Try in Video Generator →

Video Head Swap | AI Portrait Transfer API

wavespeed-ai/

Instant online AI head & face swap for videos with no watermark, delivering realistic, shareable results in seconds. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.

portrait-transfer
Input

Idle

$0.2per run·~50 / $10

ExamplesView all

Related Models

README

WaveSpeedAI Video Head Swap

WaveSpeedAI Video Head Swap is an advanced AI model for replacing the entire head (face + hair + outline) of a person in a video using a reference portrait. The model keeps the body, pose, and background intact while reconstructing a new, realistic head that matches the original lighting and perspective.

🎬 What this model does

  • Replaces the full head region of the subject (face, hair, silhouette, accessories)
  • Preserves body pose, clothing, background, and overall composition
  • Adapts the new head to scene lighting, color tone, and camera angle
  • Produces clean, watermark-free outputs ready for editing or publication

⚙️ Why it looks realistic

  • Full-head geometry replacement Swaps the entire head contour instead of only facial features, avoiding mismatched hairlines or distorted skull shapes.

  • Pose and expression preservation Follows the motion in the source video so head angle, gaze direction, and expression remain consistent with the original performance.

  • Lighting and color matching Automatically adjusts skin tone, shadows, and highlights so the new head blends naturally into the scene.

  • High-resolution blending Smooth transitions around hair, neck, and accessories, minimizing visible seams or flicker across frames.

💰 Pricing

Pricing is based on video duration and output resolution, with a 5-second minimum and 120-second cap.

ResolutionPrice per secondMin charge (5 s)Max charge (120 s)
480p$0.040$0.200$4.800
720p$0.080$0.400$9.600
  • Minimum billed duration: 5 seconds
  • Maximum billed duration: 120 seconds per run (longer clips are capped at 120 s)

🔧 Input Parameters

video (required)

The source video whose head you want to replace. This defines body motion, framing, and background.

face_image / head_image (required)

A clear portrait of the target identity. Frontal or three-quarter views with good lighting work best.

resolution

Output resolution for the processed video, for example:

  • 480p – more affordable drafts or quick previews
  • 720p – higher-quality output suitable for most publishing workflows

seed (optional)

Controls stochastic variation in generation:

  • -1 or empty → random seed each run
  • Any positive integer → reproducible results for the same inputs

(Exact field name may differ between Playground and API, but behavior is identical.)

🎯 Designed For

  • Creators & influencers – Turn one performance into many identities without reshooting.
  • Marketing & brands – Localize or personalize talking-head content while keeping the same body and scene.
  • Film, TV & post-production – Rapid previs, mockups, and concept tests for head-replacement shots.
  • Privacy & compliance – Replace real heads with synthetic or authorized identities while preserving situational context.

▶️ How to Use

  1. Upload or paste the URL of the video to edit.
  2. Upload a face/head reference image for the identity you want to swap in.
  3. Select the output resolution (480p or 720p).
  4. (Optional) Set a seed if you need reproducible results.
  5. Click Run to generate the swapped video.
  6. Review the result; if needed, adjust the reference portrait or seed and run again.

📌 Tips & Notes

  • Use sharp, well-lit videos where the face is not heavily occluded or motion-blurred.
  • For the reference portrait, keep expression and angle reasonably close to the target shot for the cleanest match.
  • Avoid extreme mismatches in lighting (e.g., dark blue stage light in video vs. warm daylight portrait) unless you want a stylized look.
  • Ensure you have the legal right and consent to use all uploaded videos and portraits.
Note:This website uses AI models provided by third parties.

Video Head Swap API — Quick start

Grab a WaveSpeedAI API key, then call POST https://api.wavespeed.ai/api/v3/wavespeed-ai/video-head-swap with your input as JSON. The endpoint returns a prediction id. Start polling the result endpoint around every 2 seconds, increase the interval for long-running tasks, and stop on any terminal status. On completed, read output values from data.outputs. Examples for Video Head Swap below.

HTTP example
set -euo pipefail

: "${WAVESPEED_API_KEY:?Set WAVESPEED_API_KEY}"

REQUEST_BODY=$(cat <<'JSON'
{
    "video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
    "face_image": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg",
    "resolution": "480p",
    "seed": -1
}
JSON
)

# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
  -X POST "https://api.wavespeed.ai/api/v3/wavespeed-ai/video-head-swap" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $WAVESPEED_API_KEY" \
  -d "$REQUEST_BODY")

TASK=$(printf '%s' "$SUBMIT_RESPONSE" | jq 'if has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "$TASK" | jq -r '.id')
if [ -z "$PREDICTION_ID" ] || [ "$PREDICTION_ID" = "null" ]; then
  printf 'Submission response did not contain a prediction id
' >&2
  exit 1
fi
RESULT_URL=$(printf '%s' "$TASK" | jq -r '.urls.get // empty')
if [ -z "$RESULT_URL" ]; then
  RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/$PREDICTION_ID/result"
fi

# 2. Poll until the prediction finishes.
while true; do
  RESPONSE=$(curl --silent --show-error --fail-with-body "$RESULT_URL" \
    -H "Authorization: Bearer $WAVESPEED_API_KEY")
  RESULT=$(printf '%s' "$RESPONSE" | jq 'if has("data") then .data else . end')
  STATUS=$(printf '%s' "$RESULT" | jq -r '.status')
  case "$STATUS" in
    completed) printf '%s\n' "$RESULT" | jq '.outputs'; break ;;
    failed|cancelled|timeout) printf '%s\n' "$RESULT" | jq . >&2; exit 1 ;;
    created|processing) sleep 2 ;;
    *) printf 'Unexpected status: %s
' "$STATUS" >&2; exit 1 ;;
  esac
done
Node.js example
const submitUrl = "https://api.wavespeed.ai/api/v3/wavespeed-ai/video-head-swap";
const apiKey = process.env.WAVESPEED_API_KEY;
if (!apiKey) throw new Error('Set WAVESPEED_API_KEY');

async function requestJson(url, options = {}) {
  const response = await fetch(url, options);
  if (!response.ok) throw new Error(await response.text());
  return response.json();
}

// 1. Submit the prediction.
const body = await requestJson(submitUrl, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
        "video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
        "face_image": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg",
        "resolution": "480p",
        "seed": -1
}),
});
const task = body.data ?? body;
if (!task.id) throw new Error("Submission response did not contain a prediction id");
const resultUrl = task.urls?.get ||
  `https://api.wavespeed.ai/api/v3/predictions/${task.id}/result`;

// 2. Poll until the prediction finishes.
while (true) {
  const resultBody = await requestJson(resultUrl, {
    headers: { "Authorization": `Bearer ${apiKey}` },
  });
  const result = resultBody.data ?? resultBody;
  if (result.status === "completed") {
    console.log(result.outputs);
    break;
  }
  if (["failed", "cancelled", "timeout"].includes(result.status)) throw new Error(JSON.stringify(result));
  if (!["created", "processing"].includes(result.status)) throw new Error("Unexpected status: " + result.status);
  await new Promise(resolve => setTimeout(resolve, 2000));
}
Python example
import json
import os
import time
from urllib.request import Request, urlopen

api_key = os.environ["WAVESPEED_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
payload = {
    "video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
    "face_image": "https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg",
    "resolution": "480p",
    "seed": -1
}

def request_json(url, data=None):
    request = Request(url, data=data, headers=headers, method="POST" if data else "GET")
    with urlopen(request) as response:
        return json.load(response)

# 1. Submit the prediction.
body = request_json("https://api.wavespeed.ai/api/v3/wavespeed-ai/video-head-swap", json.dumps(payload).encode())
task = body.get("data", body)
if not task.get("id"):
    raise RuntimeError("Submission response did not contain a prediction id")
result_url = task.get("urls", {}).get("get") or f"https://api.wavespeed.ai/api/v3/predictions/{task['id']}/result"

# 2. Poll until the prediction finishes.
while True:
    result_body = request_json(result_url)
    result = result_body.get("data", result_body)
    status = result.get("status")
    if status == "completed":
        print(result.get("outputs", []))
        break
    if status in {"failed", "cancelled", "timeout"}:
        raise RuntimeError(result)
    if status not in {"created", "processing"}:
        raise RuntimeError(f"Unexpected status: {status}")
    time.sleep(2)

Video Head Swap API — Frequently asked questions

What is the Video Head Swap API?

Video Head Swap is a WaveSpeedAI model for AI inference, exposed as a REST API on WaveSpeedAI. Instant online AI head & face swap for videos with no watermark, delivering realistic, shareable results in seconds. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing. You can call it programmatically or try it from the playground above.

How do I call the Video Head Swap API?

POST your input parameters to the model's REST endpoint (shown in the API tab of this playground) with your WaveSpeedAI API key in the Authorization header. Submission returns a prediction ID. Poll the result endpoint starting around every 2 seconds, increase the interval for long-running tasks, and stop on any terminal status. The playground generates production-oriented Python, JavaScript, and cURL examples with timeouts, transient-error handling, and safe GET retries. Full request/response shape is documented at https://wavespeed.ai/docs/docs-api/wavespeed-ai/video-head-swap.

How much does Video Head Swap cost per run?

Video Head Swap starts at $0.20 per run. That figure is the base price — the final charge scales with the parameters you set in the form (output size, length, count, references, or whatever knobs this model exposes), so a higher-quality or larger output costs more than a minimal one. The exact cost for your current input is shown live next to the Generate button before you submit, and the actual per-call charge is recorded on the prediction afterwards.

What inputs does Video Head Swap accept?

Key inputs: `prompt`, `video`, `resolution`, `seed`, `face_image`. The full JSON schema (types, defaults, allowed values) is rendered above the Generate button and mirrored in the API reference at https://wavespeed.ai/docs/docs-api/wavespeed-ai/video-head-swap.

How do I get started with the Video Head Swap API?

Sign up for a free WaveSpeedAI account to claim starter credits, copy your API key from /accesskey, then call the endpoint shown in the API tab of the playground. The playground also auto-generates a code sample in Python, JavaScript, or cURL for the parameters you've set.

Can I use Video Head Swap outputs commercially?

Commercial usage rights depend on the model's license, set by its provider (WaveSpeedAI). The license summary appears on the model card above; see WaveSpeedAI's Terms of Service for platform-level conditions.

Video Head Swap | AI Portrait Transfer API on WaveSpeedAI