All Products
Search
Document Center

Alibaba Cloud Model Studio:Pengeditan video 2.1

Last Updated:Sep 02, 2026

Model pengeditan video universal Wanxiang mendukung input multimodal (teks, gambar, dan video) serta menyediakan lima kemampuan inti: multi-image reference, video repainting, local editing, video extension, dan video outpainting .

Cakupan penerapan

  • Model yang didukung berbeda-beda tergantung wilayahnya. Sumber daya diisolasi antar-wilayah. Untuk daftar model yang didukung di setiap wilayah, lihat Konsol Model Studio.
  • Saat melakukan panggilan, pastikan model, URL endpoint, dan Kunci API Anda semuanya berasal dari wilayah yang sama. Panggilan lintas-wilayah akan gagal.

CatatanKode contoh dalam topik ini berlaku untuk wilayah Singapura.

Kemampuan inti

Multi-image reference

Pengenalan fungsi: Mendukung hingga 3 gambar referensi, yang dapat mencakup subjek dan latar belakang (misalnya orang, hewan, pakaian, dan pemandangan). Model menggabungkan beberapa gambar untuk menghasilkan konten video yang konsisten.

Parameter:
  • function: Harus diatur ke image_reference.
  • ref_images_url: Array URL. Anda dapat memasukkan 1 hingga 3 gambar referensi.
  • obj_or_bg: Mengidentifikasi setiap gambar sebagai subjek (obj) atau latar belakang (bg). Panjang array ini harus sama dengan ref_images_url.
Prompt inputGambar referensi input 1 (subjek referensi)Gambar referensi input 2 (latar belakang referensi)Video keluaran

Dalam video tersebut, seorang gadis berjalan keluar dari kedalaman hutan kuno yang berkabut. Langkahnya ringan, dan kamera menangkap setiap momen anggunnya. Saat ia berhenti dan memandang sekeliling ke hutan yang rimbun, senyum kejutan dan kegembiraan muncul di wajahnya. Momen ini, yang tertangkap dalam permainan cahaya dan bayangan, merekam pertemuannya yang indah dengan alam.

imageimage

Sebelum melakukan panggilan, Anda harus terlebih dahulu mendapatkan Kunci API, lalu mengonfigurasi Kunci API sebagai variabel lingkungan (untuk mencegah publikasi dan memasukkannya ke dalam Configure API key).

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas
curl --location 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "image_reference",
        "prompt": "In the video, a girl gracefully emerges from a misty, ancient forest. Her steps are light, and the camera captures her every nimble moment. When she stops to look at the lush woods around her, a smile of surprise and joy blossoms on her face. This scene, frozen in an interplay of light and shadow, records her wonderful encounter with nature.",
        "ref_images_url": [
            "http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png",
            "http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png"
        ]
    },
    "parameters": {
        "prompt_extend": true,
        "obj_or_bg": ["obj","bg"],
        "size": "1280*720"
    }
}'
Langkah 2: Ambil hasil berdasarkan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh panggilan API sebelumnya. task_id berlaku untuk kueri selama 24 jam.

curl -X GET https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat 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():
    """Buat tugas sintesis video dan kembalikan 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 woods, a smile of surprise and joy appears on her face. This moment, captured in the interplay of light and shadow, records her wonderful encounter with nature.",
                    "ref_images_url": [
                        "http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png",
                        "http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png"
                    ]
                },
                "parameters": {"prompt_extend": True, "obj_or_bg": ["obj", "bg"], "size": "1280*720"}
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"Gagal membuat tugas: {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"Tugas gagal: {data.get('message', 'Kesalahan tidak diketahui')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"Kesalahan polling: {e}. Mencoba lagi dalam 15 detik...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"ID Tugas: {task_id}")
    video_url = poll_result(task_id)
    print(f"\nVideo berhasil dibuat: {video_url}")

Java

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

public class VideoSynthesis {
    // Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat 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 belum diatur");
        }
        COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
        // Aktifkan HTTP keep-alive (secara default diaktifkan di JVM, tetapi pengaturan eksplisit lebih andal)
        System.setProperty("http.keepAlive", "true");
        System.setProperty("http.maxConnections", "20");
    }

    public static boolean isValidUserUrl(String urlString) {
        try {
            URL url = new URL(urlString);
            // Periksa apakah protokolnya aman
            String protocol = url.getProtocol();
            if (!"https".equalsIgnoreCase(protocol) && !"http".equalsIgnoreCase(protocol)) {
                return false;
            }

            return true;
        } catch (Exception e) {
            System.err.println("URL tidak valid: " + e.getMessage());
            return false;
        }
    }

    // Permintaan HTTP POST umum
    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);
    }

    // Permintaan HTTP GET umum
    private static String httpGet(String path) throws Exception {
        HttpURLConnection conn = createConnection(path, "GET");
        return readResponse(conn);
    }

    // Buat koneksi (gunakan kembali parameter koneksi)
    private static HttpURLConnection createConnection(String path, String method) throws Exception {
        URL url = new URL(BASE_URL + path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        // Konfigurasikan properti koneksi
        conn.setRequestMethod(method);
        conn.setConnectTimeout(30000);  // Timeout koneksi 30 detik
        conn.setReadTimeout(60000);     // Timeout baca 60 detik
        conn.setInstanceFollowRedirects(true);  // Izinkan pengalihan

        // Atur header umum
        for (Map.Entry<String, String> entry : COMMON_HEADERS.entrySet()) {
            conn.setRequestProperty(entry.getKey(), entry.getValue());
        }

        // Header untuk tugas asinkron
        if (path.contains("video-synthesis")) {
            conn.setRequestProperty("X-DashScope-Async", "enable");
        }

        // Atur tipe konten dan tipe penerimaan
        conn.setRequestProperty("Accept", "application/json");

        return conn;
    }

    // Baca respons (otomatis tangani aliran kesalahan)
    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("Tidak dapat mendapatkan aliran respons. Kode respons: " + 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");  // Tambahkan jeda baris untuk mempertahankan format asli
            }
            return sb.toString();
        }
    }

    // Langkah 1: Buat tugas
    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 woods, a smile of surprise and joy appears on her face. This moment, captured in the interplay of light and shadow, records her wonderful encounter with nature.")
                        .put("ref_images_url", new JSONArray()
                                .put("http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png")
                                .put("http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png")))
                .put("parameters", new JSONObject()
                        .put("prompt_extend", true)
                        .put("obj_or_bg", new JSONArray().put("obj").put("bg"))
                        .put("size", "1280*720"));

        String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
        JSONObject jsonResponse = new JSONObject(resp);

        // Periksa apakah respons berisi pesan kesalahan
        if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
            String errorMessage = jsonResponse.optString("message", "Kesalahan tidak diketahui");
            throw new RuntimeException("Gagal membuat tugas: " + errorMessage + ", Detail: " + resp);
        }
        JSONObject output = jsonResponse.getJSONObject("output");
        return output.getString("task_id");
    }

    // Langkah 2: Polling hasil (interval 15 detik, tanpa batas percobaan ulang)
    public static String pollResult(String taskId) throws Exception {
        while (true) {
            String resp = httpGet("/tasks/" + taskId);
            JSONObject responseJson = new JSONObject(resp);

            // Validasi struktur respons
            if (!responseJson.has("output")) {
                throw new RuntimeException("Respons API tidak memiliki bidang '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", "Kesalahan tidak diketahui");
                throw new RuntimeException("Tugas gagal: " + message + ", ID Tugas: " + taskId + ", Detail: " + resp);
            }
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("Membuat tugas sintesis video...");
            String taskId = createTask();
            System.out.println("Tugas berhasil dibuat. ID Tugas: " + taskId);
            System.out.println("Melakukan polling hasil tugas...");
            String videoUrl = pollResult(taskId);
            System.out.println("URL Video: " + videoUrl);
        } catch (Exception e) {
            System.err.println("Terjadi kesalahan: " + e.getMessage());
            e.printStackTrace(); // Cetak jejak stack lengkap untuk debugging
        }
    }

}

Video repainting

Pengenalan fungsi: Mengekstraksi pose dan gerakan subjek, komposisi dan kontur gerak, atau struktur sketsa dari video input. Kemudian menghasilkan video baru dengan fitur dinamis yang sama berdasarkan prompt teks. Anda juga dapat mengganti subjek dalam video asli menggunakan gambar referensi.

Parameter:
  • function: Harus diatur ke video_repainting.

  • video_url: Wajib. URL video input (format MP4, ≤50 MB, ≤5 detik).

  • control_condition: Wajib. Menetapkan metode ekstraksi fitur video, yang menentukan fitur mana dari video asli yang dipertahankan dalam video baru.

    • posebodyface: Mengekstraksi ekspresi wajah dan gerakan tubuh (mempertahankan detail ekspresi wajah).
    • posebody: Hanya mengekstraksi gerakan tubuh, tanpa wajah (mengontrol hanya gerakan tubuh).
    • depth: Mengekstraksi komposisi dan kontur gerak (mempertahankan struktur adegan).
    • scribble: Mengekstraksi struktur sketsa (mempertahankan detail tepi sketsa).
  • strength: Opsional. Mengontrol kekuatan ekstraksi fitur. Rentang nilainya [0.0, 1.0]. Nilai default adalah 1.0. Nilai yang lebih besar membuat output lebih mirip video asli, sedangkan nilai yang lebih kecil memberikan kebebasan kreatif lebih besar.

  • ref_images_url: Opsional. Berikan URL satu gambar referensi untuk mengganti subjek dalam video input.

Input promptVideo inputVideo keluaran

Video tersebut menampilkan sebuah mobil bergaya steampunk hitam yang dikendarai seorang pria, dihiasi roda gigi dan pipa tembaga. Latar belakangnya adalah pabrik permen berbasis uap dengan elemen retro, menciptakan adegan vintage dan menyenangkan.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas
curl --location 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_repainting",
        "prompt": "The video shows a black steampunk-style car driven by a gentleman, adorned with gears and copper pipes. The background is a steam-powered candy factory with retro elements, creating a vintage and fun scene.",
        "video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
    },
    "parameters": {
        "prompt_extend": false,
        "control_condition": "depth"
    }
}'
Langkah 2: Ambil hasil berdasarkan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh panggilan API sebelumnya. task_id berlaku untuk kueri selama 24 jam.

curl -X GET https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """Buat tugas repainting video dan kembalikan 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, # Untuk repainting video, kami sarankan menonaktifkan penulisan ulang prompt.
                    "control_condition": "depth" # Opsional: posebodyface, posebody, depth, scribble
                }
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"Gagal membuat tugas: {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"Tugas gagal: {data.get('message', 'Kesalahan tidak diketahui')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"Kesalahan polling: {e}. Mencoba lagi dalam 15 detik...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"ID Tugas: {task_id}")
    video_url = poll_result(task_id)
    print(f"\nVideo berhasil dibuat: {video_url}")

Java

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

public class VideoRepainting {
    // Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat 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 belum diatur");
        }
        COMMON_HEADERS.put("Authorization", "Bearer " + API_KEY);
        System.setProperty("http.keepAlive", "true");
        System.setProperty("http.maxConnections", "20");
    }

    // Permintaan HTTP POST umum
    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);
    }

    // Permintaan HTTP GET umum
    private static String httpGet(String path) throws Exception {
        HttpURLConnection conn = createConnection(path, "GET");
        return readResponse(conn);
    }

    // Buat koneksi
    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;
    }

    // Baca respons
    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("Tidak dapat mendapatkan aliran respons. Kode respons: " + 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();
        }
    }

    // Langkah 1: Buat tugas repainting video
    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", "Kesalahan tidak diketahui");
            throw new RuntimeException("Gagal membuat tugas: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // Langkah 2: Polling hasil
    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("Tugas gagal: " + output.optString("message", "Kesalahan tidak diketahui"));
            }
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("Membuat tugas repainting video...");
            String taskId = createTask();
            System.out.println("Tugas berhasil dibuat. ID Tugas: " + taskId);
            System.out.println("Melakukan polling hasil tugas...");
            String videoUrl = pollResult(taskId);
            System.out.println("URL Video: " + videoUrl);
        } catch (Exception e) {
            System.err.println("Terjadi kesalahan: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Local editing

Pengenalan fungsi: Melakukan pengeditan detail halus pada area tertentu dalam video. Mendukung penambahan, penghapusan, atau modifikasi elemen, serta penggantian subjek atau latar belakang. Anda dapat mengunggah gambar mask untuk menentukan area pengeditan, dan model akan secara otomatis melacak target serta menggabungkan konten yang dihasilkan.

Parameter:
  • function: Harus diatur ke video_edit.

  • video_url: Wajib. URL video input asli.

  • mask_image_url: Opsional. Pilih antara parameter ini dan mask_video_url. Kami merekomendasikan menggunakan parameter ini. Anda dapat memasukkan URL gambar mask di mana area putih merepresentasikan bagian yang akan diedit dan area hitam tetap tidak berubah.

  • mask_frame_id: Opsional. Digunakan bersama mask_image_url untuk menentukan frame video mana yang sesuai dengan mask (default adalah frame pertama).

  • mask_type: Opsional. Menentukan perilaku area pengeditan:

    • tracking (default): Area pengeditan secara otomatis mengikuti lintasan gerak objek target.
    • fixed: Area pengeditan tetap pada posisi yang tetap.
  • expand_ratio: Opsional. Hanya berlaku ketika mask_type adalah tracking.

    • Fungsi: Menetapkan rasio perluasan area mask ke luar. Rentang nilainya [0.0, 1.0], dan nilai default adalah 0.05.
    • Deskripsi: Nilai yang lebih kecil membuat mask lebih pas mengikuti target. Nilai yang lebih besar memperluas jangkauan mask.
  • ref_images_url: Opsional. Berikan URL satu gambar referensi untuk mengganti konten di area pengeditan dengan konten dari gambar referensi.

Masukan promptInput VideoInput Mask ImageVideo output

Video tersebut menampilkan kafe Prancis bergaya Paris di mana seekor singa berjas dengan elegan menyeruput kopi. Ia memegang cangkir kopi di satu tangan, menyesap dengan ekspresi santai. Kafenya didekorasi dengan selera tinggi, dengan nuansa lembut dan pencahayaan hangat yang menerangi area di sekitar singa tersebut.

mask

Area putih menunjukkan area pengeditan.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas
curl --location 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_edit",
        "prompt": "The video shows a Parisian-style French cafe where a lion in a suit elegantly sips coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft hues and warm lighting illuminating the lion's area.",
        "mask_image_url": "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png",
        "video_url": "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4",
        "mask_frame_id": 1
    },
    "parameters": {
        "prompt_extend": false,
        "mask_type": "tracking",
        "expand_ratio": 0.05
    }
}'
Langkah 2: Ambil hasil berdasarkan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh panggilan API sebelumnya. task_id berlaku untuk kueri selama 24 jam.

curl -X GET https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

Instal dependensi: pip install requests.

import os
import requests
import time

# Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """Buat tugas pengeditan lokal dan kembalikan 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 drinking coffee. It holds a coffee cup in one hand, sipping with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is.",
                    "mask_image_url": "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png",
                    "video_url": "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4",
                    "mask_frame_id": 1 # Indeks frame video yang sesuai dengan mask
                },
                "parameters": {
                    "prompt_extend": False,
                    "mask_type": "tracking", # Mode pelacakan
                    "expand_ratio": 0.05
                }
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"Gagal membuat tugas: {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"Tugas gagal: {data.get('message', 'Kesalahan tidak diketahui')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"Kesalahan polling: {e}. Mencoba lagi dalam 15 detik...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"ID Tugas: {task_id}")
    video_url = poll_result(task_id)
    print(f"\nVideo berhasil dibuat: {video_url}")

Java

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

public class VideoRegionalEdit {
    // Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat 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 belum diatur");
        }
        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();
        }
    }

    // Langkah 1: Buat tugas pengeditan lokal
    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 drinking coffee. It holds a coffee cup in one hand, sipping with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is.")
                        .put("mask_image_url", "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png")
                        .put("video_url", "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4")
                        .put("mask_frame_id", 1))
                .put("parameters", new JSONObject()
                        .put("prompt_extend", false)
                        .put("mask_type", "tracking")
                        .put("expand_ratio", 0.05));

        String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
        JSONObject jsonResponse = new JSONObject(resp);

        if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
            String errorMessage = jsonResponse.optString("message", "Kesalahan tidak diketahui");
            throw new RuntimeException("Gagal membuat tugas: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // Langkah 2: Polling hasil
    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("Tugas gagal: " + output.optString("message"));
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("Membuat tugas pengeditan lokal...");
            String taskId = createTask();
            System.out.println("Tugas berhasil dibuat. ID Tugas: " + taskId);
            String videoUrl = pollResult(taskId);
            System.out.println("URL Video: " + videoUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Video extension

Pengenalan fungsi: Memprediksi dan menghasilkan konten berkelanjutan berdasarkan gambar atau klip video input. Mendukung perluasan maju dari "frame pertama/klip pertama" atau perluasan mundur dari "frame terakhir/klip terakhir". Durasi total video yang dihasilkan tetap 5 detik.

Parameter:
  • function: Harus diatur ke video_extension.

  • prompt: Wajib. Menggambarkan konten yang diinginkan untuk diperluas.

  • first_clip_url: Opsional. Anda dapat memasukkan URL klip video pertama (≤3 detik). Model akan menghasilkan sisa video berdasarkan klip ini.

  • last_clip_url: Opsional. Anda dapat memasukkan URL klip video terakhir (≤3 detik). Model akan menghasilkan bagian sebelumnya dari video berdasarkan klip ini.

  • first_frame_url: Opsional. Anda dapat memasukkan URL gambar frame pertama. Video akan diperluas maju dari frame ini.

  • last_frame_url: Opsional. Anda dapat memasukkan URL gambar frame terakhir. Video akan diperluas mundur dari frame ini.

    Catatan: Anda harus memberikan minimal satu dari empat parameter berikut sebagai input: first_clip_url, last_clip_url, first_frame_url, atau last_frame_url.

Masukan promptKlip pertama input (1 detik)Video output (diperluas menjadi 5 detik)

Seekor anjing yang memakai kacamata hitam sedang berselancar papan luncur di jalan, kartun 3D.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas
curl --location 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_extension",
        "prompt": "A dog wearing sunglasses skateboarding on the street, 3D cartoon.",
        "first_clip_url": "http://wanx.alicdn.com/material/20250318/video_extension_1.mp4"
    },
    "parameters": {
        "prompt_extend": false
    }
}'
Langkah 2: Ambil hasil berdasarkan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh panggilan API sebelumnya. task_id berlaku untuk kueri selama 24 jam.

curl -X GET https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda.  URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """Buat tugas perluasan video dan kembalikan 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"Gagal membuat tugas: {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"Tugas gagal: {data.get('message', 'Kesalahan tidak diketahui')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"Kesalahan polling: {e}. Mencoba lagi dalam 15 detik...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"ID Tugas: {task_id}")
    video_url = poll_result(task_id)
    print(f"\nVideo berhasil dibuat: {video_url}")

Java

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

public class VideoExtension {
    // Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat 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 belum diatur");
        }
        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();
        }
    }

    // Langkah 1: Buat tugas perluasan video
    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", "Kesalahan tidak diketahui");
            throw new RuntimeException("Gagal membuat tugas: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // Langkah 2: Polling hasil
    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("Tugas gagal: " + output.optString("message"));
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("Membuat tugas perluasan video...");
            String taskId = createTask();
            System.out.println("Tugas berhasil dibuat. ID Tugas: " + taskId);
            String videoUrl = pollResult(taskId);
            System.out.println("URL Video: " + videoUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Video outpainting

Pengenalan fungsi: Memperluas konten video ke arah atas, bawah, kiri, dan kanan berdasarkan prompt dan rasio yang ditentukan, sambil mempertahankan koherensi subjek video dan penggabungan latar belakang yang alami.

Parameter:
  • function: Harus diatur ke video_outpainting.
  • video_url: Wajib. URL video input asli.
  • top_scale: Opsional. Rasio perluasan ke atas. Rentang nilainya [1.0, 2.0]. Nilai default adalah 1.0 (tidak ada perluasan).
  • bottom_scale: Opsional. Rasio perluasan ke bawah. Rentang nilainya [1.0, 2.0]. Nilai default adalah 1.0.
  • left_scale: Opsional. Rasio perluasan ke kiri. Rentang nilainya [1.0, 2.0]. Nilai default adalah 1.0.
  • right_scale: Opsional. Rasio perluasan ke kanan. Rentang nilainya [1.0, 2.0]. Nilai default adalah 1.0.

Contoh: Mengatur left_scale ke 1.5 berarti sisi kiri frame akan diperluas menjadi 1.5 kali lebar aslinya.

Masukan promptVideo MasukanVideo keluaran

Seorang wanita elegan dengan penuh semangat memainkan biola, dengan orkestra simfoni lengkap di belakangnya.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas
curl --location 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_outpainting",
        "prompt": "An elegant woman passionately plays the violin, with a full symphony orchestra behind her.",
        "video_url": "http://wanx.alicdn.com/material/20250318/video_outpainting_1.mp4"
    },
    "parameters": {
        "prompt_extend": false,
        "top_scale": 1.5,
        "bottom_scale": 1.5,
        "left_scale": 1.5,
        "right_scale": 1.5
    }
}'
Langkah 2: Ambil hasil berdasarkan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh panggilan API sebelumnya. task_id berlaku untuk kueri selama 24 jam.

curl -X GET https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/tasks/{task_id} \
--header "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import os
import requests
import time

# Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/get-api-key
API_KEY = os.getenv("DASHSCOPE_API_KEY", "YOUR_API_KEY")

def create_task():
    """Buat tugas outpainting video dan kembalikan 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,    # Rasio perluasan ke atas
                    "bottom_scale": 1.5, # Rasio perluasan ke bawah
                    "left_scale": 1.5,   # Rasio perluasan ke kiri
                    "right_scale": 1.5   # Rasio perluasan ke kanan
                }
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"Gagal membuat tugas: {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"Tugas gagal: {data.get('message', 'Kesalahan tidak diketahui')}")
            time.sleep(15)
        except requests.RequestException as e:
            print(f"Kesalahan polling: {e}. Mencoba lagi dalam 15 detik...")
            time.sleep(15)

if __name__ == "__main__":
    task_id = create_task()
    print(f"ID Tugas: {task_id}")
    video_url = poll_result(task_id)
    print(f"\nVideo berhasil dibuat: {video_url}")

Java

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

public class VideoOutpainting {
    // Berikut adalah URL untuk wilayah Singapura. Ganti {WorkspaceId} dengan ID ruang kerja aktual Anda. URL berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk informasi lebih lanjut, lihat 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 belum diatur");
        }
        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();
        }
    }

    // Langkah 1: Buat tugas outpainting video
    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", "Kesalahan tidak diketahui");
            throw new RuntimeException("Gagal membuat tugas: " + errorMessage);
        }
        return jsonResponse.getJSONObject("output").getString("task_id");
    }

    // Langkah 2: Polling hasil
    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("Tugas gagal: " + output.optString("message"));
            Thread.sleep(15000);
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println("Membuat tugas outpainting video...");
            String taskId = createTask();
            System.out.println("Tugas berhasil dibuat. ID Tugas: " + taskId);
            String videoUrl = pollResult(taskId);
            System.out.println("URL Video: " + videoUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Cara memasukkan gambar dan video

Gambar input

Video input

Video output

  • Jumlah video: 1.

  • Spesifikasi video: Resolusi total tetap 720P, dengan laju frame 30 fps, dalam format MP4 (encoding H.264).

  • Masa berlaku URL video: 24 jam.

  • Dimensi video: Berbeda-beda tergantung fitur yang dipilih.

    • Multi-image reference / Local editing:

      • Resolusi output tetap 720P.
      • Lebar dan tinggi spesifik ditentukan oleh parameter permintaan size.
    • Video repainting / Video extension / Video outpainting:

      • Jika resolusi video input ≤ 720P: Output mempertahankan resolusi asli.
      • Jika resolusi video input > 720P: Output diskalakan turun ke 720P sambil mempertahankan rasio aspek.

Penagihan dan pembatasan laju

  • Untuk informasi lebih lanjut tentang kuota gratis dan tarif penagihan model, lihat Harga model.

  • Untuk informasi lebih lanjut tentang batas laju model, lihat Seri Wanxiang.

  • Deskripsi penagihan:

    • Anda tidak dikenai biaya untuk input. Penagihan didasarkan pada durasi dalam detik video yang berhasil dihasilkan.
    • Panggilan model yang gagal atau kesalahan pemrosesan tidak dikenai biaya apa pun dan tidak mengurangi kuota gratis pengguna baru.
    • Pengeditan video universal juga mendukung rencana penghematan.

Dokumentasi API

Referensi API pengeditan video universal

FAQ

T: Berapa jumlah maksimum gambar yang didukung oleh fitur multi-image reference?

J: Mendukung hingga 3 gambar referensi. Jika Anda memberikan lebih dari 3, hanya 3 gambar pertama yang digunakan sebagai input. Kami merekomendasikan menggunakan latar belakang polos untuk gambar subjek agar subjek lebih menonjol, dan gambar latar belakang yang tidak mengandung subjek apa pun.

T: Kapan sebaiknya saya menonaktifkan penulisan ulang prompt untuk video repainting?

J: Ketika deskripsi teks tidak konsisten dengan konten video input, model mungkin salah memahaminya. Kami merekomendasikan menonaktifkan secara manual penulisan ulang prompt dengan mengatur prompt_extend=false, serta memberikan deskripsi adegan yang jelas dan spesifik dalam prompt untuk meningkatkan konsistensi dan akurasi hasil generasi.

T: Dalam fitur local editing, apa perbedaan antara gambar mask dan video mask?

J: Anda harus memberikan salah satu dari mask_image_url atau mask_video_url. Kami merekomendasikan menggunakan gambar mask. Anda hanya perlu menentukan area pengeditan untuk satu frame, dan sistem akan secara otomatis melacak target.