The Wan unified video editing model supports multimodal input (text, image, and video) and provides five core capabilities: multi-image reference, video repainting, local editing, video extension, and frame expansion.
Availability
Supported models vary by region. Resources are isolated between regions. When calling the API, make sure your model, endpoint URL, and API key all belong to the same region. Cross-region calls will fail.
Supported models:
International
In the International deployment mode, the access point and data storage are located in the Singapore region, and model inference compute resources are dynamically scheduled worldwide, excluding Chinese Mainland.
Model | Features | Input modalities | Output video specifications |
wan2.1-vace-plus | Video without audio Multi-image reference, video redraw, local editing, video extension, video frame expansion | Text, image, video | Resolution options: 720P Video duration: Up to 5s Defined specifications: 30 fps, MP4 (H.264 encoding) |
Chinese Mainland
In the Chinese Mainland deployment mode, the access point and data storage are located in the Beijing region, and model inference compute resources are restricted to Chinese Mainland.
Model | Features | Input modalities | Output video specifications |
wanx2.1-vace-plus | Video without audio Multi-image reference, video redraw, local editing, video extension, video frame expansion | Text, image, video | Resolution options: 720P Video duration: Up to 5s Defined specifications: 30 fps, MP4 (H.264 encoding) |
Sample codes in this topic apply to the Singapore region.
Core capabilities
Multi-image reference
Description: Supports up to 3 reference images, including subjects and backgrounds (people, animals, clothing, scenes). The model merges the images to generate coherent video content.
Parameter settings:
function: Must beimage_reference.ref_images_url: An array of URLs. Supports 1 to 3 reference images.obj_or_bg: Identifies each image as a subject (obj) or background (bg). The length of this array must be the same as the length of theref_images_urlarray.
Input prompt | Input reference image 1 (Reference subject) | Input reference image 2 (Reference background) | Output video |
In the video, a girl walks out from the depths of an ancient, misty forest. Her steps are light, and the camera captures her every graceful moment. When she stops and looks around at the lush trees, a smile of surprise and joy blossoms on her face. This scene, frozen in a moment of intertwined light and shadow, records her wonderful encounter with nature. |
|
|
Before calling the API, get an API key. Then set your API key as an environment variable.
curl
Step 1: Create a task to get the task ID
curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.1-vace-plus",
"input": {
"function": "image_reference",
"prompt": "In the video, a girl gracefully walks out from a misty, ancient forest. Her steps are light, and the camera captures her every nimble moment. When she stops and looks around at the lush woods, a smile of surprise and joy blossoms on her face. This scene, frozen in a moment of interplay between light and shadow, records her wonderful encounter with nature.",
"ref_images_url": [
"http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png",
"http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png"
]
},
"parameters": {
"prompt_extend": true,
"obj_or_bg": ["obj","bg"],
"size": "1280*720"
}
}'Step 2: Get the result using the task ID
Replace {task_id} with the task_id value returned by the previous API call.
curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"Python
import os
import requests
import time
# The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
headers = {"X-DashScope-Async": "enable", "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def create_task():
"""Create a video synthesis task and return the task_id"""
try:
resp = requests.post(
f"{BASE_URL}/services/aigc/video-generation/video-synthesis",
headers={
"X-DashScope-Async": "enable",
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"model": "wan2.1-vace-plus",
"input": {
"function": "image_reference",
"prompt": "In the video, a girl walks out from the depths of an ancient, misty forest. Her steps are light, and the camera captures her every graceful moment. When she stops and looks around at the lush trees, a smile of surprise and joy blossoms on her face. This scene, frozen in a moment of intertwined light and shadow, records her wonderful encounter with nature.",
"ref_images_url": [
"http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png",
"http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png"
]
},
"parameters": {"prompt_extend": True, "obj_or_bg": ["obj", "bg"], "size": "1280*720"}
},
timeout=30
)
resp.raise_for_status()
return resp.json()["output"]["task_id"]
except requests.RequestException as e:
raise RuntimeError(f"Failed to create task: {e}")
def poll_result(task_id):
while True:
try:
resp = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10
)
resp.raise_for_status()
data = resp.json()["output"]
status = data["task_status"]
print(f"Status: {status}")
if status == "SUCCEEDED":
return data["video_url"]
elif status in ("FAILED", "CANCELLED"):
raise RuntimeError(f"Task failed: {data.get('message', 'Unknown error')}")
time.sleep(15)
except requests.RequestException as e:
print(f"Polling exception: {e}, retrying in 15 seconds...")
time.sleep(15)
if __name__ == "__main__":
task_id = create_task()
print(f"Task ID: {task_id}")
video_url = poll_result(task_id)
print(f"\nVideo generated successfully: {video_url}")Java
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
public class VideoSynthesis {
// The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
// API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
private static final Map<String, String> COMMON_HEADERS = new HashMap<>();
static {
if (API_KEY == null || API_KEY.isEmpty()) {
throw new IllegalStateException("DASHSCOPE_API_KEY is not set");
}
COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
// Enable HTTP keep-alive (enabled by default in JVM, but explicit setting is more reliable)
System.setProperty("http.keepAlive", "true");
System.setProperty("http.maxConnections", "20");
}
public static boolean isValidUserUrl(String urlString) {
try {
URL url = new URL(urlString);
// Check if the protocol is secure
String protocol = url.getProtocol();
if (!"https".equalsIgnoreCase(protocol) && !"http".equalsIgnoreCase(protocol)) {
return false;
}
return true;
} catch (Exception e) {
System.err.println("Invalid URL: " + e.getMessage());
return false;
}
}
// General HTTP POST request
private static String httpPost(String path, JSONObject body) throws Exception {
HttpURLConnection conn = createConnection(path, "POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(body.toString().getBytes("UTF-8"));
}
return readResponse(conn);
}
// General HTTP GET request
private static String httpGet(String path) throws Exception {
HttpURLConnection conn = createConnection(path, "GET");
return readResponse(conn);
}
// Create connection (reuse connection parameters)
private static HttpURLConnection createConnection(String path, String method) throws Exception {
URL url = new URL(BASE_URL + path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Configure connection properties
conn.setRequestMethod(method);
conn.setConnectTimeout(30000); // 30-second connection timeout
conn.setReadTimeout(60000); // 60-second read timeout
conn.setInstanceFollowRedirects(true); // Allow redirection
// Set common headers
for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
// Header for asynchronous tasks
if (path.contains("video-synthesis")) {
conn.setRequestProperty("X-DashScope-Async", "enable");
}
// Set content type and accept type
conn.setRequestProperty("Accept", "application/json");
return conn;
}
// Read response (automatically handle error stream)
private static String readResponse(HttpURLConnection conn) throws IOException {
InputStream is = (conn.getResponseCode() >= 200 && conn.getResponseCode() < 400)
? conn.getInputStream()
: conn.getErrorStream();
if (is == null) {
throw new IOException("Cannot get response stream, response code: " + conn.getResponseCode());
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n"); // Add a line feed to maintain the original format
}
return sb.toString();
}
}
// Step 1: Create a task
public static String createTask() throws Exception {
JSONObject body = new JSONObject()
.put("model", "wan2.1-vace-plus")
.put("input", new JSONObject()
.put("function", "image_reference")
.put("prompt", "In the video, a girl walks out from the depths of an ancient, misty forest. Her steps are light, and the camera captures her every graceful moment. When she stops and looks around at the lush trees, a smile of surprise and joy blossoms on her face. This scene, frozen in a moment of intertwined light and shadow, records her wonderful encounter with nature.")
.put("ref_images_url", new JSONArray()
.put("http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png")
.put("http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png")))
.put("parameters", new JSONObject()
.put("prompt_extend", true)
.put("obj_or_bg", new JSONArray().put("obj").put("bg"))
.put("size", "1280*720"));
String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
JSONObject jsonResponse = new JSONObject(resp);
// Check if the response contains an error message
if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
String errorMessage = jsonResponse.optString("message", "Unknown error");
throw new RuntimeException("Failed to create task: " + errorMessage + ", details: " + resp);
}
JSONObject output = jsonResponse.getJSONObject("output");
return output.getString("task_id");
}
// Step 2: Poll for the result (15-second interval, no limit on retries)
public static String pollResult(String taskId) throws Exception {
while (true) {
String resp = httpGet("/tasks/" + taskId);
JSONObject responseJson = new JSONObject(resp);
// Validate the response structure
if (!responseJson.has("output")) {
throw new RuntimeException("API response is missing the 'output' field: " + resp);
}
JSONObject output = responseJson.getJSONObject("output");
String status = output.getString("task_status");
System.out.println("Status: " + status);
if ("SUCCEEDED".equals(status)) {
return output.getString("video_url");
} else if ("FAILED".equals(status) || "CANCELLED".equals(status)) {
String message = output.optString("message", "Unknown error");
throw new RuntimeException("Task failed: " + message + ", Task ID: " + taskId + ", details: " + resp);
}
Thread.sleep(15000);
}
}
public static void main(String[] args) {
try {
System.out.println("Creating video synthesis task...");
String taskId = createTask();
System.out.println("Task created successfully, Task ID: " + taskId);
System.out.println("Polling for task result...");
String videoUrl = pollResult(taskId);
System.out.println("Video URL: " + videoUrl);
} catch (Exception e) {
System.err.println("An error occurred: " + e.getMessage());
e.printStackTrace(); // Print the full stack trace for debugging
}
}
}Video repainting
Description: Extracts the subject's pose and motion, composition and motion contours, or sketch structure from an input video. Then combines this with a text prompt to generate a new video with the same dynamic features. You can also replace the subject with a reference image.
Parameter settings:
function: Must bevideo_repainting.video_url: Required. The URL of the input video. Must be MP4 format, no larger than 50 MB, and no longer than 5 seconds.control_condition: Required. Video feature extraction method. This determines which features from the original video are retained:posebodyface: Extracts facial expressions and body movements. Retains facial expression details.posebody: Extracts only body movements, without the face. Controls only body motion.depth: Extracts composition and motion contours. Retains the scene structure.scribble: Extracts the sketch structure. Retains sketch edge details.
strength: Optional. Controls feature extraction strength. Range: 0.0–1.0. Default: 1.0. Higher values make the output more similar to the original; lower values allow more creative freedom.ref_images_url: Optional. URL of a reference image to replace the subject in the input video.
Input prompt | Input video | Output video |
The video shows a black steampunk-style car driven by a gentleman, adorned with gears and copper pipes. The background is a steam-powered candy factory with retro elements, creating a vintage and playful scene. |
curl
Step 1: Create a task to get the task ID
curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.1-vace-plus",
"input": {
"function": "video_repainting",
"prompt": "The video shows a black steampunk-style car driven by a gentleman. The car is decorated with gears and copper pipes. The background features a steam-powered candy factory and retro elements, creating a vintage and playful scene.",
"video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
},
"parameters": {
"prompt_extend": false,
"control_condition": "depth"
}
}'Step 2: Get the result using the task ID
Replace {task_id} with the task_id value returned by the previous API call.
curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"Python
import os
import requests
import time
# The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
def create_task():
"""Create a video repainting task and return the task_id"""
try:
resp = requests.post(
f"{BASE_URL}/services/aigc/video-generation/video-synthesis",
headers={
"X-DashScope-Async": "enable",
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"model": "wan2.1-vace-plus",
"input": {
"function": "video_repainting",
"prompt": "The video shows a black steampunk-style car driven by a gentleman, adorned with gears and copper pipes. The background is a steam-powered candy factory with retro elements, creating a vintage and playful scene.",
"video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
},
"parameters": {
"prompt_extend": False, # We recommend disabling prompt rewriting for video repainting.
"control_condition": "depth" # Optional: posebodyface, posebody, depth, scribble
}
},
timeout=30
)
resp.raise_for_status()
return resp.json()["output"]["task_id"]
except requests.RequestException as e:
raise RuntimeError(f"Failed to create task: {e}")
def poll_result(task_id):
while True:
try:
resp = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10
)
resp.raise_for_status()
data = resp.json()["output"]
status = data["task_status"]
print(f"Status: {status}")
if status == "SUCCEEDED":
return data["video_url"]
elif status in ("FAILED", "CANCELLED"):
raise RuntimeError(f"Task failed: {data.get('message', 'Unknown error')}")
time.sleep(15)
except requests.RequestException as e:
print(f"Polling exception: {e}, retrying in 15 seconds...")
time.sleep(15)
if __name__ == "__main__":
task_id = create_task()
print(f"Task ID: {task_id}")
video_url = poll_result(task_id)
print(f"\nVideo generated successfully: {video_url}")Java
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
public class VideoRepainting {
// The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
// API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
private static final Map<String, String> COMMON_HEADERS = new HashMap<>();
static {
if (API_KEY == null || API_KEY.isEmpty()) {
throw new IllegalStateException("DASHSCOPE_API_KEY is not set");
}
COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
System.setProperty("http.keepAlive", "true");
System.setProperty("http.maxConnections", "20");
}
// General HTTP POST request
private static String httpPost(String path, JSONObject body) throws Exception {
HttpURLConnection conn = createConnection(path, "POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(body.toString().getBytes("UTF-8"));
}
return readResponse(conn);
}
// General HTTP GET request
private static String httpGet(String path) throws Exception {
HttpURLConnection conn = createConnection(path, "GET");
return readResponse(conn);
}
// Create connection
private static HttpURLConnection createConnection(String path, String method) throws Exception {
URL url = new URL(BASE_URL + path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(30000);
conn.setReadTimeout(60000);
conn.setInstanceFollowRedirects(true);
for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
if (path.contains("video-synthesis")) {
conn.setRequestProperty("X-DashScope-Async", "enable");
}
conn.setRequestProperty("Accept", "application/json");
return conn;
}
// Read response
private static String readResponse(HttpURLConnection conn) throws IOException {
InputStream is = (conn.getResponseCode() >= 200 && conn.getResponseCode() < 400)
? conn.getInputStream()
: conn.getErrorStream();
if (is == null) throw new IOException("Cannot get response stream, response code: " + conn.getResponseCode());
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
}
}
// Step 1: Create a video repainting task
public static String createTask() throws Exception {
JSONObject body = new JSONObject()
.put("model", "wan2.1-vace-plus")
.put("input", new JSONObject()
.put("function", "video_repainting")
.put("prompt", "The video shows a black steampunk-style car driven by a gentleman, adorned with gears and copper pipes. The background is a steam-powered candy factory with retro elements, creating a vintage and playful scene.")
.put("video_url", "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"))
.put("parameters", new JSONObject()
.put("prompt_extend", false)
.put("control_condition", "depth"));
String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
JSONObject jsonResponse = new JSONObject(resp);
if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
String errorMessage = jsonResponse.optString("message", "Unknown error");
throw new RuntimeException("Failed to create task: " + errorMessage);
}
return jsonResponse.getJSONObject("output").getString("task_id");
}
// Step 2: Poll for the result
public static String pollResult(String taskId) throws Exception {
while (true) {
String resp = httpGet("/tasks/" + taskId);
JSONObject output = new JSONObject(resp).getJSONObject("output");
String status = output.getString("task_status");
System.out.println("Status: " + status);
if ("SUCCEEDED".equals(status)) {
return output.getString("video_url");
} else if ("FAILED".equals(status) || "CANCELLED".equals(status)) {
throw new RuntimeException("Task failed: " + output.optString("message", "Unknown error"));
}
Thread.sleep(15000);
}
}
public static void main(String[] args) {
try {
System.out.println("Creating video repainting task...");
String taskId = createTask();
System.out.println("Task created successfully, Task ID: " + taskId);
System.out.println("Polling for task result...");
String videoUrl = pollResult(taskId);
System.out.println("Video URL: " + videoUrl);
} catch (Exception e) {
System.err.println("An error occurred: " + e.getMessage());
e.printStackTrace();
}
}
}Local editing
Description: Performs fine-grained editing on specified video areas. Supports adding, deleting, and modifying elements, or replacing subjects and backgrounds. Upload a mask image to specify the editing area—the model automatically tracks the target and blends the generated content.
Parameter settings:
function: Must bevideo_edit.video_url: Required. The URL of the original input video.mask_image_url: Optional. Specify either this parameter ormask_video_url. We recommend using this parameter. The URL of a mask image. White areas of the mask are edited; black areas remain unchanged.mask_frame_id: Optional. Use withmask_image_urlto specify which video frame the mask corresponds to. Default: first frame.mask_type: Optional. Specifies the behavior of the editing area:tracking(default): The editing area automatically follows the target's motion trajectory.fixed: The editing area stays in a fixed position.
expand_ratio: Optional. Only effective whenmask_typeistracking.The ratio by which the mask area expands outward. Range: 0.0–1.0. Default: 0.05.
Lower values fit the target more closely; higher values expand the mask area.
ref_images_url: Optional. URL of a reference image. Content in the editing area is replaced with the reference image content.
Input prompt | Input video | Input mask image | Output video |
The video shows a Parisian-style French cafe where a lion in a suit is elegantly sipping coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is. |
The white area indicates the editing area. |
curl
Step 1: Create a task to get the task ID
curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.1-vace-plus",
"input": {
"function": "video_edit",
"prompt": "The video shows a Parisian-style French cafe where a lion in a suit is elegantly sipping coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft hues and warm lighting illuminating the area where the lion is.",
"mask_image_url": "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png",
"video_url": "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4",
"mask_frame_id": 1
},
"parameters": {
"prompt_extend": false,
"mask_type": "tracking",
"expand_ratio": 0.05
}
}'Step 2: Get the result using the task ID
Replace {task_id} with the task_id value returned by the previous API call.
curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"Python
import os
import requests
import time
# The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
def create_task():
"""Create a local editing task and return the task_id"""
try:
resp = requests.post(
f"{BASE_URL}/services/aigc/video-generation/video-synthesis",
headers={
"X-DashScope-Async": "enable",
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"model": "wan2.1-vace-plus",
"input": {
"function": "video_edit",
"prompt": "The video shows a Parisian-style French cafe where a lion in a suit is elegantly sipping coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is.",
"mask_image_url": "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png",
"video_url": "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4",
"mask_frame_id": 1 # Frame index to which the mask corresponds
},
"parameters": {
"prompt_extend": False,
"mask_type": "tracking", # Tracking mode
"expand_ratio": 0.05
}
},
timeout=30
)
resp.raise_for_status()
return resp.json()["output"]["task_id"]
except requests.RequestException as e:
raise RuntimeError(f"Failed to create task: {e}")
def poll_result(task_id):
while True:
try:
resp = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10
)
resp.raise_for_status()
data = resp.json()["output"]
status = data["task_status"]
print(f"Status: {status}")
if status == "SUCCEEDED":
return data["video_url"]
elif status in ("FAILED", "CANCELLED"):
raise RuntimeError(f"Task failed: {data.get('message', 'Unknown error')}")
time.sleep(15)
except requests.RequestException as e:
print(f"Polling exception: {e}, retrying in 15 seconds...")
time.sleep(15)
if __name__ == "__main__":
task_id = create_task()
print(f"Task ID: {task_id}")
video_url = poll_result(task_id)
print(f"\nVideo generated successfully: {video_url}")Java
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
public class VideoRegionalEdit {
// The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
// API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
private static final Map<String, String> COMMON_HEADERS = new HashMap<>();
static {
if (API_KEY == null || API_KEY.isEmpty()) {
throw new IllegalStateException("DASHSCOPE_API_KEY is not set");
}
COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
System.setProperty("http.keepAlive", "true");
}
private static String httpPost(String path, JSONObject body) throws Exception {
HttpURLConnection conn = createConnection(path, "POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(body.toString().getBytes("UTF-8"));
}
return readResponse(conn);
}
private static String httpGet(String path) throws Exception {
HttpURLConnection conn = createConnection(path, "GET");
return readResponse(conn);
}
private static HttpURLConnection createConnection(String path, String method) throws Exception {
URL url = new URL(BASE_URL + path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(30000);
conn.setReadTimeout(60000);
for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
if (path.contains("video-synthesis")) {
conn.setRequestProperty("X-DashScope-Async", "enable");
}
return conn;
}
private static String readResponse(HttpURLConnection conn) throws IOException {
InputStream is = (conn.getResponseCode() >= 200 && conn.getResponseCode() < 400) ? conn.getInputStream() : conn.getErrorStream();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) sb.append(line).append("\n");
return sb.toString();
}
}
// Step 1: Create a local editing task
public static String createTask() throws Exception {
JSONObject body = new JSONObject()
.put("model", "wan2.1-vace-plus")
.put("input", new JSONObject()
.put("function", "video_edit")
.put("prompt", "The video shows a Parisian-style French cafe where a lion in a suit is elegantly sipping coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is.")
.put("mask_image_url", "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png")
.put("video_url", "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4")
.put("mask_frame_id", 1))
.put("parameters", new JSONObject()
.put("prompt_extend", false)
.put("mask_type", "tracking")
.put("expand_ratio", 0.05));
String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
JSONObject jsonResponse = new JSONObject(resp);
if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
String errorMessage = jsonResponse.optString("message", "Unknown error");
throw new RuntimeException("Failed to create task: " + errorMessage);
}
return jsonResponse.getJSONObject("output").getString("task_id");
}
// Step 2: Poll for the result
public static String pollResult(String taskId) throws Exception {
while (true) {
String resp = httpGet("/tasks/" + taskId);
JSONObject output = new JSONObject(resp).getJSONObject("output");
String status = output.getString("task_status");
System.out.println("Status: " + status);
if ("SUCCEEDED".equals(status)) return output.getString("video_url");
else if ("FAILED".equals(status) || "CANCELLED".equals(status))
throw new RuntimeException("Task failed: " + output.optString("message"));
Thread.sleep(15000);
}
}
public static void main(String[] args) {
try {
System.out.println("Creating local editing task...");
String taskId = createTask();
System.out.println("Task created successfully, Task ID: " + taskId);
String videoUrl = pollResult(taskId);
System.out.println("Video URL: " + videoUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
}Video extension
Description: Predicts and generates continuous content based on an input image or video clip. Supports extending a video forward from the first frame or clip, or backward from the last frame or clip. The generated video is 5 seconds long.
Parameter settings:
function: Must bevideo_extension.prompt: Required. A description of the desired extended content.first_clip_url: Optional. The URL of the first video clip (3 seconds or shorter). The model generates the rest of the video based on this clip.last_clip_url: Optional. The URL of the last video clip (3 seconds or shorter). The model generates the preceding content based on this clip.first_frame_url: Optional. The URL of the first frame image. The video extends forward from this frame.last_frame_url: Optional. The URL of the last frame image. Generation proceeds backward from this frame.Specify at least one of the following:
first_clip_url,last_clip_url,first_frame_url, orlast_frame_url.
Input prompt | Input first clip video (1 second) | Output video (Extended video is 5 seconds) |
A dog wearing sunglasses is skateboarding on the street, 3D cartoon. |
curl
Step 1: Create a task to get the task ID
curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.1-vace-plus",
"input": {
"function": "video_extension",
"prompt": "A dog wearing sunglasses is skateboarding on the street, 3D cartoon.",
"first_clip_url": "http://wanx.alicdn.com/material/20250318/video_extension_1.mp4"
},
"parameters": {
"prompt_extend": false
}
}'Step 2: Get the result using the task ID
Replace {task_id} with the task_id value returned by the previous API call.
curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"Python
import os
import requests
import time
# The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
def create_task():
"""Create a video extension task and return the task_id"""
try:
resp = requests.post(
f"{BASE_URL}/services/aigc/video-generation/video-synthesis",
headers={
"X-DashScope-Async": "enable",
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"model": "wan2.1-vace-plus",
"input": {
"function": "video_extension",
"prompt": "A dog wearing sunglasses is skateboarding on the street, 3D cartoon.",
"first_clip_url": "http://wanx.alicdn.com/material/20250318/video_extension_1.mp4"
},
"parameters": {
"prompt_extend": False
}
},
timeout=30
)
resp.raise_for_status()
return resp.json()["output"]["task_id"]
except requests.RequestException as e:
raise RuntimeError(f"Failed to create task: {e}")
def poll_result(task_id):
while True:
try:
resp = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10
)
resp.raise_for_status()
data = resp.json()["output"]
status = data["task_status"]
print(f"Status: {status}")
if status == "SUCCEEDED":
return data["video_url"]
elif status in ("FAILED", "CANCELLED"):
raise RuntimeError(f"Task failed: {data.get('message', 'Unknown error')}")
time.sleep(15)
except requests.RequestException as e:
print(f"Polling exception: {e}, retrying in 15 seconds...")
time.sleep(15)
if __name__ == "__main__":
task_id = create_task()
print(f"Task ID: {task_id}")
video_url = poll_result(task_id)
print(f"\nVideo generated successfully: {video_url}")Java
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
public class VideoExtension {
// The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
// API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
private static final Map<String, String> COMMON_HEADERS = new HashMap<>();
static {
if (API_KEY == null || API_KEY.isEmpty()) {
throw new IllegalStateException("DASHSCOPE_API_KEY is not set");
}
COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
System.setProperty("http.keepAlive", "true");
}
private static String httpPost(String path, JSONObject body) throws Exception {
HttpURLConnection conn = createConnection(path, "POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(body.toString().getBytes("UTF-8"));
}
return readResponse(conn);
}
private static String httpGet(String path) throws Exception {
HttpURLConnection conn = createConnection(path, "GET");
return readResponse(conn);
}
private static HttpURLConnection createConnection(String path, String method) throws Exception {
URL url = new URL(BASE_URL + path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(30000);
conn.setReadTimeout(60000);
for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
if (path.contains("video-synthesis")) {
conn.setRequestProperty("X-DashScope-Async", "enable");
}
return conn;
}
private static String readResponse(HttpURLConnection conn) throws IOException {
InputStream is = (conn.getResponseCode() >= 200 && conn.getResponseCode() < 400) ? conn.getInputStream() : conn.getErrorStream();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) sb.append(line).append("\n");
return sb.toString();
}
}
// Step 1: Create a video extension task
public static String createTask() throws Exception {
JSONObject body = new JSONObject()
.put("model", "wan2.1-vace-plus")
.put("input", new JSONObject()
.put("function", "video_extension")
.put("prompt", "A dog wearing sunglasses is skateboarding on the street, 3D cartoon.")
.put("first_clip_url", "http://wanx.alicdn.com/material/20250318/video_extension_1.mp4"))
.put("parameters", new JSONObject()
.put("prompt_extend", false));
String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
JSONObject jsonResponse = new JSONObject(resp);
if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
String errorMessage = jsonResponse.optString("message", "Unknown error");
throw new RuntimeException("Failed to create task: " + errorMessage);
}
return jsonResponse.getJSONObject("output").getString("task_id");
}
// Step 2: Poll for the result
public static String pollResult(String taskId) throws Exception {
while (true) {
String resp = httpGet("/tasks/" + taskId);
JSONObject output = new JSONObject(resp).getJSONObject("output");
String status = output.getString("task_status");
System.out.println("Status: " + status);
if ("SUCCEEDED".equals(status)) return output.getString("video_url");
else if ("FAILED".equals(status) || "CANCELLED".equals(status))
throw new RuntimeException("Task failed: " + output.optString("message"));
Thread.sleep(15000);
}
}
public static void main(String[] args) {
try {
System.out.println("Creating video extension task...");
String taskId = createTask();
System.out.println("Task created successfully, Task ID: " + taskId);
String videoUrl = pollResult(taskId);
System.out.println("Video URL: " + videoUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
}Frame expansion
Description: Expands video frame content proportionally in all directions (top, bottom, left, right) based on a prompt. Maintains video subject continuity and ensures a natural blend with the background.
Parameter settings:
function: Must bevideo_outpainting.video_url: Required. The URL of the original input video.top_scale: Optional. Upward expansion ratio. Range: 1.0–2.0. Default: 1.0 (no expansion).bottom_scale: Optional. Downward expansion ratio. Range: 1.0–2.0. Default: 1.0.left_scale: Optional. Leftward expansion ratio. Range: 1.0–2.0. Default: 1.0.right_scale: Optional. Rightward expansion ratio. Range: 1.0–2.0. Default: 1.0.
Example: Setting left_scale to 1.5 expands the left side of the frame to 1.5 times its original width.Input prompt | Input video | Output video |
An elegant lady is passionately playing the violin, with a full symphony orchestra behind her. |
curl
Step 1: Create a task to get the task ID
curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "wan2.1-vace-plus",
"input": {
"function": "video_outpainting",
"prompt": "An elegant lady is passionately playing the violin, with a full symphony orchestra behind her.",
"video_url": "http://wanx.alicdn.com/material/20250318/video_outpainting_1.mp4"
},
"parameters": {
"prompt_extend": false,
"top_scale": 1.5,
"bottom_scale": 1.5,
"left_scale": 1.5,
"right_scale": 1.5
}
}'Step 2: Get the result using the task ID
Replace {task_id} with the task_id value returned by the previous API call.
curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"Python
import os
import requests
import time
# The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
def create_task():
"""Create a video frame expansion task and return the task_id"""
try:
resp = requests.post(
f"{BASE_URL}/services/aigc/video-generation/video-synthesis",
headers={
"X-DashScope-Async": "enable",
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"model": "wan2.1-vace-plus",
"input": {
"function": "video_outpainting",
"prompt": "An elegant lady is passionately playing the violin, with a full symphony orchestra behind her.",
"video_url": "http://wanx.alicdn.com/material/20250318/video_outpainting_1.mp4"
},
"parameters": {
"prompt_extend": False,
"top_scale": 1.5, # Upward expansion ratio
"bottom_scale": 1.5, # Downward expansion ratio
"left_scale": 1.5, # Leftward expansion ratio
"right_scale": 1.5 # Rightward expansion ratio
}
},
timeout=30
)
resp.raise_for_status()
return resp.json()["output"]["task_id"]
except requests.RequestException as e:
raise RuntimeError(f"Failed to create task: {e}")
def poll_result(task_id):
while True:
try:
resp = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10
)
resp.raise_for_status()
data = resp.json()["output"]
status = data["task_status"]
print(f"Status: {status}")
if status == "SUCCEEDED":
return data["video_url"]
elif status in ("FAILED", "CANCELLED"):
raise RuntimeError(f"Task failed: {data.get('message', 'Unknown error')}")
time.sleep(15)
except requests.RequestException as e:
print(f"Polling exception: {e}, retrying in 15 seconds...")
time.sleep(15)
if __name__ == "__main__":
task_id = create_task()
print(f"Task ID: {task_id}")
video_url = poll_result(task_id)
print(f"\nVideo generated successfully: {video_url}")Java
import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
public class VideoOutpainting {
// The following is the URL for the Singapore region. URLs vary by region. To get the URL, see https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
// API keys vary by region. To get an API key, see https://www.alibabacloud.com/help/en/model-studio/get-api-key
static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
private static final Map<String, String> COMMON_HEADERS = new HashMap<>();
static {
if (API_KEY == null || API_KEY.isEmpty()) {
throw new IllegalStateException("DASHSCOPE_API_KEY is not set");
}
COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
System.setProperty("http.keepAlive", "true");
}
private static String httpPost(String path, JSONObject body) throws Exception {
HttpURLConnection conn = createConnection(path, "POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
os.write(body.toString().getBytes("UTF-8"));
}
return readResponse(conn);
}
private static String httpGet(String path) throws Exception {
HttpURLConnection conn = createConnection(path, "GET");
return readResponse(conn);
}
private static HttpURLConnection createConnection(String path, String method) throws Exception {
URL url = new URL(BASE_URL + path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(method);
conn.setConnectTimeout(30000);
conn.setReadTimeout(60000);
for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
if (path.contains("video-synthesis")) {
conn.setRequestProperty("X-DashScope-Async", "enable");
}
return conn;
}
private static String readResponse(HttpURLConnection conn) throws IOException {
InputStream is = (conn.getResponseCode() >= 200 && conn.getResponseCode() < 400) ? conn.getInputStream() : conn.getErrorStream();
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) sb.append(line).append("\n");
return sb.toString();
}
}
// Step 1: Create a video frame expansion task
public static String createTask() throws Exception {
JSONObject body = new JSONObject()
.put("model", "wan2.1-vace-plus")
.put("input", new JSONObject()
.put("function", "video_outpainting")
.put("prompt", "An elegant lady is passionately playing the violin, with a full symphony orchestra behind her.")
.put("video_url", "http://wanx.alicdn.com/material/20250318/video_outpainting_1.mp4"))
.put("parameters", new JSONObject()
.put("prompt_extend", false)
.put("top_scale", 1.5)
.put("bottom_scale", 1.5)
.put("left_scale", 1.5)
.put("right_scale", 1.5));
String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
JSONObject jsonResponse = new JSONObject(resp);
if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
String errorMessage = jsonResponse.optString("message", "Unknown error");
throw new RuntimeException("Failed to create task: " + errorMessage);
}
return jsonResponse.getJSONObject("output").getString("task_id");
}
// Step 2: Poll for the result
public static String pollResult(String taskId) throws Exception {
while (true) {
String resp = httpGet("/tasks/" + taskId);
JSONObject output = new JSONObject(resp).getJSONObject("output");
String status = output.getString("task_status");
System.out.println("Status: " + status);
if ("SUCCEEDED".equals(status)) return output.getString("video_url");
else if ("FAILED".equals(status) || "CANCELLED".equals(status))
throw new RuntimeException("Task failed: " + output.optString("message"));
Thread.sleep(15000);
}
}
public static void main(String[] args) {
try {
System.out.println("Creating video frame expansion task...");
String taskId = createTask();
System.out.println("Task created successfully, Task ID: " + taskId);
String videoUrl = pollResult(taskId);
System.out.println("Video URL: " + videoUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
}Input images and videos
Input images
Number of images: See the number required for your selected feature.
Input method:
Public URL: Supports HTTP and HTTPS protocols. Example: https://xxxx/xxx.png.
Input videos
Number of videos: See the number required for your selected feature.
Input method:
Public URL: Supports HTTP and HTTPS protocols. Example: https://xxxx/xxx.mp4.
Output video
Number of videos: One.
Format: MP4. See video specifications below for resolution and dimensions.
URL expiration: 24 hours.
Dimensions: Varies based on the selected feature.
Multi-image reference / Local editing:
Output resolution is fixed at 720P.
Specific width and height are determined by the size parameter.
Video repainting / Video extension / Frame expansion:
If the input video resolution is 720P or lower, the output resolution matches the input.
If the input video resolution is higher than 720P, the output is scaled down to 720P while maintaining aspect ratio.
Billing and rate limiting
For free quota and pricing, see Model invocation pricing.
For rate limiting, see Wan series.
Billing details:
Input is free. Output is billed per successfully generated second of video.
Failed model calls or processing errors incur no charge and do not consume your free quota.
General video editing also supports savings plans.
API reference
FAQ
Q: How many images does the multi-image reference feature support at most?
A: Supports a maximum of 3 reference images. If you provide more than 3, only the first 3 are used. For best results, use a solid background for the subject image to highlight the subject better, and ensure the background image does not contain subject objects.
Q: When should I disable prompt rewriting for video repainting?
A: If the text description is inconsistent with the input video content, the model may misinterpret your request. In this case, we recommend manually disabling prompt rewriting by setting prompt_extend=false and providing a clear, specific scene description in the prompt. This improves consistency and accuracy.
Q: In the local editing feature, what is the difference between a mask image and a mask video?
A: Specify either a mask image using mask_image_url or a mask video using mask_video_url. We recommend using a mask image because you only need to specify the editing area in a single frame, and the system automatically tracks the target.


