curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려간다",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "요청 매개변수가 유효하지 않습니다",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "인증에 실패했습니다. API 키를 확인해 주세요",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "잔액이 부족합니다. 충전 후 다시 시도해 주세요",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "요청이 너무 많습니다. 잠시 후 다시 시도해 주세요",
"type": "rate_limit_error"
}
}
Wan3.0
Wan3.0 동영상 생성
- 알리바바 클라우드 완상 3.0 올인원 참조 동영상 모델 (통합 엔드포인트)
- 텍스트→동영상 / 첫 프레임 / 첫·마지막 프레임 / 멀티모달 참조 / 파일·웹 참조
- 해상도 480P / 720P / 1080P, 길이 2–30초, 또는
-1모델 결정 - 이미지, 동영상, 오디오, 문서, 공개 웹 페이지를 참조로 사용 가능
POST
/
v1
/
videos
/
generations
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려간다",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "요청 매개변수가 유효하지 않습니다",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "인증에 실패했습니다. API 키를 확인해 주세요",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "잔액이 부족합니다. 충전 후 다시 시도해 주세요",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "요청이 너무 많습니다. 잠시 후 다시 시도해 주세요",
"type": "rate_limit_error"
}
}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려간다",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "요청 매개변수가 유효하지 않습니다",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "인증에 실패했습니다. API 키를 확인해 주세요",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "잔액이 부족합니다. 충전 후 다시 시도해 주세요",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "요청이 너무 많습니다. 잠시 후 다시 시도해 주세요",
"type": "rate_limit_error"
}
}
인증
string
필수
생성 모드
모델 이름은wan3.0-video 로 고정. 요청 필드에 따라 모드가 결정됩니다:
| 모드 | 대표 입력 |
|---|---|
| 텍스트→동영상 | prompt 만 |
| 첫 프레임→동영상 | image_urls 1장 (프레임 계열) |
| 첫·마지막 프레임 | image_urls 2장, 또는 image_with_roles 로 first_frame / last_frame 지정 |
| 참조→동영상 | 참조 이미지 / 동영상 / 오디오; 프롬프트에서 「图1 / 视频1 / 音频1」 형식 라벨 사용 가능 |
| 파일 / 페이지 참조 | file_url 또는 link_url (prompt 선택) |
요청 매개변수
기본
string
필수
고정값:
wan3.0-videoboolean
기본값:"false"
비디오 작업을 제출하기 전에 콘텐츠 검토를 실행할지 여부를 지정합니다.
true:omni-moderation-latest로 프롬프트와 입력 이미지를 검토false또는 생략: 검토 요청을 보내지 않으며 검토 비용이나 지연이 추가되지 않음(기본값)
string
텍스트 설명. 미디어 필드와 적어도 하나는 필수.
- 최대 20,000자. 초과분은 오류 없이 자동 잘림
- 참조 모드에서는 「图N / 视频N / 音频N」으로 에셋을 지정. 번호는 각 미디어 유형 내 순서를 따름
string
기본값:"1080P"
출력 해상도 (대소문자 구분 없음)
480P720P1080P(기본값, 최고 요금)
resolution 을 생략하면 1080P 로 과금됩니다. 비용이 중요하면 480P 또는 720P 를 명시하세요.string
기본값:"adaptive"
가로세로 비율.
aspect_ratio 도 허용됩니다.adaptive(기본값)16:9/4:3/1:1/3:4/9:16
integer
기본값:"5"
생성 길이(초):
2–30: 출력 길이 지정(기본5)-1: 길이는 모델이 결정
참조 동영상 입력이 있을 때 입력 동영상 총 길이 + 출력 길이는 30초 이하여야 합니다.
duration: -1 이어도 모델이 선택한 길이가 이 제약을 만족해야 합니다.boolean
기본값:"true"
출력에 오디오 트랙 포함 여부. 기본값
true. 오디오 유무와 관계없이 요금 동일.integer
난수 시드, 범위
[0, 2147483647]boolean
기본값:"false"
워터마크 추가 여부. 기본값
falsestring
순수
image_urls 분류 방식:frame— 첫/마지막 프레임 계열reference— 참조 계열
미디어 입력
string[]
이미지 URL 배열. 역할 할당은 상호 배제 규칙을 따릅니다.공개 URL 또는 Base64 (
data:image/png;base64,...).object[]
역할이 명시된 이미지 배열. 각 항목:
url: 이미지 주소role:first_frame/last_frame/reference_image(일반 별칭 허용)
string[]
참조 동영상, 최대 5개. 각 1–15초, 총합 ≤ 15초
string[]
참조 오디오, 최대 5개. 각 1–15초, 총합 ≤ 15초
string
단일 참조 오디오 (
audio_urls 의 단일 값 형태)string
참조 문서 URL, 최대 1개.
link_url 과 함께 사용 불가.형식: docx / doc / xlsx / xls / pptx / ppt / pdf / txt / key / pages / numbers / md 등, ≤100MB, ≤50페이지.string
공개 웹 페이지 URL, 최대 1개. 로그인 불필요 페이지만.
file_url 과 함께 사용 불가.미디어 계열 상호 배제
미디어는 두 계열 중 하나이며 혼합 불가 (제출 전 검증 → 400, 작업 미생성·과금 없음):| 계열 | 구성원 | 의미 |
|---|---|---|
| 프레임 계열 | first_frame, last_frame | 동영상의 엄격한 첫 / 마지막 프레임 |
| 참조 계열 | reference_image, reference_video, reference_audio, file, link | 모델이 내용을 자유롭게 해석 |
순수 image_urls 할당 방식
generation_type이 있으면 → 그것을 사용 (frame/reference)- 없고 요청에 참조 계열 입력이 있으면 (
video_urls/audio_urls/audio_url/file_url/link_url) →reference_image로 처리 - 둘 다 아니면 → 프레임 계열: 1번째
first_frame, 2번째last_frame(wan2.7과 동일)
image_with_roles 를 사용하세요.
미디어 제한 및 형식
| 유형 | 제한 |
|---|---|
| 첫 / 마지막 프레임 | 각 ≤ 1장 |
| 참조 이미지 | ≤ 10장 |
| 참조 동영상 | ≤ 5개, 각 1–15s, 총 ≤15s; mp4/mov; 변 240–4096 px, 비율 ≤8:1, ≤100MB |
| 참조 오디오 | ≤ 5개, 각 1–15s, 총 ≤15s; wav/mp3; ≤15MB |
| 이미지 | JPEG/JPG/PNG (알파 없음) / BMP / WEBP; 변 240–8000 px, 비율 ≤8:1, ≤20MB |
| 문서 | ≤100MB, ≤50페이지 |
| 웹 페이지 | 공개, 로그인 불필요 URL |
요청 예시
텍스트→동영상
{
"model": "wan3.0-video",
"prompt": "고양이가 달빛 아래 지붕을 달려가고, 멀리 도시의 네온이 반짝인다. 시네마틱 화질, 부드러운 카메라 무브.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}
첫 프레임→동영상
{
"model": "wan3.0-video",
"prompt": "화면 속 인물이 랩을 시작하고, 카메라가 천천히 다가간다",
"image_urls": ["https://example.com/first.png"],
"resolution": "720P",
"duration": 5
}
첫·마지막 프레임
{
"model": "wan3.0-video",
"prompt": "미소가 점점 웃음이 되고, 배경 조명이 한색에서 난색으로 변한다",
"image_urls": [
"https://example.com/first.png",
"https://example.com/last.jpg"
],
"duration": 5
}
image_with_roles 사용:
{
"model": "wan3.0-video",
"prompt": "미소가 점점 웃음이 된다",
"image_with_roles": [
{"url": "https://example.com/first.png", "role": "first_frame"},
{"url": "https://example.com/last.jpg", "role": "last_frame"}
],
"duration": 5
}
멀티모달 참조
{
"model": "wan3.0-video",
"prompt": "视频1抱着图1,在图3的椅子上弹奏一支舒缓的乡村民谣,并说道:\"今天的阳光真好。\"",
"generation_type": "reference",
"image_urls": [
"https://example.com/object1.jpg",
"https://example.com/object2.png",
"https://example.com/chair.png"
],
"video_urls": ["https://example.com/role.mp4"],
"resolution": "480P",
"duration": 5
}
video_urls가 있으면 순수image_urls는 참조 이미지로 자동 분류됩니다.generation_type: "reference"를 명시하면 더 명확합니다.
파일 참조→동영상
prompt 는 생략 가능. 문서 내용으로 생성이 구동됩니다:
{
"model": "wan3.0-video",
"file_url": "https://example.com/glass.pptx",
"resolution": "480P",
"duration": 10
}
웹 페이지 참조→동영상
{
"model": "wan3.0-video",
"prompt": "이 글을 짧은 교육용 동영상으로 만들어 주세요",
"link_url": "https://example.com/article/123",
"duration": 15
}
요금
초 × 해상도 (공식 리스트 가격 기준). 오디오 온/오프는 가격에 영향 없음:| 해상도 | 단가 | 5초 | 30초 |
|---|---|---|---|
| 480P | ¥0.30 / 초 | ¥1.50 | ¥9.00 |
| 720P | ¥0.60 / 초 | ¥3.00 | ¥18.00 |
| 1080P | ¥1.20 / 초 | ¥6.00 | ¥36.00 |
- 기본값은 1080P (가장 비쌈). 비용에 민감하면
480P/720P지정 - 과금 초수:
2–30이면 요청duration;-1이면 모델의 실제 출력 초 audio: true/false는 가격에 영향 없음
제한 및 참고
| 항목 | 설명 |
|---|---|
| 길이 | 정수 2–30, 또는 -1(모델이 길이 결정) |
| 동영상 입력 시 | 입력 동영상 총 길이 + 출력 길이 ≤ 30초 |
| 생성 시간 | 보통 1–5분. 긴 클립은 더 소요 |
| 결과 URL | 성공 후 플랫폼 CDN 에 미러링되어 장기 사용 가능 |
| 프롬프트 | ≤20,000자. 초과분 잘림 |
자주 발생하는 오류
모두 동기 400 (작업 미생성·과금 없음):| 경우 | 조치 |
|---|---|
| 프레임 계열과 참조 계열 혼합 | generation_type 으로 한 계열 선택, 또는 image_with_roles 로 역할 지정 |
file_url 과 link_url 동시 전달 | 둘 중 하나 선택 |
잘못된 duration | 2–30 또는 -1 만 |
| 미지원 해상도 (예: 4K) | 480P / 720P / 1080P 만 |
| 참조 이미지 10장 초과 | ≤10장으로 줄이기 |
prompt 와 미디어 모두 비어 있음 | 적어도 하나 제공 |
Response
integer
상태 코드. 성공 시 200
결과 조회동영상 생성은 비동기입니다. 작업 상태 조회 또는
GET /v1/videos/generations/{task_id} 로 폴링하세요.권장 간격 5–10초. 생성은 보통 1–5분 소요. 성공 후 result.videos 의 URL 을 사용하세요.