The Wanxiang universal video editing model supports multimodal inputs (text, image, and video) and provides five core capabilities: multi-image reference, video repainting, local editing, video extension, and video outpainting.
Applicable scope
-
Supported models vary by region. Resources are isolated between regions. For supported models in each region, see the Model Studio console.
-
When making a call, make sure your model, endpoint URL, and API key all belong to the same region. Cross-region calls fail.
The sample code in this topic applies to the China (Beijing) region.
Core capabilities
Multi-image reference
Function introduction: Supports up to 3 reference images, which can include subjects and backgrounds (such as people, animals, clothing, and scenes). The model merges multiple images to generate coherent video content.
Parameters:
-
function: Must be set toimage_reference. -
ref_images_url: An array of URLs. You can input 1 to 3 reference images. -
obj_or_bg: Identifies each image as a subject (obj) or background (bg). The length must be the same asref_images_url.
|
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 woods, a smile of surprise and joy appears on her face. This moment, captured in the interplay of light and shadow, records her wonderful encounter with nature. |
|
|
Before making a call, you must first obtain an API key and then configure the API key as an environment variable (to be unpublished and merged into Configure API key).
curl
Step 1: Create a task to obtain a task ID
curl --location 'https://dashscope.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": "wanx2.1-vace-plus",
"input": {
"function": "image_reference",
"prompt": "In the video, a girl gracefully emerges from a misty, ancient forest. Her steps are light, and the camera captures her every nimble moment. When she stops to look at the lush woods around her, a smile of surprise and joy blossoms on her face. This scene, frozen in an interplay of 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: Retrieve the result based on the task ID
Replace {task_id} with the task_id value returned by the previous API call. The task_id is valid for queries for 24 hours.
curl -X GET https://dashscope.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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope.aliyuncs.com/api/v1"
# API keys vary by region. For more information, see https://help.aliyun.com/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": "wanx2.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 the girl stops and looks around at the lush woods, a smile of surprise and joy appears on her face. This moment, captured in the interplay of 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 the 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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope.aliyuncs.com/api/v1";
// API keys vary by region. For more information, see https://help.aliyun.com/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 a 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 the response (automatically handle error streams)
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", "wanx2.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 woods, a smile of surprise and joy appears on her face. This moment, captured in the interplay of 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 the 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("The 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
Function introduction: Extracts the subject's pose and actions, composition and motion contours, or sketch structure from an input video. It then generates a new video with the same dynamic features based on a text prompt. You can also replace the subject in the original video using a reference image.
Parameters:
-
function: Must be set tovideo_repainting. -
video_url: Required. The URL of the input video (MP4 format, ≤50 MB, ≤5 seconds). -
control_condition: Required. Sets the method for video feature extraction, which determines which features of the original video are retained in the new video.-
posebodyface: Extracts facial expressions and body movements (retains facial expression details). -
posebody: Extracts only body movements, excluding the face (controls only body actions). -
depth: Extracts composition and motion contours (retains scene structure). -
scribble: Extracts the sketch structure (retains sketch edge details).
-
-
strength: Optional. Controls the strength of feature extraction. The range is [0.0, 1.0]. The default is 1.0. A larger value makes the output closer to the original video, while a smaller value allows for more creative freedom. -
ref_images_url: Optional. Provide the URL of one 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 obtain a task ID
curl --location 'https://dashscope.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": "wanx2.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 fun scene.",
"video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
},
"parameters": {
"prompt_extend": false,
"control_condition": "depth"
}
}'Step 2: Retrieve the result based on the task ID
Replace {task_id} with the task_id value returned by the previous API call. The task_id is valid for queries for 24 hours.
curl -X GET https://dashscope.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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope.aliyuncs.com/api/v1"
# API keys vary by region. For more information, see https://help.aliyun.com/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": "wanx2.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, # For video repainting, we recommend disabling prompt rewriting.
"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 the 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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope.aliyuncs.com/api/v1";
// API keys vary by region. For more information, see https://help.aliyun.com/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 a 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 the 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", "wanx2.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 the 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
Function introduction: Performs fine-grained editing on specified areas of a video. It supports adding, deleting, or modifying elements, and replacing subjects or backgrounds. You can upload a mask image to specify the editing area, and the model will automatically track the target and blend the generated content.
Parameters:
-
function: Must be set tovideo_edit. -
video_url: Required. The URL of the original input video. -
mask_image_url: Optional. Choose between this andmask_video_url. We recommend using this parameter. You can input the URL of a mask image where the white area represents the part to be edited and the black area remains unchanged. -
mask_frame_id: Optional. Used withmask_image_urlto specify which frame of the video the mask corresponds to (default is the first frame). -
mask_type: Optional. Specifies the behavior of the editing area:-
tracking(default): The editing area automatically follows the motion trajectory of the target object. -
fixed: The editing area remains in a fixed position.
-
-
expand_ratio: Optional. Effective only whenmask_typeistracking.-
Function: Sets the ratio by which the mask area expands outward. The value range is [0.0, 1.0], and the default is 0.05.
-
Description: A smaller value makes the mask fit the target more closely. A larger value expands the mask's range.
-
-
ref_images_url: Optional. Provide the URL of one reference image to replace the content in the editing area with the content of the reference image.
|
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 drinking coffee. It holds a coffee cup in one hand, sipping 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 obtain a task ID
# If you use a model in the China (Beijing) region, replace the URL with: https://dashscope.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis
curl --location 'https://dashscope.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": "wanx2.1-vace-plus",
"input": {
"function": "video_edit",
"prompt": "The video shows a Parisian-style French cafe where a lion in a suit elegantly sips 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 lion's area.",
"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: Retrieve the result based on the task ID
Replace {task_id} with the task_id value returned by the previous API call. The task_id is valid for queries for 24 hours.
curl -X GET https://dashscope.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"Python
Install dependencies: pip install requests.
import os
import requests
import time
# The following is the URL for the China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope.aliyuncs.com/api/v1"
# API keys vary by region. For more information, see https://help.aliyun.com/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": "wanx2.1-vace-plus",
"input": {
"function": "video_edit",
"prompt": "The video shows a Parisian-style French cafe where a lion in a suit is elegantly drinking coffee. It holds a coffee cup in one hand, sipping 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 # The index of the video frame corresponding to the mask
},
"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 the 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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope.aliyuncs.com/api/v1";
// API keys vary by region. For more information, see https://help.aliyun.com/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", "wanx2.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 drinking coffee. It holds a coffee cup in one hand, sipping 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 the 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
Function introduction: Predicts and generates continuous subsequent content based on an input image or video clip. It supports extending forward from the "first frame/first clip" or extending backward from the "last frame/last clip". The total duration of the final generated video is fixed at 5 seconds.
Parameters:
-
function: Must be set tovideo_extension. -
prompt: Required. Describes the desired extended content. -
first_clip_url: Optional. You can input the URL of the first video clip (≤3 seconds). The model will generate the rest of the video based on this clip. -
last_clip_url: Optional. You can input the URL of the last video clip (≤3 seconds). The model will generate the preceding part of the video based on this clip. -
first_frame_url: Optional. You can input the URL of the first frame image. The video will be extended forward from this frame. -
last_frame_url: Optional. You can input the URL of the last frame image. The video will be extended backward from this frame.Note: You must provide at least one of the following four parameters as input: first_clip_url, last_clip_url, first_frame_url, or last_frame_url.
|
Input prompt |
Input first clip (1 second) |
Output video (extended to 5 seconds) |
|
A dog wearing sunglasses is skateboarding on the street, 3D cartoon. |
curl
Step 1: Create a task to obtain a task ID
curl --location 'https://dashscope.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": "wanx2.1-vace-plus",
"input": {
"function": "video_extension",
"prompt": "A dog wearing sunglasses 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: Retrieve the result based on the task ID
Replace {task_id} with the task_id value returned by the previous API call. The task_id is valid for queries for 24 hours.
curl -X GET https://dashscope.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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope.aliyuncs.com/api/v1"
# API keys vary by region. For more information, see https://help.aliyun.com/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": "wanx2.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 the 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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope.aliyuncs.com/api/v1";
// API keys vary by region. For more information, see https://help.aliyun.com/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", "wanx2.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 the 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();
}
}
}
Video outpainting
Function introduction: Expands the video content in the top, bottom, left, and right directions based on a prompt and a specified ratio, while maintaining the coherence of the video's subject and the natural blending of the background.
Parameters:
-
function: Must be set tovideo_outpainting. -
video_url: Required. The URL of the original input video. -
top_scale: Optional. The upward expansion ratio. The range is [1.0, 2.0]. The default is 1.0 (no expansion). -
bottom_scale: Optional. The downward expansion ratio. The range is [1.0, 2.0]. The default is 1.0. -
left_scale: Optional. The leftward expansion ratio. The range is [1.0, 2.0]. The default is 1.0. -
right_scale: Optional. The rightward expansion ratio. The range is [1.0, 2.0]. The default is 1.0.
Example: Setting left_scale to 1.5 means the left side of the frame will be expanded 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 obtain a task ID
curl --location 'https://dashscope.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": "wanx2.1-vace-plus",
"input": {
"function": "video_outpainting",
"prompt": "An elegant woman passionately plays 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: Retrieve the result based on the task ID
Replace {task_id} with the task_id value returned by the previous API call. The task_id is valid for queries for 24 hours.
curl -X GET https://dashscope.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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope.aliyuncs.com/api/v1"
# API keys vary by region. For more information, see https://help.aliyun.com/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
def create_task():
"""Create a video outpainting 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": "wanx2.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 the 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 China (Beijing) region. URLs vary by region. For more information, see https://help.aliyun.com/en/model-studio/wanx-vace-api-reference
static final String BASE_URL = "https://dashscope.aliyuncs.com/api/v1";
// API keys vary by region. For more information, see https://help.aliyun.com/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);
sb.append("\n");
}
return sb.toString();
}
}
// Step 1: Create a video outpainting task
public static String createTask() throws Exception {
JSONObject body = new JSONObject()
.put("model", "wanx2.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 the 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 outpainting 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();
}
}
}
How to input images and videos
Input images
-
Number of images: You can provide the number of images corresponding to the selected feature.
-
Input methods:
-
Public URL: Supports the HTTP or HTTPS protocol. Example: https://xxxx/xxx.png.
-
Temporary URL: Supports the OSS protocol. You must upload a file to obtain a temporary URL. Example: oss://dashscope-instant/xxx/xxx.png.
-
Input videos
-
Number of videos: You can provide the number of videos corresponding to the selected feature.
-
Input methods:
-
Public URL: Supports the HTTP or HTTPS protocol. Example: https://xxxx/xxx.mp4.
-
Temporary URL: Supports the OSS protocol. You must upload a file to obtain a temporary URL. Example: oss://dashscope-instant/xxx/xxx.mp4.
-
Output videos
-
Number of videos: 1.
-
Video specifications: The total resolution is fixed at 720P, with a frame rate of 30 fps, in MP4 format (H.264 encoding).
-
Video URL validity: 24 hours.
-
Video dimensions: Vary depending on the selected feature.
-
Multi-image reference / Local editing:
-
The output resolution is fixed at 720P.
-
The specific width and height are determined by the size request parameter.
-
-
Video repainting / Video extension / Video outpainting:
-
If the input video resolution is ≤ 720P: The output maintains the original resolution.
-
If the input video resolution is > 720P: The output is scaled down to 720P while maintaining the aspect ratio.
-
-
Billing and rate limiting
-
For more information about the model's free quota and billing rates, see Model pricing.
-
For more information about model rate limits, see Wanxiang series.
-
Billing description:
-
You are not billed for inputs. Billing is based on the duration in seconds of the successfully generated video.
-
Failed model calls or processing errors do not incur any fees and do not consume the new user free quota.
-
Universal video editing also supports savings plans.
-
API documentation
FAQ
Q: How many images does the multi-image reference feature support at most?
A: It supports up to 3 reference images. If you provide more than 3, only the first 3 are used as input. We recommend using a solid background for the subject image to better highlight the subject, and a background image that does not contain any subjects.
Q: When should I disable prompt rewriting for video repainting?
A: When the text description is inconsistent with the input video content, the model may misinterpret it. We recommend manually disabling prompt rewriting by setting prompt_extend=false, and providing a clear, specific description of the scene in the prompt to improve generation consistency and accuracy.
Q: In the local editing feature, what is the difference between a mask image and a mask video?
A: You must provide either mask_image_url or mask_video_url. We recommend using a mask image. You only need to specify the editing area for one frame, and the system will automatically track the target.


