全部產品
Search
文件中心

Alibaba Cloud Model Studio:通用視頻編輯

更新時間:Feb 12, 2026

萬相視頻編輯統一模型支援多模態輸入(文本/映像/視頻),可實現多圖參考、視頻重繪、局部編輯、視頻延展、畫面擴充五大核心能力。

適用範圍

各地區支援的模型有所差異,且資源相互獨立。調用時,確保模型、Endpoint URL 和 API Key 均屬於同一地區,跨地區調用將會失敗。

支援的模型

國際

國際部署模式下,存取點與資料存放區均位於新加坡地區,模型推理計算資源在全球範圍內動態調度(不含中國內地)。

模型名稱

能力支援

輸入模態

輸出視頻規格

wan2.1-vace-plus

無聲視頻

多圖參考、視頻重繪、局部編輯、視頻延展、視頻畫面擴充

文本、映像、視頻

解析度檔位:720P

視頻時間長度:不超過5s

固定規格:30fps、MP4(H.264編碼)

中國內地

中國內地部署模式下,存取點與資料存放區均位於北京地區,模型推理計算資源僅限於中國內地。

模型名稱

能力支援

輸入模態

輸出視頻規格

wanx2.1-vace-plus

無聲視頻

多圖參考、視頻重繪、局部編輯、視頻延展、視頻畫面擴充

文本、映像、視頻

解析度檔位:720P

視頻時間長度:不超過5s

固定規格:30fps、MP4(H.264編碼)

說明

本文的範例程式碼適用於新加坡地區

核心能力

多圖參考

功能介紹:支援最多 3張參考映像,可包括主體與背景(如人物、動物、服飾、情境等)。模型將多張圖片融合產生連貫的視頻內容。

參數設定:

  • function:必須設為 image_reference

  • ref_images_url:URL數組,支援輸入1~3張參考圖。

  • obj_or_bg:標識每張圖為主體(obj)還是背景(bg),與ref_images_url長度一致。

輸入提示詞

輸入參考圖1(參考主體)

輸入參考圖2(參考背景)

輸出視頻

視頻中,一位女孩自晨霧繚繞的古老森林深處款款走出,她步伐輕盈,鏡頭捕捉她每一個靈動瞬間。當她站定,環顧四周蔥鬱林木時,她臉上綻放出驚喜與喜悅交織的笑容。這一幕,定格在了光影交錯的瞬間,記錄下她與大自然的美妙邂逅。

image

image

在調用前,先擷取API Key,再配置API Key到環境變數(準備下線,併入配置 API Key)

curl

步驟1:建立任務擷取任務ID

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "image_reference",
        "prompt": "視頻中,一位女孩自晨霧繚繞的古老森林深處款款走出,她步伐輕盈,鏡頭捕捉她每一個靈動瞬間。當她站定,環顧四周蔥鬱林木時,她臉上綻放出驚喜與喜悅交織的笑容。這一幕,定格在了光影交錯的瞬間,記錄下她與大自然的美妙邂逅。",
        "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"
    }
}'

步驟2:根據任務ID擷取結果

{task_id}完整替換為上一步介面返回的task_id的值。

curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")
headers = {"X-DashScope-Async": "enable", "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

def create_task():
    """建立視頻合成任務,返回 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": "視頻中,一位女孩自晨霧繚繞的古老森林深處款款走出,她步伐輕盈,鏡頭捕捉她每一個靈動瞬間。當女孩站定,環顧四周蔥鬱林木時,她臉上綻放出驚喜與喜悅交織的笑容。這一幕,定格在了光影交錯的瞬間,記錄下女孩與大自然的美妙邂逅。",
                    "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"建立任務失敗: {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"任務失敗: {data.get('message', '未知錯誤')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"輪詢異常: {e},15秒後重試...")
            time.sleep(15)


if __name__ == "__main__":
    task_id = create_task()
    print(f"任務ID: {task_id}")
    video_url = poll_result(task_id)
    print(f"\n視頻產生成功: {video_url}")

Java

import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;

public class VideoSynthesis {
    // 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
    static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
    private static final Map<String, String> COMMON_HEADERS = new HashMap<>();

    static {
        if (API_KEY == null || API_KEY.isEmpty()) {
            throw new IllegalStateException("未設定 DASHSCOPE_API_KEY");
        }
        COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
        // 啟用HTTP Keep-Alive(JVM預設已開啟,顯式設定更可靠)
        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("無效的URL: " + e.getMessage());
            return false;
        }
    }
    
    // 通用HTTP POST請求
    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);
    }

    // 通用HTTP GET請求
    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);  // 30秒連線逾時
        conn.setReadTimeout(60000);     // 60秒讀取逾時
        conn.setInstanceFollowRedirects(true);  // 允許重新導向
        
        // 設定通用Header
        for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
            conn.setRequestProperty(entry.getKey(), entry.getValue());
        }
        
        // 非同步任務專用Header
        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("無法擷取響應流,響應碼: " + 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();
        }
    }

    // 步驟1:建立任務
    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", "視頻中,一位女孩自晨霧繚繞的古老森林深處款款走出,她步伐輕盈,鏡頭捕捉她每一個靈動瞬間。當女孩站定,環顧四周蔥鬱林木時,她臉上綻放出驚喜與喜悅交織的笑容。這一幕,定格在了光影交錯的瞬間,記錄下女孩與大自然的美妙邂逅。")
                        .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", "未知錯誤");
            throw new RuntimeException("建立任務失敗: " + errorMessage + ", 詳細資料: " + resp);
        }
        JSONObject output = jsonResponse.getJSONObject("output");
        return output.getString("task_id");
    }

    // 步驟2:輪詢結果(15秒間隔,無次數限制)
    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響應缺少'output'欄位: " + 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", "未知錯誤");
                throw new RuntimeException("任務失敗: " + message + ", 任務ID: " + taskId + ", 詳細資料: " + resp);
            }
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("正在建立視頻合成任務...");
            String taskId = createTask();
            System.out.println("任務建立成功,Task ID: " + taskId);
            System.out.println("正在輪詢任務結果...");
            String videoUrl = pollResult(taskId);
            System.out.println("視頻URL: " + videoUrl);
        } catch (Exception e) {
            System.err.println("發生錯誤: " + e.getMessage());
            e.printStackTrace(); // 列印完整的堆疊追蹤以便調試
        }
    }

}

視頻重繪

功能介紹:從輸入視頻中提取主體姿態與動作、構圖與運動輪廓或線稿結構,結合文本提示詞產生具有相同動態特徵的新視頻。還支援通過參考映像替換原視頻中的主體。

參數設定:

  • function: 必須設為 video_repainting

  • video_url必填。輸入視頻的URL地址(MP4格式,≤50MB,≤5秒)。

  • control_condition必填。設定視頻特徵提取的方式,決定了新視頻保留原視頻的哪些特徵。

    • posebodyface:提取臉部表情和肢體動作(保留面部表情細節)。

    • posebody:僅提取肢體動作,不含臉部(僅控制身體動作)。

    • depth:提取構圖和運動輪廓(保留情境結構)。

    • scribble:提取線稿結構(保留線稿邊緣細節)。

  • strength:可選。控制特徵提取的強度,範圍 [0.0, 1.0],預設 1.0。數值越大越貼近原視頻,數值越小產生越自由。

  • ref_images_url:可選。傳入1張參考映像URL,用於替換輸入視頻中的主體。

輸入提示詞

輸入視頻

輸出視頻

視頻展示了一輛黑色的蒸汽龐克風格汽車,紳士駕駛著,車輛裝飾著齒輪和銅管。背景是蒸汽驅動的糖果工廠和複古元素,畫面複古與趣味

curl

步驟1:建立任務擷取任務ID

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_repainting",
        "prompt": "視頻展示了一輛黑色的蒸汽龐克風格汽車,紳士駕駛著,車輛裝飾著齒輪和銅管。背景是蒸汽驅動的糖果工廠和複古元素,畫面複古與趣味。",
        "video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
    },
    "parameters": {
        "prompt_extend": false,
        "control_condition": "depth"
    }
}'

步驟2:根據任務ID擷取結果

{task_id}完整替換為上一步介面返回的task_id的值。

curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """建立視頻重繪任務,返回 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": "視頻展示了一輛黑色的蒸汽龐克風格汽車,紳士駕駛著,車輛裝飾著齒輪和銅管。背景是蒸汽驅動的糖果工廠和複古元素,畫面複古與趣味。",
                    "video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
                },
                "parameters": {
                    "prompt_extend": False, # 視頻重繪建議關閉prompt智能改寫
                    "control_condition": "depth" # 可選: posebodyface, posebody, depth, scribble
                }
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"建立任務失敗: {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"任務失敗: {data.get('message', '未知錯誤')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"輪詢異常: {e},15秒後重試...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"任務ID: {task_id}")
    video_url = poll_result(task_id)
    print(f"\n視頻產生成功: {video_url}")

Java

import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;

public class VideoRepainting {
    // 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
    static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
    private static final Map<String, String> COMMON_HEADERS = new HashMap<>();

    static {
        if (API_KEY == null || API_KEY.isEmpty()) {
            throw new IllegalStateException("未設定 DASHSCOPE_API_KEY");
        }
        COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
        System.setProperty("http.keepAlive", "true");
        System.setProperty("http.maxConnections", "20");
    }

    // 通用HTTP POST請求
    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);
    }

    // 通用HTTP GET請求
    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("無法擷取響應流,響應碼: " + 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();
        }
    }

    // 步驟1:建立視頻重繪任務
    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", "視頻展示了一輛黑色的蒸汽龐克風格汽車,紳士駕駛著,車輛裝飾著齒輪和銅管。背景是蒸汽驅動的糖果工廠和複古元素,畫面複古與趣味。")
                        .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", "未知錯誤");
            throw new RuntimeException("建立任務失敗: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // 步驟2:輪詢結果
    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("任務失敗: " + output.optString("message", "未知錯誤"));
            }
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("正在建立視頻重繪任務...");
            String taskId = createTask();
            System.out.println("任務建立成功,Task ID: " + taskId);
            System.out.println("正在輪詢任務結果...");
            String videoUrl = pollResult(taskId);
            System.out.println("視頻URL: " + videoUrl);
        } catch (Exception e) {
            System.err.println("發生錯誤: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

局部編輯

功能介紹:對視頻指定地區進行精細化編輯,支援元素增刪改和主體背景替換。上傳掩碼映像指定編輯地區,模型將自動跟蹤目標並融合產生內容。

參數設定:

  • function:必須設為 video_edit

  • video_url必填。輸入原視頻的URL地址。

  • mask_image_url:可選。與 mask_video_url 二選一,推薦使用此參數。輸入遮罩映像URL,白色地區代表需要編輯的部分,黑色地區保留不變。

  • mask_frame_id:可選。配合 mask_image_url 使用,指定掩碼對應視頻的哪一幀(預設第1幀)。

  • mask_type:可選。指定編輯地區的行為方式:

    • tracking(預設):編輯地區會根據目標物體的運動軌跡自動跟隨。

    • fixed:編輯地區保持固定位置不變。

  • expand_ratio:可選。僅當 mask_type 為 tracking 時生效。

    • 作用:設定掩碼地區向外擴充的比例。取值範圍[0.0, 1.0],預設值為 0.05。

    • 說明:數值越小,掩碼越貼合目標;數值越大,掩碼擴充範圍越廣。

  • ref_images_url:可選。傳入1張參考映像URL,用於將編輯地區的內容替換為該參考圖的內容。

輸入提示詞

輸入視頻

輸入遮罩映像

輸出視頻

視頻展示了一家巴黎風情的法式咖啡館,一隻穿著西裝的獅子優雅地品著咖啡。它一手端著咖啡杯,輕輕啜飲,神情愜意。咖啡館裝飾雅緻,柔和的色調與溫暖燈光映照著獅子所在的地區。

mask

白色地區表示編輯地區

curl

步驟1:建立任務擷取任務ID

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_edit",
        "prompt": "視頻展示了一家巴黎風情的法式咖啡館,一隻穿著西裝的獅子優雅地品著咖啡。它一手端著咖啡杯,輕輕啜飲,神情愜意。咖啡館裝飾雅緻,柔和的色調與溫暖燈光映照著獅子所在的地區。",
        "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
    }
}'

步驟2:根據任務ID擷取結果

{task_id}完整替換為上一步介面返回的task_id的值。

curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

安裝依賴:pip install requests。
import os
import requests
import time

# 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """建立局部編輯任務,返回 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": "視頻展示了一家巴黎風情的法式咖啡館,一隻穿著西裝的獅子優雅地品著咖啡。它一手端著咖啡杯,輕輕啜飲,神情愜意。咖啡館裝飾雅緻,柔和的色調與溫暖燈光映照著獅子所在的地區。",
                    "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
                }
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"建立任務失敗: {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"任務失敗: {data.get('message', '未知錯誤')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"輪詢異常: {e},15秒後重試...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"任務ID: {task_id}")
    video_url = poll_result(task_id)
    print(f"\n視頻產生成功: {video_url}")

Java

import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;

public class VideoRegionalEdit {
    // 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
    static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
    private static final Map<String, String> COMMON_HEADERS = new HashMap<>();

    static {
        if (API_KEY == null || API_KEY.isEmpty()) {
            throw new IllegalStateException("未設定 DASHSCOPE_API_KEY");
        }
        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();
        }
    }

    // 步驟1:建立局部編輯任務
    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", "視頻展示了一家巴黎風情的法式咖啡館,一隻穿著西裝的獅子優雅地品著咖啡。它一手端著咖啡杯,輕輕啜飲,神情愜意。咖啡館裝飾雅緻,柔和的色調與溫暖燈光映照著獅子所在的地區。")
                        .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", "未知錯誤");
            throw new RuntimeException("建立任務失敗: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // 步驟2:輪詢結果
    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("任務失敗: " + output.optString("message"));
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("正在建立局部編輯任務...");
            String taskId = createTask();
            System.out.println("任務建立成功,Task ID: " + taskId);
            String videoUrl = pollResult(taskId);
            System.out.println("視頻URL: " + videoUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

視頻延展

功能介紹:基於輸入的映像或視頻片段,預測並產生具有連續性的後續內容。支援“首幀/首片段”向後延展,或“尾幀/尾片段”向前延展。最終產生的視頻總時間長度固定為5秒。

參數設定:

  • function:必須設為 video_extension

  • prompt必填。描述期望產生的延展內容。

  • first_clip_url:可選。輸入首段視頻URL(≤3秒),模型將基於此片段向後延續產生視頻。

  • last_clip_url:可選。輸入尾段視頻URL(≤3秒),模型將基於此片段向前反向推算產生視頻。

  • first_frame_url:可選,輸入首幀映像的 URL 地址。基於首幀映像向後延展。

  • last_frame_url:可選,輸入尾幀映像的 URL 地址。基於尾幀映像向前延展。

    注意:first_clip_url、last_clip_url、first_frame_url、last_frame_url 四個參數中,必須至少提供一項作為輸入。

輸入提示詞

輸入首片段視頻(1秒)

輸出視頻(延長後的視頻為5秒)

一隻戴著墨鏡的狗在街道上滑滑板,3D卡通。

curl

步驟1:建立任務擷取任務ID

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_extension",
        "prompt": "一隻戴著墨鏡的狗在街道上滑滑板,3D卡通。",
        "first_clip_url": "http://wanx.alicdn.com/material/20250318/video_extension_1.mp4"
    },
    "parameters": {
        "prompt_extend": false
    }
}'

步驟2:根據任務ID擷取結果

{task_id}完整替換為上一步介面返回的task_id的值。

curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """建立視頻延展任務,返回 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": "一隻戴著墨鏡的狗在街道上滑滑板,3D卡通。",
                    "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"建立任務失敗: {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"任務失敗: {data.get('message', '未知錯誤')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"輪詢異常: {e},15秒後重試...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"任務ID: {task_id}")
    video_url = poll_result(task_id)
    print(f"\n視頻產生成功: {video_url}")

Java

import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;

public class VideoExtension {
    // 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
    static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
    private static final Map<String, String> COMMON_HEADERS = new HashMap<>();

    static {
        if (API_KEY == null || API_KEY.isEmpty()) {
            throw new IllegalStateException("未設定 DASHSCOPE_API_KEY");
        }
        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();
        }
    }

    // 步驟1:建立視頻延展任務
    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", "一隻戴著墨鏡的狗在街道上滑滑板,3D卡通。")
                        .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", "未知錯誤");
            throw new RuntimeException("建立任務失敗: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // 步驟2:輪詢結果
    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("任務失敗: " + output.optString("message"));
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("正在建立視頻延展任務...");
            String taskId = createTask();
            System.out.println("任務建立成功,Task ID: " + taskId);
            String videoUrl = pollResult(taskId);
            System.out.println("視頻URL: " + videoUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

視頻畫面擴充

功能介紹: 在視頻的上下左右四個方向上,根據提示詞按比例擴充畫面內容,保持視頻主體的連貫性和背景的自然融合。

參數設定:

  • function:必須設為 video_outpainting

  • video_url必填。輸入原視頻的URL地址。

  • top_scale:可選。向上擴充比例,範圍 [1.0, 2.0],預設值為1.0(不擴充)。

  • bottom_scale:可選。向下擴充比例,範圍 [1.0, 2.0],預設值為1.0。

  • left_scale:可選。向左擴充比例,範圍 [1.0, 2.0],預設值為1.0。

  • right_scale:可選。向右擴充比例,範圍 [1.0, 2.0],預設值為1.0。

樣本:設定 left_scale 為 1.5,表示左側畫面將擴充為原寬度的1.5倍。

輸入提示詞

輸入視頻

輸出視頻

一位優雅的女士正在激情演奏小提琴,她身後是一支完整的交響樂團

curl

步驟1:建立任務擷取任務ID

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_outpainting",
        "prompt": "一位優雅的女士正在激情演奏小提琴,她身後是一支完整的交響樂團。",
        "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
    }
}'

步驟2:根據任務ID擷取結果

{task_id}完整替換為上一步介面返回的task_id的值。

curl -X GET https://dashscope-intl.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """建立視頻畫面擴充任務,返回 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": "一位優雅的女士正在激情演奏小提琴,她身後是一支完整的交響樂團。",
                    "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   # 右方擴充比例
                }
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"建立任務失敗: {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"任務失敗: {data.get('message', '未知錯誤')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"輪詢異常: {e},15秒後重試...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"任務ID: {task_id}")
    video_url = poll_result(task_id)
    print(f"\n視頻產生成功: {video_url}")

Java

import org.json.*;
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;

public class VideoOutpainting {
    // 以下為新加坡地區URL,各地區的URL不同,擷取URL:https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // 各地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/en/model-studio/get-api-key
    static final String API_KEY = System.getenv("DASHSCOPE_API_KEY");
    private static final Map<String, String> COMMON_HEADERS = new HashMap<>();

    static {
        if (API_KEY == null || API_KEY.isEmpty()) {
            throw new IllegalStateException("未設定 DASHSCOPE_API_KEY");
        }
        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();
        }
    }

    // 步驟1:建立視頻畫面擴充任務
    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", "一位優雅的女士正在激情演奏小提琴,她身後是一支完整的交響樂團。")
                        .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", "未知錯誤");
            throw new RuntimeException("建立任務失敗: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // 步驟2:輪詢結果
    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("任務失敗: " + output.optString("message"));
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("正在建立視頻畫面擴充任務...");
            String taskId = createTask();
            System.out.println("任務建立成功,Task ID: " + taskId);
            String videoUrl = pollResult(taskId);
            System.out.println("視頻URL: " + videoUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如何輸入映像和視頻

輸入映像

  • 映像數量:根據所選功能傳入對應數量的映像。

  • 輸入方式

    • 公網URL:支援 HTTP 或 HTTPS 協議。樣本:https://xxxx/xxx.png。

輸入視頻

  • 視頻數量:根據所選功能傳入對應數量的視頻。

  • 輸入方式

    • 公網URL:支援 HTTP 或 HTTPS 協議。樣本:https://xxxx/xxx.mp4。

輸出視頻

  • 視頻數量:1個。

  • 視頻規格:解析度總像素固定為720P,幀率30fps,格式為MP4(H.264 編碼)。

  • 視頻URL有效期間24小時

  • 視頻尺寸:根據所選功能不同而有所差異。

    • 多圖參考 / 局部編輯

      • 輸出固定為 720P 規格。

      • 具體寬高由請求參數 size 決定。

    • 視頻重繪 / 視頻延展 / 視頻畫面擴充

      • 若輸入視頻解析度 ≤ 720P:保持原生解析度輸出。

      • 若輸入視頻解析度 > 720P:保持寬高比不變,按比例縮放至 720P 輸出。

計費與限流

  • 模型免費額度和計費單價請參見模型價格

  • 模型限流請參見萬相系列

  • 計費說明:

    • 輸入不計費,輸出計費。按成功產生的 視頻秒數 計費。

    • 模型調用失敗或處理錯誤不產生任何費用,也不消耗新人免費額度

    • 通用視頻編輯還支援節省計劃

API文檔

通用視頻編輯API參考

常見問題

Q:多圖參考功能最多支援幾張圖片?

A:最多支援3張參考映像。若超過3張,僅保留前3張作為輸入。建議主體映像使用純色背景以便更好突出主體,背景映像不包含任何主體對象。

Q: 視頻重繪時什麼情況下應該關閉prompt智能改寫?

A: 當文本描述與輸入視頻內容不一致時,模型可能產生誤解。建議手動關閉智能改寫prompt_extend=false,並在prompt中提供清晰、具體的畫面描述,以提升產生一致性與準確性。

Q:局部編輯功能中,掩碼映像和掩碼視頻有什麼區別?

A:掩碼映像mask_image_url與掩碼視頻mask_video_url二選一填寫。推薦優先使用掩碼映像,只需指定一幀的編輯地區,系統會自動跟蹤目標。