All Products
Search
Document Center

Alibaba Cloud Model Studio:Pengeditan video 2.1

Last Updated:Jun 13, 2026

Model pengeditan video universal Wanxiang mendukung input multimodal (teks, gambar, dan video) serta menyediakan lima kemampuan inti: referensi multi-gambar, repainting video, pengeditan lokal, ekstensi video, dan outpainting video.

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.

Catatan

Kode contoh dalam topik ini berlaku untuk wilayah Singapura.

Kemampuan inti

Referensi multi-gambar

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

Parameter:

  • function: Harus diatur ke image_reference.

  • ref_images_url: Array berisi URL. Anda dapat memasukkan 1 hingga 3 gambar referensi.

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

Prompt input

Gambar 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. Langkah-langkahnya ringan, dan kamera menangkap setiap momen anggunnya. Saat ia berhenti dan melihat sekeliling ke hutan yang rimbun, senyum terkejut dan gembira muncul di wajahnya. Momen ini, yang tertangkap dalam permainan cahaya dan bayangan, merekam pertemuannya yang indah dengan alam.

image

image

Sebelum melakukan panggilan, Anda harus terlebih dahulu mendapatkan Kunci API, lalu mengonfigurasi Kunci API sebagai variabel lingkungan (akan diterbitkan dan digabung ke Konfigurasi Kunci API).

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"Pengecualian polling: {e}. Mencoba ulang 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 (diaktifkan secara default 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 untuk 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 untuk 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 tumpukan lengkap untuk debugging
        }
    }

}

Repainting video

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, tidak termasuk 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 prompt

Input video

Video output

Video tersebut menampilkan mobil bergaya steampunk hitam yang dikendarai seorang pria, dihiasi roda gigi dan pipa tembaga. Latar belakangnya adalah pabrik permen bertenaga 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 menyarankan 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"Pengecualian polling: {e}. Mencoba ulang 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 untuk 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 untuk hasil tugas...");
            String videoUrl = pollResult(taskId);
            System.out.println("URL Video: " + videoUrl);
        } catch (Exception e) {
            System.err.println("Terjadi kesalahan: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Pengeditan lokal

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 menyarankan 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 tetap.

  • expand_ratio: Opsional. Hanya berlaku saat 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 prompt

Video input

Input Mask Image

Video 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"Pengecualian polling: {e}. Mencoba ulang 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 untuk 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();
        }
    }
}

Ekstensi video

Pengenalan fungsi: Memprediksi dan menghasilkan konten berkelanjutan berdasarkan gambar input atau klip video. Mendukung ekstensi maju dari "frame pertama/klip pertama" atau ekstensi 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 ekstensi yang diinginkan.

  • 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 diekstensi maju dari frame ini.

  • last_frame_url: Opsional. Anda dapat memasukkan URL gambar frame terakhir. Video akan diekstensi 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.

Input prompt

Klip pertama input (1 detik)

Video output (diekstensi menjadi 5 detik)

Seekor anjing yang memakai kacamata hitam sedang bermain skateboard 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 ekstensi 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"Pengecualian polling: {e}. Mencoba ulang 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 ekstensi 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 untuk 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 ekstensi 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();
        }
    }
}

Outpainting video

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.

Prompt input

Video input

Video output

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"Pengecualian polling: {e}. Mencoba ulang 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 untuk 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

  • Jumlah gambar: Anda dapat memberikan jumlah gambar yang sesuai dengan fitur yang dipilih.

  • Metode input:

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

Video masukan

  • Jumlah video: Anda dapat memberikan jumlah video yang sesuai dengan fitur yang dipilih.

  • Metode input:

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

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.

    • Referensi multi-gambar / Pengeditan lokal:

      • Resolusi output tetap 720P.

      • Lebar dan tinggi spesifik ditentukan oleh parameter permintaan size.

    • Repainting video / Ekstensi video / Outpainting video:

      • 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:

    • Input tidak dikenai biaya. Penagihan didasarkan pada durasi dalam detik video yang berhasil dihasilkan.

    • Panggilan model yang gagal atau kesalahan pemrosesan tidak dikenai biaya 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 referensi multi-gambar?

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

T: Kapan saya harus menonaktifkan penulisan ulang prompt untuk pelukisan ulang video?

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

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

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