Nano Banana 2.1 is LIVE — Google's Latest | Try Now →

bytedance/seedance-2.5/motion-control

Transfer the motion of a reference video onto a character image with Seedance 2.5. The character from your image performs the same movements, gestures and camera motion as the video, in 480p, 720p or 1080p for up to 30 seconds. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.

Motion Control
Input

Drag & drop or click to upload

preview

Drag & drop or click to upload

Whether to generate native audio for the output. Defaults to true. When set to false, the reference video's audio track is preserved on the output instead.

Idle

$1.1per run

ExamplesView all

Related Models

README

Seedance 2.5 Motion Control

Seedance 2.5 Motion Control transfers the motion of a reference video onto a character image. The character in your image performs the same movements, gestures, timing and camera motion as the person in the video, while the background, framing and pacing of the video are kept.

Why Choose This?

  • Faithful motion transfer - Dance, gestures, walking, turning and full-body action carry over from the reference video to your character.

  • Character identity from one image - Face, hairstyle and clothing come from the image you provide.

  • Video-driven timing and camera - Duration, framing and camera movement follow the reference video, so the result drops straight into your cut.

  • Native audio - Generate synchronized audio, or keep the original soundtrack of the reference video.

  • Up to 1080p, up to 30 seconds - Choose 480p for fast previews or 1080p for final delivery.

Parameters

ParameterRequiredDescription
imageYesURL of the character image. A clear, full-body or half-body picture with a visible face works best.
videoYesURL of the motion reference video. Videos longer than 30 seconds are trimmed to 30 seconds; videos shorter than 4 seconds are padded to 4 seconds.
promptNoOptional extra direction. Leave empty to transfer the motion as it is.
resolutionNoOutput resolution: 480p, 720p, or 1080p. Default: 720p.
generate_audioNoGenerate synchronized audio for the output. When set to false, the reference video's audio track is kept. Default: true.

The output duration and aspect ratio follow the reference video.

How to Use

  1. Upload the character image — Choose the person or character that should perform the motion.
  2. Upload the motion video — Provide a clip of the movement you want to copy, 4 to 30 seconds.
  3. Add direction if needed — Leave prompt empty, or add a short instruction.
  4. Choose resolution — Select 480p, 720p, or 1080p.
  5. Submit — Generate the video. API requests are asynchronous; poll the result endpoint until the video URL is available.

Tips for Better Results

  • Use a motion video with one clearly visible performer and a stable camera.
  • Pick a character image whose pose and framing are close to the first frame of the video (full body for full-body motion).
  • Keep the character's face and clothing clearly visible in the image.
  • Avoid heavily occluded limbs in the reference video; fast, complex motion is easier to follow when the performer stays in frame.

Pricing

Charges are based on the duration of the reference video, rounded up to whole seconds, with a 4-second minimum and a 30-second maximum.

ResolutionPer second5 seconds10 seconds30 seconds
480p$0.22$1.10$2.20$6.60
720p$0.44$2.20$4.40$13.20
1080p$1.10$5.50$11.00$33.00

For example, a 3.2-second clip is billed as 4 seconds, and a 8.04-second clip is billed as 9 seconds.

Related Models

Note:This website uses AI models provided by third parties. Documentation prices are for reference and may be outdated. The Generate button shows an estimate; the final task charge prevails.

Seedance 2.5 Motion Control API — Quick start

Grab a WaveSpeedAI API key, then call POST https://api.wavespeed.ai/api/v3/bytedance/seedance-2.5/motion-control 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 Seedance 2.5 Motion Control below.

HTTP example
set -euo pipefail

: "${WAVESPEED_API_KEY:?Set WAVESPEED_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": "720p",
    "generate_audio": true
}
JSON
)

# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
  -X POST "https://api.wavespeed.ai/api/v3/bytedance/seedance-2.5/motion-control" \
  -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="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 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|deleted) printf '%s\n' "$RESULT" | jq . >&2; exit 1 ;;
    *) sleep 2 ;;
  esac
done
Node.js example
const submitUrl = "https://api.wavespeed.ai/api/v3/bytedance/seedance-2.5/motion-control";
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({
        "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": "720p",
        "generate_audio": true
}),
});
const task = body.data ?? body;
if (!task.id) throw new Error("Submission response did not contain a prediction id");
const resultUrl = `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", "deleted"].includes(result.status)) throw new Error(JSON.stringify(result));
  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 = {
    "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": "720p",
    "generate_audio": True
}

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/bytedance/seedance-2.5/motion-control", 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 = 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", "deleted"}:
        raise RuntimeError(result)
    time.sleep(2)

Seedance 2.5 Motion Control API — Frequently asked questions

What is the Seedance 2.5 Motion Control API?

Seedance 2.5 Motion Control is a ByteDance model for pose / motion driven video, exposed as a REST API on WaveSpeedAI. Transfer the motion of a reference video onto a character image with Seedance 2.5. The character from your image performs the same movements, gestures and camera motion as the video, in 480p, 720p or 1080p for up to 30 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 Seedance 2.5 Motion Control 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 Python, JavaScript, and cURL examples for submitting requests and polling results. Full request/response shape is documented at https://wavespeed.ai/docs/docs-api/bytedance/bytedance-seedance-2.5-motion-control.

How much does Seedance 2.5 Motion Control cost per run?

Seedance 2.5 Motion Control starts at $1.1 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 Seedance 2.5 Motion Control accept?

Key inputs: `prompt`, `image`, `video`, `resolution`, `generate_audio`. 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/bytedance/bytedance-seedance-2.5-motion-control.

How do I get started with the Seedance 2.5 Motion Control 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 Seedance 2.5 Motion Control outputs commercially?

Commercial usage rights depend on the model's license, set by its provider (ByteDance). Check the provider's applicable terms and WaveSpeedAI's Terms of Service before commercial use.

llms.txt — bytedance/seedance-2.5/motion-control for AI agents and LLMs