Wan 2.1 Mocha API Documentation

Wan 2.1 Mocha API Documentation

Playground

Try it on WaveSpeedAI!

Wan 2.1 MoCha Video-to-Video Character Swap replaces a video’s character using reference images, preserving identity and motion without per-frame pose or depth maps for character replacement, avatar edits, creative videos, and production workflows. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.

Features

MoCha AI Video Character Replacement replaces the main character in a video with a new character provided through a reference image. It preserves the source video’s motion, facial expressions, lighting, and camera perspective while transferring the new character identity into the scene.

Unlike traditional workflows, MoCha does not require explicit per-frame structural inputs such as pose maps or depth maps. Provide a source video and a character image, then use an optional prompt to guide the replacement result.


Why Choose This?

  • Character replacement workflow
    Replace the main character in a video using a reference image.

  • Structure-free input
    No pose maps, depth maps, or manual frame-by-frame guidance are required.

  • Motion preservation
    Preserve the source actor’s body movement, facial expression, timing, and camera perspective.

  • Identity consistency
    Maintain the new character’s facial identity, appearance, and style across frames.

  • Simple setup
    Use one character image and one source video without complex preprocessing or rigging.

  • Flexible resolution options
    Choose 480p for lower-cost processing or 720p for higher-quality output.


Parameters

ParameterRequiredDescription
imageYesReference image of the new character. Use a clear JPG or PNG image when possible.
videoYesSource video containing the motion, expression, and camera perspective to preserve.
promptNoOptional text instruction to guide the replacement result, such as appearance details, preservation requirements, or style direction.
resolutionNoOutput resolution: 480p or 720p.
seedNoRandom seed for reproducible results. Use a fixed seed to reproduce similar outputs.

How to Use

  1. Upload a character image — Provide a clear reference image of the new character.
  2. Upload a source video — Provide the video whose motion, expression, and camera perspective should be preserved.
  3. Add a prompt optional — Describe what should be preserved or adjusted, such as outfit, lighting, background, or expression style.
  4. Choose resolution — Use 480p for lower-cost previews or 720p for higher-quality output.
  5. Set seed optional — Use a fixed seed when reproducibility is needed.
  6. Submit — Generate the character-replaced video.

Pricing

Pricing is based on input video duration and selected resolution.

Billed duration is rounded up to the next whole second, with a minimum billed duration of 3 seconds and a maximum billed duration of 120 seconds.

ResolutionPer 5sPer secondMax billed length
480p$0.20$0.04120s
720p$0.40$0.08120s

Example Costs

Input DurationBilled Duration480p720p
0.5s3s$0.12$0.24
3s3s$0.12$0.24
5s5s$0.20$0.40
30s30s$1.20$2.40
120s120s$4.80$9.60
150s120s$4.80$9.60

image, prompt, and seed do not add separate charges.


Best Use Cases

  • Character replacement — Swap the main character in a video with a new reference character.
  • Digital avatar videos — Create character-driven clips from existing performances.
  • Advertising and creative production — Replace performers or characters while preserving the original scene motion.
  • Film and concept tests — Prototype character variations without reshooting footage.
  • Social video creation — Generate character-transformed short videos for creative content.
  • Motion-preserving edits — Keep the original timing, action, and camera perspective while changing the character.

Pro Tips

  • Use a clear, well-lit reference image with the character’s face and body details visible.
  • Match the reference image’s angle, framing, and body orientation to the source video when possible.
  • Use a source video with clear subject motion and limited occlusion.
  • Keep the source video and reference image visually compatible for smoother replacement.
  • Add prompt instructions for what should remain unchanged, such as background, camera movement, lighting, or outfit style.
  • Use 480p for quick tests and 720p for higher-quality output.
  • For better stability, test with shorter clips before processing longer videos.

Notes

  • image and video are required.
  • Billed duration is rounded up and clamped to 3–120 seconds.
  • Videos longer than 120 seconds are billed at the 120-second cap.
  • The model is designed for replacing the main character in the source video.
  • Clear subject framing and consistent lighting improve replacement quality.

Authentication

For authentication details, please refer to the Authentication Guide.

API Endpoints

Submit Task & Query Result

set -euo pipefail

export WAVESPEED_API_KEY="your-api-key"

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

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

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

# 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 type == "object" and has("data") then .data else . end')
  STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')

  case "${STATUS}" in
    completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
    failed|cancelled|timeout|deleted) printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
    *) sleep 2 ;;
  esac
done

Parameters

Task Submission Parameters

Request Parameters

ParameterTypeRequiredDefaultRangeDescription
imagestringYes-The image for generating the output.
videostringYes-The video for generating the output.
promptstringNo-The positive prompt for the generation.
resolutionstringNo480p480p, 720pThe resolution of the output video.
seedintegerNo--The random seed to use for the generation. -1 means a random seed will be used.

Response Parameters

ParameterTypeDescription
codeintegerHTTP status code (e.g., 200 for success)
messagestringStatus message (e.g., “success”)
data.idstringUnique identifier for the prediction, Task Id
data.modelstringModel ID used for the prediction
data.outputsarrayOutput values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed)
data.urlsobjectObject containing related API endpoints
data.statusstringTask status. completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses.
data.created_atstringISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”)
data.errorstringError message (empty if no error occurred)
data.timingsobjectObject containing timing details
data.timings.inferenceintegerInference time in milliseconds

Result Request Parameters

ParameterTypeRequiredDefaultDescription
idstringYes-Task ID

Result Response Parameters

ParameterTypeDescription
codeintegerHTTP status code (e.g., 200 for success)
messagestringStatus message (e.g., “success”)
dataobjectThe prediction data object containing all details
data.idstringUnique identifier for the prediction
data.modelstringModel ID used for the prediction
data.outputsarray<string | object>Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model.
data.urlsobjectObject containing related API endpoints
data.statusstringStatus: completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses
data.created_atstringISO timestamp of when the request was created
data.errorstringError message (empty if no error occurred)
data.timingsobjectObject containing timing details
data.timings.inferenceintegerInference time in milliseconds
© 2026 WaveSpeedAI. All rights reserved.