All Products
Search
Document Center

Alibaba Cloud Model Studio:Pengeditan video umum

Last Updated:Feb 13, 2026

Model pengeditan video terpadu Wan mendukung input multimodal (teks, gambar, dan video) serta menyediakan lima kemampuan inti: multi-image reference, video repainting, local editing, video extension, dan frame expansion.

Ketersediaan

Model yang didukung berbeda-beda tergantung wilayahnya. Sumber daya diisolasi antarwilayah. Saat memanggil API, pastikan model, URL endpoint, dan Kunci API Anda semuanya berasal dari wilayah yang sama. Pemanggilan lintas wilayah akan gagal.

Model yang Didukung:

Internasional

Dalam mode penyebaran Internasional, titik akses dan penyimpanan data berlokasi di wilayah Singapura, serta sumber daya komputasi inferensi model dijadwalkan secara dinamis di seluruh dunia, kecuali Tiongkok Daratan.

Model

Fitur

Modalitas input

Spesifikasi video output

wan2.1-vace-plus

Video tanpa audio

Multi-image reference, video redraw, local editing, video extension, video frame expansion

Teks, gambar, video

Opsi resolusi: 720P

Durasi video: Maksimal 5 detik

Spesifikasi tetap: 30 fps, MP4 (encoding H.264)

Tiongkok Daratan

Dalam mode penyebaran Tiongkok Daratan, titik akses dan penyimpanan data berlokasi di wilayah Beijing, serta sumber daya komputasi inferensi model dibatasi hanya untuk Tiongkok Daratan.

Model

Fitur

Modalitas input

Spesifikasi video output

wanx2.1-vace-plus

Video tanpa audio

Multi-image reference, video redraw, local editing, video extension, video frame expansion

Teks, gambar, video

Opsi resolusi: 720P

Durasi video: Maksimal 5 detik

Spesifikasi tetap: 30 fps, MP4 (encoding H.264)

Catatan

Kode contoh dalam topik ini berlaku untuk wilayah Singapura.

Kemampuan inti

Multi-image reference

Deskripsi: Mendukung hingga 3 gambar referensi, termasuk subjek dan latar belakang (orang, hewan, pakaian, pemandangan). Model menggabungkan gambar-gambar tersebut untuk menghasilkan konten video yang koheren.

Pengaturan parameter:

  • function: Harus diatur sebagai image_reference.

  • ref_images_url: Array berisi URL. Mendukung 1 hingga 3 gambar referensi.

  • obj_or_bg: Mengidentifikasi setiap gambar sebagai subjek (obj) atau latar belakang (bg). Panjang array ini harus sama dengan panjang array ref_images_url.

Input prompt

Gambar referensi input 1 (Subjek referensi)

Gambar referensi input 2 (Latar belakang referensi)

Video output

Dalam video, seorang gadis berjalan keluar dari kedalaman hutan kuno yang berkabut. Langkah-langkahnya ringan, dan kamera menangkap setiap momen anggunnya. Ketika ia berhenti dan melihat sekeliling ke pepohonan yang rindang, senyum kejutan dan sukacita merekah di wajahnya. Adegan ini, yang membeku dalam momen cahaya dan bayangan yang saling bertaut, merekam pertemuannya yang indah dengan alam.

image

image

Sebelum memanggil API, dapatkan Kunci API. Lalu tetapkan Kunci API Anda sebagai variabel lingkungan.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas

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

Langkah 2: Dapatkan hasil menggunakan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh pemanggilan API sebelumnya.

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

# Berikut adalah URL untuk wilayah Singapura. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 trees, a smile of surprise and joy blossoms on her face. This scene, frozen in a moment of intertwined light and shadow, records her wonderful encounter with nature.",
                    "ref_images_url": [
                        "http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png",
                        "http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png"
                    ]
                },
                "parameters": {"prompt_extend": True, "obj_or_bg": ["obj", "bg"], "size": "1280*720"}
            },
            timeout=30
        )
        resp.raise_for_status()
        return resp.json()["output"]["task_id"]
    except requests.RequestException as e:
        raise RuntimeError(f"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 dihasilkan: {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. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 sudah aktif 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 ulang 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 penerima
        conn.setRequestProperty("Accept", "application/json");
        
        return conn;
    }

    // Baca respons (otomatis tangani aliran error)
    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 aslinya
            }
            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 trees, a smile of surprise and joy blossoms on her face. This scene, frozen in a moment of intertwined light and shadow, records her wonderful encounter with nature.")
                        .put("ref_images_url", new JSONArray()
                                .put("http://wanx.alicdn.com/material/20250318/image_reference_2_5_16.png")
                                .put("http://wanx.alicdn.com/material/20250318/image_reference_1_5_16.png")))
                .put("parameters", new JSONObject()
                        .put("prompt_extend", true)
                        .put("obj_or_bg", new JSONArray().put("obj").put("bg"))
                        .put("size", "1280*720"));

        String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
        JSONObject jsonResponse = new JSONObject(resp);
        
        // 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 field '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

Deskripsi: Mengekstraksi pose dan gerakan subjek, komposisi dan kontur gerakan, atau struktur sketsa dari video input. Kemudian menggabungkannya dengan prompt teks untuk menghasilkan video baru dengan fitur dinamis yang sama. Anda juga dapat mengganti subjek dengan gambar referensi.

Pengaturan parameter:

  • function: Harus diatur sebagai video_repainting.

  • video_url: Wajib. URL video input. Harus dalam format MP4, ukuran maksimal 50 MB, dan durasi maksimal 5 detik.

  • control_condition: Wajib. Metode ekstraksi fitur video. Menentukan fitur mana dari video asli yang dipertahankan:

    • 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 gerakan. Mempertahankan struktur adegan.

    • scribble: Mengekstraksi struktur sketsa. Mempertahankan detail tepi sketsa.

  • strength: Opsional. Mengontrol kekuatan ekstraksi fitur. Rentang: 0,0–1,0. Default: 1,0. Nilai lebih tinggi membuat output lebih mirip aslinya; nilai lebih rendah memberikan kebebasan kreatif lebih besar.

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

Input prompt

Video masukan

Video output

Video menampilkan mobil bergaya steampunk berwarna hitam yang dikemudikan 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://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_repainting",
        "prompt": "The video shows a black steampunk-style car driven by a gentleman. The car is decorated with gears and copper pipes. The background features a steam-powered candy factory and retro elements, creating a vintage and playful scene.",
        "video_url": "http://wanx.alicdn.com/material/20250318/video_repainting_1.mp4"
    },
    "parameters": {
        "prompt_extend": false,
        "control_condition": "depth"
    }
}'

Langkah 2: Dapatkan hasil menggunakan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh pemanggilan API sebelumnya.

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

# Berikut adalah URL untuk wilayah Singapura. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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, # Kami menyarankan menonaktifkan penulisan ulang prompt untuk repainting video.
                    "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 dihasilkan: {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. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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

Deskripsi: Melakukan pengeditan detail halus pada area video tertentu. Mendukung penambahan, penghapusan, dan modifikasi elemen, atau mengganti subjek dan latar belakang. Unggah gambar mask untuk menentukan area pengeditan—model secara otomatis melacak target dan memadukan konten yang dihasilkan.

Pengaturan parameter:

  • function: Harus diatur sebagai video_edit.

  • video_url: Wajib. URL video input asli.

  • mask_image_url: Opsional. Tentukan salah satu parameter ini atau mask_video_url. Kami menyarankan menggunakan parameter ini. URL gambar mask. Area putih pada mask akan diedit; area hitam tetap tidak berubah.

  • mask_frame_id: Opsional. Gunakan bersama mask_image_url untuk menentukan frame video mana yang sesuai dengan mask. Default: frame pertama.

  • mask_type: Opsional. Menentukan perilaku area pengeditan:

    • tracking (default): Area pengeditan secara otomatis mengikuti lintasan gerak target.

    • fixed: Area pengeditan tetap pada posisi tetap.

  • expand_ratio: Opsional. Hanya berlaku saat mask_type diatur sebagai tracking.

    • Rasio perluasan area mask ke arah luar. Rentang: 0,0–1,0. Default: 0,05.

    • Nilai lebih rendah lebih pas mengikuti target; nilai lebih tinggi memperluas area mask.

  • ref_images_url: Opsional. URL gambar referensi. Konten di area pengeditan diganti dengan konten gambar referensi.

Prompt input

Video input

Gambar mask input

Video output

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

mask

Area putih menunjukkan area pengeditan.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas

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

Langkah 2: Dapatkan hasil menggunakan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh pemanggilan API sebelumnya.

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

# Berikut adalah URL untuk wilayah Singapura. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 sipping coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is.",
                    "mask_image_url": "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png",
                    "video_url": "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4",
                    "mask_frame_id": 1 # Indeks frame 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 dihasilkan: {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. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 sipping coffee. It holds a coffee cup in one hand, taking a gentle sip with a relaxed expression. The cafe is tastefully decorated, with soft tones and warm lighting illuminating the area where the lion is.")
                        .put("mask_image_url", "http://wanx.alicdn.com/material/20250318/video_edit_1_mask.png")
                        .put("video_url", "http://wanx.alicdn.com/material/20250318/video_edit_2.mp4")
                        .put("mask_frame_id", 1))
                .put("parameters", new JSONObject()
                        .put("prompt_extend", false)
                        .put("mask_type", "tracking")
                        .put("expand_ratio", 0.05));

        String resp = httpPost("/services/aigc/video-generation/video-synthesis", body);
        JSONObject jsonResponse = new JSONObject(resp);
        
        if (jsonResponse.has("code") && jsonResponse.getInt("code") != 200) {
            String errorMessage = jsonResponse.optString("message", "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

Deskripsi: Memprediksi dan menghasilkan konten berkelanjutan berdasarkan gambar input atau klip video. Mendukung perpanjangan video maju dari frame atau klip pertama, atau mundur dari frame atau klip terakhir. Video yang dihasilkan berdurasi 5 detik.

Pengaturan parameter:

  • function: Harus diatur sebagai video_extension.

  • prompt: Wajib. Deskripsi konten yang diinginkan untuk diperpanjang.

  • first_clip_url: Opsional. URL klip video pertama (durasi maksimal 3 detik). Model menghasilkan sisa video berdasarkan klip ini.

  • last_clip_url: Opsional. URL klip video terakhir (durasi maksimal 3 detik). Model menghasilkan konten sebelumnya berdasarkan klip ini.

  • first_frame_url: Opsional. URL gambar frame pertama. Video diperpanjang maju dari frame ini.

  • last_frame_url: Opsional. URL gambar frame terakhir. Generasi dilakukan mundur dari frame ini.

    Tentukan minimal salah satu dari berikut: first_clip_url, last_clip_url, first_frame_url, atau last_frame_url.

Input prompt

Masukkan klip video pertama (1 detik)

Video output (Video yang diperpanjang berdurasi 5 detik)

Seekor anjing yang memakai kacamata hitam sedang berseluncur dengan skateboard di jalan, kartun 3D.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_extension",
        "prompt": "A dog wearing sunglasses is skateboarding on the street, 3D cartoon.",
        "first_clip_url": "http://wanx.alicdn.com/material/20250318/video_extension_1.mp4"
    },
    "parameters": {
        "prompt_extend": false
    }
}'

Langkah 2: Dapatkan hasil menggunakan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh pemanggilan API sebelumnya.

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

# Berikut adalah URL untuk wilayah Singapura. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 perpanjangan 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 dihasilkan: {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. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 perpanjangan 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 perpanjangan 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();
        }
    }
}

Frame expansion

Deskripsi: Memperluas konten frame video secara proporsional ke segala arah (atas, bawah, kiri, kanan) berdasarkan prompt. Mempertahankan kontinuitas subjek video dan memastikan perpaduan alami dengan latar belakang.

Pengaturan parameter:

  • function: Harus diatur sebagai video_outpainting.

  • video_url: Wajib. URL video input asli.

  • top_scale: Opsional. Rasio perluasan ke atas. Rentang: 1,0–2,0. Default: 1,0 (tidak diperluas).

  • bottom_scale: Opsional. Rasio perluasan ke bawah. Rentang: 1,0–2,0. Default: 1,0.

  • left_scale: Opsional. Rasio perluasan ke kiri. Rentang: 1,0–2,0. Default: 1,0.

  • right_scale: Opsional. Rasio perluasan ke kanan. Rentang: 1,0–2,0. Default: 1,0.

Contoh: Mengatur left_scale menjadi 1,5 memperluas sisi kiri frame menjadi 1,5 kali lebar aslinya.

Masukan prompt

Video input

Video output

Seorang wanita elegan sedang bersemangat memainkan biola, dengan orkestra simfoni lengkap di belakangnya.

curl

Langkah 1: Buat tugas untuk mendapatkan ID tugas

curl --location 'https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis' \
--header 'X-DashScope-Async: enable' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
    "model": "wan2.1-vace-plus",
    "input": {
        "function": "video_outpainting",
        "prompt": "An elegant lady is passionately playing the violin, with a full symphony orchestra behind her.",
        "video_url": "http://wanx.alicdn.com/material/20250318/video_outpainting_1.mp4"
    },
    "parameters": {
        "prompt_extend": false,
        "top_scale": 1.5,
        "bottom_scale": 1.5,
        "left_scale": 1.5,
        "right_scale": 1.5
    }
}'

Langkah 2: Dapatkan hasil menggunakan ID tugas

Ganti {task_id} dengan nilai task_id yang dikembalikan oleh pemanggilan API sebelumnya.

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

# Berikut adalah URL untuk wilayah Singapura. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1"
# Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 frame 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 dihasilkan: {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. URL berbeda-beda tergantung wilayahnya. Untuk mendapatkan URL, lihat https://www.alibabacloud.com/help/en/model-studio/wanx-vace-api-reference
    static final String BASE_URL = "https://dashscope-intl.aliyuncs.com/api/v1";
    // Kunci API berbeda-beda tergantung wilayahnya. Untuk mendapatkan Kunci API, 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 frame 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 perluasan frame 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();
        }
    }
}

Gambar dan video input

Gambar input

  • Jumlah gambar: Lihat jumlah yang diperlukan untuk fitur yang dipilih.

  • Metode input:

    • URL publik: Mendukung protokol HTTP dan HTTPS. Contoh: https://xxxx/xxx.png.

Video input

  • Jumlah video: Lihat jumlah yang diperlukan untuk fitur yang dipilih.

  • Metode input:

    • URL publik: Mendukung protokol HTTP dan HTTPS. Contoh: https://xxxx/xxx.mp4.

Video output

  • Jumlah video: Satu.

  • Format: MP4. Lihat spesifikasi video di bawah untuk resolusi dan dimensi.

  • Waktu kedaluwarsa URL: 24 jam.

  • Dimensi: Berbeda-beda tergantung fitur yang dipilih.

    • Multi-image reference / Local editing:

      • Resolusi output tetap pada 720P.

      • Lebar dan tinggi spesifik ditentukan oleh parameter size.

    • Video repainting / Video extension / Frame expansion:

      • Jika resolusi video input 720P atau lebih rendah, resolusi output sesuai dengan input.

      • Jika resolusi video input lebih tinggi dari 720P, output diskalakan turun ke 720P sambil mempertahankan rasio aspek.

Penagihan dan pembatasan laju

  • Untuk kuota gratis dan harga, lihat Harga pemanggilan model.

  • Untuk pembatasan laju, lihat Seri Wan.

  • Rincian penagihan:

    • Input gratis. Output ditagih per detik video yang berhasil dihasilkan.

    • Pemanggilan model yang gagal atau kesalahan pemrosesan tidak dikenai biaya dan tidak mengurangi kuota gratis Anda.

    • Pengeditan video umum juga mendukung rencana penghematan.

Referensi API

Referensi API pengeditan video umum

FAQ

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

J: Mendukung maksimal 3 gambar referensi. Jika Anda memberikan lebih dari 3, hanya 3 gambar pertama yang digunakan. Untuk hasil terbaik, gunakan latar belakang solid pada gambar subjek agar subjek lebih menonjol, dan pastikan gambar latar belakang tidak mengandung objek subjek.

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

J: Jika deskripsi teks tidak konsisten dengan konten video input, model mungkin salah menafsirkan permintaan Anda. Dalam kasus ini, kami menyarankan menonaktifkan secara manual penulisan ulang prompt dengan mengatur prompt_extend=false dan memberikan deskripsi adegan yang jelas dan spesifik dalam prompt. Hal ini meningkatkan konsistensi dan akurasi.

T: Pada fitur pengeditan lokal, apa perbedaan antara gambar mask dan video mask?

J: Tentukan salah satu menggunakan mask_image_url atau mask_video_url. Kami menyarankan menggunakan gambar mask karena Anda hanya perlu menentukan area pengeditan pada satu frame saja, dan sistem secara otomatis melacak target.