Dzięki API MiniMax H3 w PoYo wygenerujesz 5–15-sekundowe wideo 2K z tekstu, z pierwszej i ostatniej klatki albo z materiałów referencyjnych. Bez materiałów referencyjnych szacunkowy koszt 5-sekundowego wideo to 105 kredytów ($0.525).
Ten przewodnik zaczyna się od pierwszego żądania, a potem omawia cennik, tryby danych wejściowych, przykłady w Pythonie i Node.js oraz prompty do różnych scen. Wszystkie endpointy i ceny w tym przewodniku dotyczą PoYo.
Szybki start: wyślij zadanie i pobierz wideo
1. Wyślij zadanie 5-sekundowego wideo
Pobierz klucz API z konsoli PoYo, zastąp YOUR_POYO_API_KEY poniżej i uruchom polecenie w terminalu lub na swoim serwerze. Trzymaj klucz po stronie serwera; nie umieszczaj go w kodzie działającym w przeglądarce ani w publicznych repozytoriach.
W żądaniach do PoYo wartość model dla MiniMax H3 to hailuo-03. Poniższy przykład wysyła płatne zadanie generowania.
export POYO_API_KEY="YOUR_POYO_API_KEY"
curl --fail-with-body --max-time 30 \
--request POST 'https://api.poyo.ai/api/generate/submit' \
--header "Authorization: Bearer ${POYO_API_KEY}" \
--header 'Content-Type: application/json' \
--data '{
"model": "hailuo-03",
"input": {
"prompt": "A golden retriever walks through a sunlit autumn park. One slow tracking shot, natural movement, warm afternoon light.",
"duration": 5,
"resolution": "2K",
"aspect_ratio": "16:9"
}
}'
Po udanym wysłaniu odczytaj ID zadania z data.task_id. Ten przykład pokazuje strukturę odpowiedzi z zastępczym ID zadania:
{
"code": 200,
"message": "success",
"data": {
"task_id": "YOUR_TASK_ID"
}
}
2. Odpytaj o wynik zadania
Ustaw TASK_ID na zwrócone ID zadania i użyj tego samego klucza API:
TASK_ID="YOUR_TASK_ID"
curl --fail-with-body --max-time 30 \
--request GET "https://api.poyo.ai/api/generate/status/${TASK_ID}" \
--header "Authorization: Bearer ${POYO_API_KEY}"
Udane wysłanie oznacza, że zadanie zostało przyjęte; nadal musisz poczekać, aż generowanie wideo się zakończy. Odpowiedź na zapytanie może zawierać cztery wartości data.status:
| Status | Znaczenie | Następny krok |
|---|---|---|
not_started | Czeka na przetworzenie | Zapytaj ponownie później |
running | Generowanie w toku | Zapytaj ponownie później |
finished | Generowanie zakończone | Odczytaj data.files[].file_url |
failed | Generowanie nie powiodło się | Sprawdź data.error_message i przestań odpytywać |
Oto przykład odpowiedzi dla zakończonego zadania. Adres URL i znacznik czasu mają charakter poglądowy:
{
"code": 200,
"data": {
"task_id": "YOUR_TASK_ID",
"status": "finished",
"credits_amount": 105,
"files": [
{
"file_url": "https://example.com/generated/video.mp4",
"file_type": "video"
}
],
"created_time": "2026-09-22T08:30:00",
"progress": 100,
"error_message": null
}
}
Definicje pól i przykłady odpowiedzi dla pozostałych stanów znajdziesz w dokumentacji zapytań o zadania w PoYo. Jeśli zapytanie chwilowo się nie powiedzie albo twój czas oczekiwania minie, zachowaj ID zadania i zapytaj ponownie później; nie wysyłaj automatycznie kolejnego płatnego generowania.
Jak działa cennik MiniMax H3 w PoYo
Poniższe ceny sprawdzono 21 września 2026. Wszystkie kwoty są w USD, przy przeliczniku 1 kredyt = $0.005. Zanim zaczniesz generować hurtowo, potwierdź aktualne ceny na stronie modelu.
| Pozycja rozliczeniowa | Kredyty | USD |
|---|---|---|
| Czas trwania wygenerowanego wideo | 21 kredytów/sekundę | $0.105/sekundę |
| Czas trwania wejściowego wideo referencyjnego | 21 kredytów/sekundę | $0.105/sekundę |
| Pierwsze 5 obrazów referencyjnych na jedno generowanie | 0 | $0 |
| Każdy obraz referencyjny od szóstego wzwyż | 6,4 kredytu | $0.032 |
Szacunkowe kredyty = 21 × (sekundy wyniku + rozliczane sekundy wideo referencyjnego) + 6,4 × liczba obrazów referencyjnych ponad 5. Przy 5 lub mniej obrazach referencyjnych dodatkowa opłata za obrazy wynosi 0. Pomnóż szacunkowe kredyty przez $0.005, aby otrzymać koszt w USD. Dla wideo referencyjnych z ułamkową liczbą sekund rozliczenie opiera się na czasie trwania ustalonym przez serwer.
| Przykład | Szacunkowe kredyty | Szacunkowo USD |
|---|---|---|
| Generowanie 5 sekund bez materiałów referencyjnych | 105 | $0.525 |
| Generowanie 10 sekund bez materiałów referencyjnych | 210 | $1.05 |
| Generowanie 15 sekund bez materiałów referencyjnych | 315 | $1.575 |
| Generowanie 10 sekund + 5 sekund wideo referencyjnego + 7 obrazów referencyjnych | 327,8 | $1.639 |
Ostatni przykład korzysta z wyrażenia 21 × (10 + 5) + 6.4 × (7 − 5). To koszty jednego generowania; jeśli ujęcie wymaga kilku prób, uwzględnij w budżecie każde generowanie.
Wybierz tryb danych wejściowych i materiały referencyjne
Tryb danych wejściowych zależy od pól z mediami, które wyślesz. Przykład z szybkiego startu wyżej to tekst na wideo. Dodaj odpowiednie pola, gdy chcesz określić klatkę początkową i końcową albo użyć materiałów referencyjnych.
| Tryb | Pola wejściowe | Zastosowanie |
|---|---|---|
| Tekst na wideo | prompt, bez adresów URL mediów | Opisz słowami scenę, akcję i ruch kamery |
| Generowanie z pierwszej/ostatniej klatki | image_urls | Pierwszy obraz to klatka początkowa; drugi, opcjonalny obraz to klatka końcowa. Pomiń aspect_ratio; proporcje wyznacza pierwsza klatka |
| Generowanie multimodalne z referencji | reference_image_urls, reference_video_urls, reference_audio_urls | Łącz obrazy, wideo i dźwięk; audio referencyjne wymaga obrazu lub wideo referencyjnego |
Nie łącz image_urls z żadnym polem reference_*_urls. Wszystkie adresy URL mediów muszą być publicznie dostępne i umożliwiać bezpośrednie pobranie.
Limity parametrów i mediów
Poniższe limity pochodzą z dokumentacji API MiniMax H3 w PoYo:
promptjest wymagany i przyjmuje do 2000 znaków.durationto liczba całkowita od 5 do 15 sekund, domyślnie 5;resolutionobsługuje tylko2K.- Tekst na wideo obsługuje
21:9,16:9,4:3,1:1,3:4i9:16, domyślnie16:9. Tryb referencji obsługuje teżadaptivei domyślnie go używa. - Możesz podać do 9 obrazów referencyjnych, 3 wideo referencyjne i 3 klipy audio referencyjne. Każdy klip wideo lub audio musi trwać 2–15 sekund; łączny czas trwania wideo i łączny czas trwania audio muszą się mieścić w 15 sekundach.
Przykład żądania z pierwszą i ostatnią klatką
Użyj poniższego JSON jako treści POST /api/generate/submit. Adresy URL mediów w domenie example.com to zaślepki: przed wysłaniem zastąp je własnymi mediami możliwymi do pobrania. Aby użyć tylko klatki początkowej, usuń drugi adres URL z tablicy.
{
"model": "hailuo-03",
"input": {
"prompt": "The camera slowly moves through the temple doorway, starting at the entrance and ending inside the hall. Dust floats in the sunlight.",
"duration": 6,
"resolution": "2K",
"image_urls": [
"https://example.com/assets/temple-entrance.jpg",
"https://example.com/assets/temple-interior.jpg"
]
}
}
Przykład połączonej referencji obrazu i wideo
Użyj Image 1, aby określić wygląd postaci, a Video 1 dla pożądanego ruchu kamery. Odnoszą się one odpowiednio do pierwszego elementu tablicy obrazów i tablicy wideo. Zastąp adresy URL mediów i przed wysłaniem sprawdź czas trwania wideo referencyjnego.
{
"model": "hailuo-03",
"input": {
"prompt": "Use Image 1 for the character appearance and outfit. The character turns and walks toward the window. Use Video 1 as the camera movement reference.",
"duration": 8,
"resolution": "2K",
"aspect_ratio": "adaptive",
"reference_image_urls": [
"https://example.com/assets/character.png"
],
"reference_video_urls": [
"https://example.com/assets/camera-motion.mp4"
]
}
}
Przykłady integracji w Pythonie i Node.js
Poniższe przykłady dzielą wysyłanie i odpytywanie na dwie funkcje: najpierw pobierz i zapisz ID zadania, potem czekaj na wynik. Jeśli odpytywanie zostanie przerwane, wznów je z oryginalnym ID zadania, bez ponownego generowania. Tylko zapytania o status ponawiają próbę po błędach połączenia, przekroczeniu czasu, HTTP 429 i wybranych błędach 5xx; wysyłanie nie jest ponawiane automatycznie.
Obie implementacje czekają 10 sekund między zapytaniami, wykonują ich maksymalnie 60 i ustawiają limit 30 sekund na pojedyncze żądanie. Łączny czas oczekiwania obejmuje więc także czas trwania żądań. To ustawienia aplikacji na potrzeby przykładów, a nie gwarancja czasu generowania. Dostosuj odstępy i politykę ponawiania do potrzeb swojej aplikacji.
Python: wyślij zadanie i odpytuj o wynik
Zainstaluj zależność poleceniem python -m pip install requests i ustaw zmienną środowiskową POYO_API_KEY, jak opisano wyżej. Ten synchroniczny skrypt w Pythonie odpytuje o asynchroniczne zadanie generowania.
import os
import time
import requests
BASE_URL = "https://api.poyo.ai"
API_KEY = os.environ["POYO_API_KEY"]
if not API_KEY.strip():
raise ValueError("Set POYO_API_KEY")
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
RETRYABLE_HTTP = {429, 500, 502, 503, 504}
def response_data(response):
response.raise_for_status()
body = response.json()
if body.get("code") != 200 or not isinstance(body.get("data"), dict):
raise RuntimeError(f"Unexpected API response: {body}")
return body["data"]
def submit_h3(prompt, duration=5):
response = requests.post(
f"{BASE_URL}/api/generate/submit",
headers=HEADERS,
json={"model": "hailuo-03", "input": {
"prompt": prompt, "duration": duration,
"resolution": "2K", "aspect_ratio": "16:9",
}},
timeout=30,
)
task_id = response_data(response).get("task_id")
if not isinstance(task_id, str) or not task_id:
raise RuntimeError("Submission response is missing a task ID; check records instead of resubmitting automatically")
return task_id
def wait_for_h3(task_id, max_polls=60):
for _ in range(max_polls):
time.sleep(10)
try:
response = requests.get(
f"{BASE_URL}/api/generate/status/{task_id}",
headers=HEADERS, timeout=30,
)
except (requests.Timeout, requests.ConnectionError):
continue
if response.status_code in RETRYABLE_HTTP:
continue
task = response_data(response)
status = task.get("status")
if status == "finished":
for item in task.get("files") or []:
if item.get("file_type") == "video" and item.get("file_url"):
return item["file_url"]
raise RuntimeError(f"Task {task_id} finished, but the response has no video URL")
if status == "failed":
raise RuntimeError(f"Task {task_id} failed: {task.get('error_message')}")
if status not in {"not_started", "running"}:
raise RuntimeError(f"Task {task_id} returned an unknown status: {status}")
raise TimeoutError(f"Query limit reached; keep the task ID and query again later: {task_id}")
if __name__ == "__main__":
task_id = submit_h3("A golden retriever walks through a sunlit autumn park.")
# In your application, save task_id to the database here before polling.
print(f"Task ID: {task_id}", flush=True)
print(wait_for_h3(task_id))
Aby wznowić odpytywanie, wywołaj bezpośrednio wait_for_h3(saved_task_id). Błędy HTTP, takie jak 401 i 403, błędy na poziomie API albo nieoczekiwane odpowiedzi przerywają odpytywanie; usuń ich przyczynę, zanim będziesz kontynuować.
Node.js: użyj wbudowanego fetch
Poniższy kod JavaScript korzysta z wbudowanego fetch w Node.js 20 lub nowszym, więc nie potrzeba zależności z klientem HTTP. Zapisz go jako plik .mjs i uruchom na serwerze.
const BASE_URL = 'https://api.poyo.ai';
const apiKey = process.env.POYO_API_KEY;
if (!apiKey?.trim()) throw new Error('Set POYO_API_KEY');
const headers = {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
};
const retryableHttp = new Set([429, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function responseData(response) {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const body = await response.json();
if (body.code !== 200 || !body.data || typeof body.data !== 'object') {
throw new Error(`Unexpected API response: ${JSON.stringify(body)}`);
}
return body.data;
}
export async function submitH3(prompt, duration = 5) {
const response = await fetch(`${BASE_URL}/api/generate/submit`, {
method: 'POST', headers,
body: JSON.stringify({
model: 'hailuo-03',
input: { prompt, duration, resolution: '2K', aspect_ratio: '16:9' },
}),
signal: AbortSignal.timeout(30_000),
});
const data = await responseData(response);
if (typeof data.task_id !== 'string' || !data.task_id) {
throw new Error('Submission response is missing a task ID; check records instead of resubmitting automatically');
}
return data.task_id;
}
export async function waitForH3(taskId, maxPolls = 60) {
for (let attempt = 0; attempt < maxPolls; attempt++) {
await sleep(10_000);
let response;
try {
response = await fetch(
`${BASE_URL}/api/generate/status/${encodeURIComponent(taskId)}`,
{ headers, signal: AbortSignal.timeout(30_000) },
);
} catch (error) {
if (error instanceof Error &&
(error.name === 'TimeoutError' || error.name === 'TypeError')) {
continue;
}
throw error;
}
if (retryableHttp.has(response.status)) {
await response.body?.cancel();
continue;
}
const task = await responseData(response);
if (task.status === 'finished') {
const video = task.files?.find((file) => file.file_type === 'video' && file.file_url);
if (!video) throw new Error(`Task ${taskId} finished, but the response has no video URL`);
return video.file_url;
}
if (task.status === 'failed') {
throw new Error(`Task ${taskId} failed: ${task.error_message || 'No error details provided'}`);
}
if (!['not_started', 'running'].includes(task.status)) {
throw new Error(`Task ${taskId} returned an unknown status: ${task.status}`);
}
}
throw new Error(`Query limit reached; keep the task ID and query again later: ${taskId}`);
}
const taskId = await submitH3('A golden retriever walks through a sunlit autumn park.');
// In your application, save taskId to the database here before polling.
console.log(`Task ID: ${taskId}`);
console.log(await waitForH3(taskId));
Aby wznowić odpytywanie, zastąp wywołania wysyłania i odpytywania na końcu pliku wywołaniem waitForH3(savedTaskId). Ten przykład odpytywania nadaje się do skryptów lub zadań w tle. W aplikacji webowej zwróć ID zadania do frontendu i śledź generowanie w tle, zamiast trzymać żądanie strony w oczekiwaniu.
Odbieraj wyniki przez webhook
W żądaniu wysyłania możesz też przekazać callback_url na najwyższym poziomie, obok model i input, na przykład https://your-domain.com/webhooks/poyo. PoYo wyśle wynik pod ten adres, gdy zadanie zakończy się powodzeniem lub niepowodzeniem.
Odbiorca powinien dopasować ID zadania do lokalnych zapisów i obsługiwać zduplikowane powiadomienia według ID zadania, aby nie powtarzać operacji w dalszych krokach. Czasochłonne czynności, takie jak pobieranie lub transkodowanie wideo, mogą działać w zadaniach w tle. Podczas integrowania callbacków nadal możesz weryfikować wyniki zapytaniami o status.
Prompty i przykłady scen
Najpierw opisz bohatera i akcję, potem dodaj ruch kamery, miejsce, oświetlenie i dźwięk. Przy materiałach referencyjnych określ rolę Image 1, Video 1 lub Audio 1, aby jedna referencja nie niosła sprzecznych wymagań.
Cztery angielskie przykłady poniżej ilustrują pisanie promptów; nie zawierają przetestowanych wyników generowania. Angielskie sformułowania ułatwiają ponowne użycie przykładów, ale nie oznaczają, że angielski musi działać lepiej niż chiński. Instrukcje dotyczące czasu i zachowania wyglądu opisują zamierzone wyniki; sprawdź rzeczywisty rezultat.
Reklama produktu: 8 sekund, tryb obrazu referencyjnego
Umieść obraz produktu na pierwszym miejscu w input.reference_image_urls, ustaw duration: 8 i aspect_ratio: "16:9", a poniższy tekst wstaw jako prompt. Zachowaj strukturę żądania w trybie referencji opisaną wyżej; usuń reference_video_urls, jeśli wideo referencyjne nie jest ci potrzebne.
Use Image 1 as the product reference. A clear glass perfume bottle rests on
wet black stone after rain. Preserve the bottle shape, cap, and label placement.
One continuous 8-second shot: begin close to the water droplets, then slowly
pull back to reveal the bottle in warm rim light. Realistic glass reflections,
no added text. Soft rain ambience.
Zacznij od prostego ujęcia, aby sprawdzić, czy butelka i etykieta pozostają spójne, a dopiero potem wypróbuj bardziej złożony ruch kamery po orbicie.
Dialog postaci: 8 sekund, tryb obrazu referencyjnego
Umieść obraz postaci na pierwszym miejscu w input.reference_image_urls i ustaw duration: 8 oraz aspect_ratio: "16:9". Krótka kwestia dialogowa ułatwia sprawdzenie synchronizacji ust, tempa mowy i wyglądu postaci.
Use Image 1 as the character reference. An 8-second medium close-up of a pastry
chef in a quiet kitchen at sunrise. She looks into the camera and says:
"Every detail matters in baking." Natural breathing, a subtle smile,
soft window light. Preserve her face, hairstyle, and apron. A steady camera,
clear speech, quiet room tone.
Pionowa reklama gry: 10 sekund, tekst na wideo
Ustaw duration: 10 i aspect_ratio: "9:16". Przedziały czasu wyrażają zamierzoną kolejność działań; jeśli scena wydaje się zatłoczona, zacznij od zmniejszenia liczby akcji i postaci.
A 10-second vertical fantasy game trailer.
0-3s: An armored knight walks through a ruined stone gate.
3-6s: One creature charges; the knight blocks once with a shield.
6-9s: The camera rises to reveal the fortress walls.
9-10s: Hold the final composition.
Readable action, consistent armor, wind and impact sounds, no UI or captions.
Ciągłe ujęcie z jazdą kamery: 10 sekund, tekst na wideo
Ustaw duration: 10 i aspect_ratio: "16:9". Zbuduj ujęcie wokół jednego bohatera i jednej trasy, a potem sprawdź, czy nie ma cięć, zmian bohatera ani nieciągłego ruchu.
One unbroken 10-second tracking shot follows a cyclist through a night market.
Begin behind the rear wheel, rise to shoulder height, then move alongside
without cutting. Wet pavement reflections, a clear path between stalls,
consistent bicycle geometry, no speed ramps or scene transitions.
Natural street ambience and bicycle tires rolling on wet pavement.
FAQ i rozwiązywanie problemów z integracją
Czy mogę bezpośrednio użyć formatu żądań własnego API MiniMax?
Te przykłady korzystają z POST /api/generate/submit i GET /api/generate/status/{task_id} w PoYo. Endpointy, identyfikatory modeli i struktury pól mogą się różnić między platformami; kieruj się dokumentacją platformy, z której korzystasz.
Czy należy ponownie wysłać zadanie, które zostaje w stanie not_started?
not_started oznacza, że zadanie czeka na przetworzenie; samo w sobie nie jest niepowodzeniem. Zachowaj ID zadania i dalej odpytuj. Jeśli limit oczekiwania w twojej aplikacji minie, zapisz zadanie i sprawdź je później. W razie potrzeby skontaktuj się ze wsparciem, podając ID zadania.
Co zrobić, jeśli wysyłanie przekroczy czas, zanim dostanę ID zadania?
Przekroczenie czasu żądania nie dowodzi, że serwer nie przyjął zadania. Najpierw sprawdź zapisy zadań; w razie potrzeby skontaktuj się ze wsparciem, podając szczegóły, takie jak czas wysłania. Do użycia endpointu zapytań o status potrzebujesz ID zadania. Nie traktuj ponownego wysłania jako remedium na nieudane zapytanie.
Czy mogę łączyć obrazy, wideo i audio jako referencje?
Tak, łącz je w trybie referencji w granicach liczby i czasu trwania podanych wyżej. Audio referencyjne wymaga obrazu lub wideo referencyjnego. Tych pól nie można łączyć z image_urls w trybie pierwszej/ostatniej klatki.
Ile kosztuje 10-sekundowe wideo?
Przy podanych tu cenach, bez materiałów referencyjnych, koszt to 10 × 21 = 210 kredytów, czyli $1.05. Wideo referencyjne i obrazy referencyjne ponad pierwsze 5 zwiększają koszt.
Zanim zintegrujesz to z aplikacją, upewnij się, że adresy URL mediów pozwalają na bezpośrednie pobieranie, zapisuj ID zadań i ustaw odpowiednie limity generowania i współbieżności dla każdego użytkownika. Przed opublikowaniem wygenerowanego wideo sprawdź, czy wygląd postaci, kształt produktu, tekst, ruch i dźwięk nadają się do zamierzonego użycia.
Wypróbuj generowanie na stronie modelu MiniMax H3 albo wejdź na stronę kluczy API, by zacząć integrację. Więcej o modelach przeczytasz w recenzji MiniMax H3 i w porównaniu MiniMax H3 z Seedance 2.5.