Wan 3.0 w 1080p, 2K lub 4K, do 30 sekund
- Do 4K
- Klipy 2–30 s
- Z dźwiękiem
- Pierwsza i ostatnia klatka
- Do 10 obrazów referencyjnych
- Proporcje obrazu: 5
- Utwórz wideo
- Obraz w wideo
- Wideo z referencji
- Wydłuż wideo
Wywołujesz go nazwą modelu alibaba/wan-3.0-pro/reference-to-video w POST /jobs/createTask, od 108 kredytów za klip 5-sekundowy (1,08 USD). Nowe konta dostają 30 darmowych kredytów, więc możesz najpierw przetestować go w Playgroundzie.
alibaba/wan-3.0-pro/reference-to-videoPOST https://api.popnow.ai/api/v1/jobs/createTask# 1. Create the task. Keep the Idempotency-Key if you retry after a network error.
export IDEMPOTENCY_KEY="$(uuidgen)"
curl -X POST https://api.popnow.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{
"model": "alibaba/wan-3.0-pro/reference-to-video",
"input": {
"reference_image_urls": [
"https://media.popnow.ai/influencer/examples/ava.webp"
],
"resolution": "1080p",
"aspect_ratio": "adaptive",
"duration_seconds": 5
}
}'
# 2. Copy data.taskId from the response, then poll until state is succeeded, failed, canceled or expired.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $POPNOW_API_KEY"// Node 18+ (or any runtime with fetch). Keep the API key on your server.
const BASE = "https://api.popnow.ai/api/v1";
const headers = { Authorization: `Bearer ${process.env.POPNOW_API_KEY}` };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function call(path, init = {}) {
const res = await fetch(BASE + path, { ...init, headers: { ...headers, ...init.headers } });
const body = await res.json();
if (body.code !== 200) throw new Error(`${body.code} ${body.msg}`);
return body.data;
}
const { taskId } = await call("/jobs/createTask", {
method: "POST",
headers: { "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({
"model": "alibaba/wan-3.0-pro/reference-to-video",
"input": {
"reference_image_urls": [
"https://media.popnow.ai/influencer/examples/ava.webp"
],
"resolution": "1080p",
"aspect_ratio": "adaptive",
"duration_seconds": 5
}
}),
});
// Poll with backoff. A finished task may still be copying files: wait while an asset is pending.
let task;
for (let delay = 2000; ; delay = Math.min(delay * 1.5, 15000)) {
await sleep(delay);
task = await call(`/jobs/recordInfo?taskId=${taskId}`);
const copying = (task.output?.assets ?? []).some((a) => a.pending && !a.unavailable);
if (["succeeded", "failed", "canceled", "expired"].includes(task.state) && !copying) break;
}
if (task.state !== "succeeded") throw new Error(`${task.state}: ${task.errorMessage ?? "no detail"}`);
// Each asset has a signed url (no API key needed) that expires at expiresAt: save the file.
for (const asset of task.output.assets) console.log(asset.url);import os, time, uuid, requests
BASE = "https://api.popnow.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['POPNOW_API_KEY']}"}
def call(method, path, **kwargs):
body = requests.request(method, BASE + path, headers={**HEADERS, **kwargs.pop("headers", {})}, timeout=30, **kwargs).json()
if body["code"] != 200:
raise RuntimeError(f'{body["code"]} {body["msg"]}')
return body["data"]
task_id = call(
"POST",
"/jobs/createTask",
headers={"Idempotency-Key": str(uuid.uuid4())}, # reuse it if you retry
json={
"model": "alibaba/wan-3.0-pro/reference-to-video",
"input": {
"reference_image_urls": [
"https://media.popnow.ai/influencer/examples/ava.webp"
],
"resolution": "1080p",
"aspect_ratio": "adaptive",
"duration_seconds": 5
}
},
)["taskId"]
# Poll with backoff. A finished task may still be copying files: wait while an asset is pending.
delay = 2.0
while True:
time.sleep(delay)
task = call("GET", "/jobs/recordInfo", params={"taskId": task_id})
assets = (task.get("output") or {}).get("assets") or []
copying = any(a.get("pending") and not a.get("unavailable") for a in assets)
if task["state"] in ("succeeded", "failed", "canceled", "expired") and not copying:
break
delay = min(delay * 1.5, 15.0)
if task["state"] != "succeeded":
raise RuntimeError(f'{task["state"]}: {task.get("errorMessage", "no detail")}')
# Each asset has a signed url (no API key needed) that expires at expiresAt: save the file.
for asset in assets:
print(asset["url"])input jest zbudowany ze schematu poniżej, więc przechodzi walidację bez zmian. Zamień prompt i linki na własne.
Cena
| Opcja | Kredyty za sekundę | ≈ USD |
|---|---|---|
resolution 1080p | 21,6 | 0,22 USD |
resolution 2K | 24 | 0,24 USD |
resolution 4K | 27,6 | 0,28 USD |
1 kredyt = 0,01 USD · Wszystkie opcje i ceny: GET /models/alibaba/wan-3.0-pro/reference-to-video
Limity
- Długość klipu
- 2–30 s
- Rozdzielczości
- 1080p · 2K · 4K
- Proporcje obrazu
- 16:9 · 4:3 · 1:1 · 3:4 · 9:16 · adaptive
- Audio referencyjne
- 5
- Obrazy referencyjne
- 10
- Wideo referencyjne
- 5
- Długość promptu (znaki)
- 20,000
Parametry
Te pola pochodzą z tego samego schematu, którym sprawdzamy każde żądanie. Pola spoza listy są odrzucane.
Niektóre pola zależą od siebie (na przykład potrzebna jest co najmniej jedna referencja). Dokładne reguły są w surowym schemacie na dole.
promptstringOpcjonalneDescribe the subject, motion and camera.
reference_image_urlsarray<string>Czasem wymaganeObrazy osób, ubrań lub miejsc, które wynik ma zachować.
reference_video_urlsarray<string>Czasem wymaganeZmienia cenęKlipy, których ruch, kamerę lub styl ma powtórzyć wynik.
reference_audio_urlsarray<string>Czasem wymaganeDźwięk do dopasowania: głos, muzyka lub rytm.
reference_file_urlstringCzasem wymaganeOne reference document (PDF, DOCX, TXT, MD and similar) that the model reads for characters, wardrobe, setting and action.
reference_link_urlstringCzasem wymaganeOne public web page the model reads for reference. It must open without a login.
resolutionstringOpcjonalneZmienia cenęRozmiar wyniku. Większy jest ostrzejszy i droższy.
aspect_ratiostringOpcjonalneKształt kadru: szeroki, kwadratowy albo pionowy.
duration_secondsintegerOpcjonalneZmienia cenęDługość klipu. Płacisz za każdą sekundę.
generate_audiobooleanOpcjonalneDodaje dźwięk pasujący do obrazu: głosy, tło i efekty.
enable_prompt_expansionbooleanOpcjonalneModel dopisuje szczegóły do krótkiego promptu.
seedintegerOpcjonalneTa sama liczba daje powtarzalny wynik.
Surowy JSON Schema
{
"additionalProperties": false,
"anyOf": [
{
"required": [
"reference_image_urls"
]
},
{
"required": [
"reference_video_urls"
]
},
{
"required": [
"reference_audio_urls"
]
},
{
"required": [
"reference_file_url"
]
},
{
"required": [
"reference_link_url"
]
}
],
"properties": {
"aspect_ratio": {
"default": "adaptive",
"description": "Output aspect ratio; adaptive follows the input media and the intent.",
"enum": [
"16:9",
"4:3",
"1:1",
"3:4",
"9:16",
"adaptive"
],
"type": "string"
},
"duration_seconds": {
"default": 5,
"description": "Output duration in seconds. Pass -1 for smart duration: the model picks the length from the prompt and any input media instead of a fixed number. With reference videos, their total length plus the output length must not exceed 30 seconds, and the reference video seconds are billed together with the output seconds.",
"enum": [
-1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30
],
"type": "integer"
},
"enable_prompt_expansion": {
"default": true,
"description": "Expand the prompt before generation.",
"type": "boolean"
},
"generate_audio": {
"default": true,
"description": "Include an audio track in the output.",
"type": "boolean"
},
"prompt": {
"description": "Describe the subject, motion and camera.",
"maxLength": 20000,
"minLength": 1,
"type": "string"
},
"reference_audio_urls": {
"description": "Reference audio, up to 5 clips of 1 to 15 seconds each and 15 seconds in total.",
"items": {
"contentMediaType": [
"audio/mpeg",
"audio/wav"
],
"format": "uri",
"type": "string"
},
"maxItems": 5,
"minItems": 1,
"type": "array"
},
"reference_file_url": {
"contentMediaType": [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.apple.keynote",
"application/vnd.apple.pages",
"application/vnd.apple.numbers",
"text/plain",
"text/markdown"
],
"description": "One reference document (PDF, DOCX, TXT, MD and similar) that the model reads for characters, wardrobe, setting and action.",
"format": "uri",
"type": "string"
},
"reference_image_urls": {
"description": "Ordered reference images used to guide the scene.",
"items": {
"contentMediaType": [
"image/jpeg",
"image/png",
"image/webp",
"image/gif"
],
"format": "uri",
"type": "string"
},
"maxItems": 10,
"minItems": 1,
"type": "array"
},
"reference_link_url": {
"description": "One public web page the model reads for reference. It must open without a login.",
"format": "uri",
"type": "string"
},
"reference_video_urls": {
"description": "Reference videos, up to 5 clips of 1 to 15 seconds each and 15 seconds in total.",
"items": {
"contentMediaType": [
"video/mp4",
"video/webm",
"video/quicktime"
],
"format": "uri",
"type": "string"
},
"maxItems": 5,
"minItems": 1,
"type": "array"
},
"resolution": {
"default": "1080p",
"description": "Output resolution tier. A native Wan 3.0 render tops out at 1080p, so the 2k and 4k tiers are delivered by enlarging that render instead of rendering natively at those sizes.",
"enum": [
"1080p",
"2k",
"4k"
],
"type": "string"
},
"seed": {
"description": "Random seed. Omit for a generated seed.",
"maximum": 2147483647,
"minimum": 0,
"type": "integer"
}
},
"type": "object"
}Prawdziwy wynik z Wan 3.0 Pro
The first image is the character — keep her face, hair and the black gown. The second image is the room. She walks from the doorway to the window and stops, looking out. Slow lateral track, one practical lamp, night ambience.
{
"model": "alibaba/wan-3.0-pro/reference-to-video",
"input": {
"reference_image_urls": [
"https://media.popnow.ai/influencer/examples/ava.webp"
],
"resolution": "1080p",
"aspect_ratio": "16:9",
"duration_seconds": 8,
"prompt": "The first image is the character — keep her face, hair and the black gown. The second image is the room. She walks from the doorway to the window and stops, looking out. Slow lateral track, one practical lamp, night ambience.",
"seed": 640117
}
}Ten wynik powstał z przesłanego pliku: wstaw własny link w miejsce przykładowego.
Odpowiedzi, odpytywanie i callbacki
Wszystkie modele działają tak samo: utwórz zadanie, a potem odpytuj je albo poczekaj na callback.
Najpierw cena
curl -X POST https://api.popnow.ai/api/v1/jobs/quote \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "alibaba/wan-3.0-pro/reference-to-video",
"input": {
"reference_image_urls": [
"https://media.popnow.ai/influencer/examples/ava.webp"
],
"resolution": "1080p",
"aspect_ratio": "adaptive",
"duration_seconds": 5
}
}'To samo ciało co createTask. Zwraca przewidywaną i maksymalną możliwą opłatę, niczego nie uruchamiając.
Przyjęte
HTTP/1.1 202 Accepted
{
"code": 200,
"msg": "success",
"data": {
"taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
"state": "queued"
},
"request_id": "req_example_create"
}HTTP 202 oznacza, że zadanie przyjęto, a kredyty są zarezerwowane, jeszcze nie pobrane. Ostateczna opłata nigdy nie przekroczy rezerwacji.
Sprawdź status
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $POPNOW_API_KEY"Odpytuj co kilka sekund, stopniowo wydłużając odstęp, i przestań, gdy state ma wartość succeeded, failed, canceled lub expired.
Gotowe zadanie
{
"code": 200,
"msg": "success",
"data": {
"taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
"model": "alibaba/wan-3.0-pro/reference-to-video",
"state": "succeeded",
"output": {
"assets": [
{
"url": "https://cdn.popnow.ai/tasks/task_01k3m8x9q2z4v7n5p6r8s0t1w3/output.mp4?signature=FROM_RESPONSE",
"expiresAt": "2026-10-17T12:20:00Z",
"mime": "video/mp4",
"width": 1280,
"height": 720,
"durationSeconds": 5
}
]
},
"settled": true
},
"request_id": "req_example_record"
}Pobierz plik z url przed expiresAt. Potrzebujesz później nowego linku? Poproś o niego przez POST /common/download-url.
Weryfikacja callbacku
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
import express from "express";
const app = express();
// express.raw keeps the exact bytes that were signed; express.json would not match.
app.post("/hooks/popnow", express.raw({ type: "application/json" }), (req, res) => {
const timestamp = req.header("X-Webhook-Timestamp");
const signature = req.header("X-Webhook-Signature") ?? "";
const body = JSON.parse(req.body.toString("utf8"));
const taskId = body.data?.taskId ?? body.task_id;
const digest = createHash("sha256").update(req.body).digest("hex");
const expected = createHmac("sha256", process.env.POPNOW_WEBHOOK_SECRET)
.update(`${taskId}.${timestamp}.${digest}`)
.digest("base64");
const ok = expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
// Check the signature first, then reject anything older than five minutes.
if (!ok || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return res.status(401).end();
res.status(200).end(); // answer fast, then fetch the task and store its files
});Gdy ustawisz callBackUrl, wyślemy ci gotowe zadanie. Zanim mu zaufasz, sprawdź podpis na surowym ciele żądania.
Wysyłanie pliku lokalnego
curl -X POST https://api.popnow.ai/api/v1/common/upload-url \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contentType": "image/png", "bytes": 482113}'
# PUT the file bytes to data.uploadUrl with every header in data.headers, then commit it:
curl -X POST https://api.popnow.ai/api/v1/files/$FILE_ID/commit \
-H "Authorization: Bearer $POPNOW_API_KEY"
# The commit returns a popnow://f/... reference. Put it in any image, video or
# audio field of the task input instead of a public https URL.Publiczne linki https działają bez zmian. Pliki lokalne przechodzą najpierw przez upload-url i commit.