QwenCloudBRASIL
Tradução de apoio para consulta. Código e identificadores técnicos preservados. Consultar referência original ↗

Wan — Edite um vídeo

Enviar tarefa de edição de vídeo

Este modelo gera vídeos a partir de entradas de texto, imagem e vídeo.

OpenAPI

openapi: 3.1.0
info:
  title: Wan General Video Editing API
  description: "Wan unified video editing API. Supports multimodal input (text, image, video) with five core capabilities: multi-image reference, video repainting, local editing, video extension, and frame expansion."
  version: 1.0.0
servers:
  - url: https://maas.qwencloudapi.com/api/v1
    description: Singapore
security:
  - BearerAuth: []
paths:
  /services/aigc/video-generation/video-synthesis:
    post:
      operationId: createVideoEditing
      summary: Create video editing task
      description: Create a video editing task.
      parameters:
        - name: X-DashScope-Async
          in: header
          required: true
          description: Must be `enable` to create an asynchronous task.
          schema:
            type: string
            enum:
              - enable
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VideoEditingRequest"
      responses:
        "200":
          description: Task created successfully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AsyncTaskSubmitResponse"
        "400":
          description: Invalid request parameters.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DashScopeErrorResponse"
      x-codeSamples:
        - lang: curl
          label: cURL - Multi-image reference
          source: |-
            curl --location 'https://maas.qwencloudapi.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"
              }
            }'
        - lang: python
          label: Python - Multi-image reference
          source: |-
            import os
            import requests
            import time

            BASE_URL = "https://maas.qwencloudapi.com/api/v1"
            API_KEY = os.getenv("DASHSCOPE_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}")
        - lang: java
          label: Java - Multi-image reference
          source: |-
            import org.json.*;
            import java.io.*;
            import java.net.*;
            import java.util.HashMap;
            import java.util.Map;

            public class VideoSynthesis {
                static final String BASE_URL = "https://maas.qwencloudapi.com/api/v1";
              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");
              }

              public static boolean isValidUserUrl(String urlString) {
                try {
                  URL url = new URL(urlString);
                  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;
                }
              }

              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);
                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;
              }

              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");
                  }
                  return sb.toString();
                }
              }

              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);

                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");
              }

              public static String pollResult(String taskId) throws Exception {
                while (true) {
                  String resp = httpGet("/tasks/" + taskId);
                  JSONObject responseJson = new JSONObject(resp);

                  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();
                }
              }

            }
        - lang: curl
          label: cURL - Video repainting
          source: |-
            curl --location 'https://maas.qwencloudapi.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"
              }
            }'
        - lang: python
          label: Python - Video repainting
          source: |-
            import os
            import requests
            import time

            BASE_URL = "https://maas.qwencloudapi.com/api/v1"
            API_KEY = os.getenv("DASHSCOPE_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}")
        - lang: java
          label: Java - Video repainting
          source: |-
            import org.json.*;
            import java.io.*;
            import java.net.*;
            import java.util.HashMap;
            import java.util.Map;

            public class VideoRepainting {
                static final String BASE_URL = "https://maas.qwencloudapi.com/api/v1";
              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");
              }

              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);
                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;
              }

              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();
                }
              }

              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");
              }

              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();
                }
              }
            }
        - lang: curl
          label: cURL - Local editing
          source: |-
            curl --location 'https://maas.qwencloudapi.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
              }
            }'
        - lang: python
          label: Python - Local editing
          source: |-
            import os
            import requests
            import time

            BASE_URL = "https://maas.qwencloudapi.com/api/v1"
            API_KEY = os.getenv("DASHSCOPE_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}")
        - lang: java
          label: Java - Local editing
          source: |-
            import org.json.*;
            import java.io.*;
            import java.net.*;
            import java.util.HashMap;
            import java.util.Map;

            public class VideoRegionalEdit {
                static final String BASE_URL = "https://maas.qwencloudapi.com/api/v1";
              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();
                }
              }

              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");
              }

              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();
                }
              }
            }
        - lang: curl
          label: cURL - Video extension
          source: |-
            curl --location 'https://maas.qwencloudapi.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
              }
            }'
        - lang: python
          label: Python - Video extension
          source: |-
            import os
            import requests
            import time

            BASE_URL = "https://maas.qwencloudapi.com/api/v1"
            API_KEY = os.getenv("DASHSCOPE_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}")
        - lang: java
          label: Java - Video extension
          source: |-
            import org.json.*;
            import java.io.*;
            import java.net.*;
            import java.util.HashMap;
            import java.util.Map;

            public class VideoExtension {
                static final String BASE_URL = "https://maas.qwencloudapi.com/api/v1";
              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();
                }
              }

              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");
              }

              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();
                }
              }
            }
        - lang: curl
          label: cURL - Frame expansion
          source: |-
            curl --location 'https://maas.qwencloudapi.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
              }
            }'
        - lang: python
          label: Python - Frame expansion
          source: |-
            import os
            import requests
            import time

            BASE_URL = "https://maas.qwencloudapi.com/api/v1"
            API_KEY = os.getenv("DASHSCOPE_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}")
        - lang: java
          label: Java - Frame expansion
          source: |-
            import org.json.*;
            import java.io.*;
            import java.net.*;
            import java.util.HashMap;
            import java.util.Map;

            public class VideoOutpainting {
                static final String BASE_URL = "https://maas.qwencloudapi.com/api/v1";
              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();
                }
              }

              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");
              }

              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();
                }
              }
            }
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: DashScope API Key. Create one in the [QwenCloud console](https://home.qwencloud.com/api-keys).
  schemas:
    VideoEditingRequest:
      type: object
      required:
        - model
        - input
      properties:
        model:
          type: string
          description: Model name.
          enum:
            - wan2.1-vace-plus
          example: wan2.1-vace-plus
        input:
          $ref: "#/components/schemas/VideoEditingInput"
        parameters:
          $ref: "#/components/schemas/VideoEditingParameters"
    VideoEditingInput:
      type: object
      required:
        - function
        - prompt
      description: Input data for video editing. Required fields vary by function.
      properties:
        function:
          type: string
          description: The video editing capability to use.
          enum:
            - image_reference
            - video_repainting
            - video_edit
            - video_extension
            - video_outpainting
          example: image_reference
        prompt:
          type: string
          description: Text description of the desired video content.
          example: In the video, a girl walks out from the depths of an ancient, misty forest.
        ref_images_url:
          type: array
          description: Array of reference image URLs. Used by `image_reference` (1-3 images) and optionally by `video_repainting` and `video_edit` (1 image to replace subject).
          items:
            type: string
            format: uri
          minItems: 1
          maxItems: 3
          example:
            - http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png
            - http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png
        video_url:
          type: string
          format: uri
          description: URL of the input video. Required for `video_repainting`, `video_edit`, and `video_outpainting`. Must be MP4 format, no larger than 50 MB, and no longer than 5 seconds.
          example: http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4
        mask_image_url:
          type: string
          format: uri
          description: URL of a mask image for `video_edit`. White areas are edited; black areas remain unchanged. Specify either this or `mask_video_url`.
        mask_video_url:
          type: string
          format: uri
          description: URL of a mask video for `video_edit`. Specify either this or `mask_image_url`. Using `mask_image_url` is recommended.
        mask_frame_id:
          type: integer
          description: "For `video_edit` with `mask_image_url`: specifies which video frame the mask corresponds to. Default: first frame (0)."
          default: 0
          example: 1
        first_clip_url:
          type: string
          format: uri
          description: "For `video_extension`: 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:
          type: string
          format: uri
          description: "For `video_extension`: URL of the last video clip (3 seconds or shorter). The model generates the preceding content."
        first_frame_url:
          type: string
          format: uri
          description: "For `video_extension`: URL of the first frame image. The video extends forward from this frame."
        last_frame_url:
          type: string
          format: uri
          description: "For `video_extension`: URL of the last frame image. Generation proceeds backward from this frame."
    VideoEditingParameters:
      type: object
      description: Generation parameters for video editing. Available parameters vary by function.
      properties:
        prompt_extend:
          type: boolean
          description: "Enable prompt rewriting. `true` (default): model optimizes your prompt. `false`: use your prompt as-is. We recommend disabling this for `video_repainting`."
          default: true
        size:
          type: string
          description: Output resolution as `width*height`. Used by `image_reference` and `video_edit`.
          example: 1280*720
        obj_or_bg:
          type: array
          description: "For `image_reference`: identifies each reference image as a subject (`obj`) or background (`bg`). Array length must match `ref_images_url` length."
          items:
            type: string
            enum:
              - obj
              - bg
          example:
            - obj
            - bg
        control_condition:
          type: string
          description: "For `video_repainting`: video feature extraction method. Determines which features from the original video are retained."
          enum:
            - posebodyface
            - posebody
            - depth
            - scribble
          example: depth
        strength:
          type: number
          description: "For `video_repainting`: controls feature extraction strength. Higher values make the output more similar to the original; lower values allow more creative freedom."
          minimum: 0
          maximum: 1
          default: 1
        mask_type:
          type: string
          description: "For `video_edit`: specifies the behavior of the editing area. `tracking` (default): the editing area automatically follows the target's motion. `fixed`: the editing area stays in a fixed position."
          enum:
            - tracking
            - fixed
          default: tracking
        expand_ratio:
          type: number
          description: "For `video_edit` with `mask_type: tracking`: the ratio by which the mask area expands outward. Lower values fit the target more closely; higher values expand the mask area."
          minimum: 0
          maximum: 1
          default: 0.05
        top_scale:
          type: number
          description: "For `video_outpainting`: upward expansion ratio. Setting to 1.5 expands the top to 1.5 times original height."
          minimum: 1
          maximum: 2
          default: 1
        bottom_scale:
          type: number
          description: "For `video_outpainting`: downward expansion ratio."
          minimum: 1
          maximum: 2
          default: 1
        left_scale:
          type: number
          description: "For `video_outpainting`: leftward expansion ratio."
          minimum: 1
          maximum: 2
          default: 1
        right_scale:
          type: number
          description: "For `video_outpainting`: rightward expansion ratio."
          minimum: 1
          maximum: 2
          default: 1
    AsyncTaskSubmitResponse:
      type: object
      description: Response returned when an asynchronous task is created successfully.
      properties:
        request_id:
          type: string
          description: Unique request identifier.
        output:
          type: object
          properties:
            task_id:
              type: string
              description: Task identifier. Use this with `GET /tasks/{task_id}` to poll for results.
            task_status:
              type: string
              description: Initial task status, typically `PENDING`.
              enum:
                - PENDING
    TaskStatusResponse:
      type: object
      description: Response containing the current status and results of a video editing task.
      properties:
        request_id:
          type: string
          description: Unique request identifier.
        output:
          type: object
          properties:
            task_id:
              type: string
              description: Task identifier.
            task_status:
              type: string
              description: Current task status.
              enum:
                - PENDING
                - RUNNING
                - SUCCEEDED
                - FAILED
                - CANCELLED
            video_url:
              type: string
              format: uri
              description: Generated video URL. Only present when `task_status` is `SUCCEEDED`. Valid for 24 hours — download promptly.
            code:
              type: string
              description: Error code. Only present when `task_status` is `FAILED`.
            message:
              type: string
              description: Error message. Only present when `task_status` is `FAILED`.
        usage:
          type: object
          description: Usage statistics (only present when task succeeds).
          properties:
            video_count:
              type: integer
              description: Number of videos generated.
            video_duration:
              type: integer
              description: Duration of the generated video in seconds.
    DashScopeErrorResponse:
      type: object
      description: DashScope API error response.
      properties:
        request_id:
          type: string
          description: Unique request identifier.
        code:
          type: string
          description: Error code (e.g., `InvalidParameter`, `Throttling`, `Unauthorized`).
          example: InvalidParameter
        message:
          type: string
          description: Human-readable error message.
          example: "Invalid parameter: function"