PoYo の MiniMax H3 API では、テキスト、開始・終了フレーム、参照素材から 5–15 秒の 2K 動画を生成できます。参照素材を使わない場合、5 秒の動画の推定料金は 105 クレジット($0.525)です。
まず最初のリクエストを実行し、その後で料金、入力モード、Python と Node.js の実装例、シーン別のプロンプトを説明します。本ガイドのエンドポイントと料金は、すべて PoYo に適用されるものです。
クイックスタート:タスクを送信して動画を取得する
1. 5 秒の動画生成タスクを送信する
PoYo コンソールで API キーを取得し、下記の YOUR_POYO_API_KEY を置き換えて、ターミナルまたはサーバーで実行します。キーはサーバー側で管理し、ブラウザーのコードや公開リポジトリには含めないでください。
PoYo のリクエストでは、MiniMax H3 の model 値に hailuo-03 を指定します。次の例を実行すると、有料の生成タスクが送信されます。
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"
}
}'
送信に成功したら、data.task_id からタスク ID を取得します。次はレスポンス構造の例で、タスク ID はプレースホルダーです。
{
"code": 200,
"message": "success",
"data": {
"task_id": "YOUR_TASK_ID"
}
}
2. タスクの結果を確認する
返されたタスク ID を TASK_ID に設定し、同じ 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}"
送信の成功はタスクが受け付けられたことを意味し、動画の生成完了は別途待つ必要があります。ステータス取得レスポンスの data.status には、次の 4 つの値があります。
| ステータス | 意味 | 次の操作 |
|---|---|---|
not_started | 処理待ち | 時間を置いて再度確認 |
running | 生成中 | 時間を置いて再度確認 |
finished | 生成完了 | data.files[].file_url を取得 |
failed | 生成失敗 | data.error_message を確認し、ポーリングを停止 |
生成完了時のレスポンス例です。URL と時刻は説明用の値です。
{
"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
}
}
フィールドの定義と他のステータスの例は、PoYo のタスク照会ドキュメントを参照してください。一時的な照会エラーや待機時間の超過が発生した場合は、タスク ID を保持して後から再確認します。それを理由に有料の生成タスクを自動で再送信しないでください。
PoYo での MiniMax H3 の料金
以下の料金は 2026 年 9 月 21 日に確認したものです。金額はすべて米ドルで、1 クレジット = $0.005 として換算しています。大量に生成する前に、モデルページで最新の料金を確認してください。
| 課金対象 | クレジット | 米ドル |
|---|---|---|
| 生成動画の長さ | 21 クレジット/秒 | $0.105/秒 |
| 入力する参照動画の長さ | 21 クレジット/秒 | $0.105/秒 |
| 1 回の生成につき最初の 5 枚の参照画像 | 0 | $0 |
| 6 枚目以降の参照画像 1 枚ごと | 6.4 クレジット | $0.032 |
推定クレジット = 21 ×(出力秒数 + 参照動画の課金対象秒数)+ 6.4 × 5 枚を超える参照画像の枚数。 参照画像が 5 枚以下なら、画像の追加料金は 0 です。推定クレジットに $0.005 を掛けると米ドルでの料金になります。参照動画の長さに小数秒が含まれる場合、サーバーが採用する課金対象時間に基づいて計算されます。
| 例 | 推定クレジット | 推定米ドル |
|---|---|---|
| 参照素材なしで 5 秒生成 | 105 | $0.525 |
| 参照素材なしで 10 秒生成 | 210 | $1.05 |
| 参照素材なしで 15 秒生成 | 315 | $1.575 |
| 10 秒生成 + 5 秒の参照動画 + 7 枚の参照画像 | 327.8 | $1.639 |
最後の例は 21 × (10 + 5) + 6.4 × (7 − 5) で計算します。これは 1 回あたりの生成料金です。1 つのショットで複数回試す場合、予算には各生成の料金を含めてください。
入力モードと参照素材を選ぶ
入力モードは、送信するメディアフィールドによって決まります。先ほどのクイックスタートはテキストからの動画生成です。開始・終了フレームを指定したい場合や参照素材を使う場合に、対応するフィールドを追加します。
| モード | 入力フィールド | 使い方 |
|---|---|---|
| テキストから動画生成 | prompt。メディア URL は送信しない | シーン、動作、カメラの動きを文章で記述 |
| 開始・終了フレームから生成 | image_urls | 1 枚目が開始フレーム、任意の 2 枚目が終了フレーム。aspect_ratio は指定せず、開始フレームの比率を使用 |
| マルチモーダル参照生成 | reference_image_urls、reference_video_urls、reference_audio_urls | 画像・動画・音声を組み合わせる。参照音声には参照画像または参照動画が必要 |
image_urls と reference_*_urls のフィールドは併用できません。素材の URL はすべて公開アクセスでき、直接ダウンロードできる必要があります。
パラメーターと素材の制限
以下の制限は、PoYo の MiniMax H3 API ドキュメントに基づきます。
promptは必須で、最大 2000 文字です。durationは秒単位の 5–15 の整数で、デフォルトは 5。resolutionは2Kのみ対応します。- テキストからの動画生成では
21:9、16:9、4:3、1:1、3:4、9:16に対応し、デフォルトは16:9です。参照モードではadaptiveにも対応し、デフォルトとして使用します。 - 参照画像は最大 9 枚、参照動画は最大 3 本、参照音声は最大 3 本です。動画・音声は各 2–15 秒で、動画の合計と音声の合計はそれぞれ 15 秒以内に収めてください。
開始・終了フレームを使うリクエスト例
以下の JSON を POST /api/generate/submit のリクエストボディとして使用します。example.com の素材 URL はプレースホルダーなので、送信前に自分のダウンロード可能な素材へ置き換えてください。開始フレームだけを使う場合は、配列の 2 番目の URL を削除します。
{
"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"
]
}
}
画像と動画を組み合わせた参照の例
Image 1 で人物の外見を、Video 1 で参考にしたいカメラの動きを指定します。それぞれ画像配列と動画配列の最初の要素に対応します。送信前に素材 URL を置き換え、参照動画の長さも確認してください。
{
"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"
]
}
}
Python と Node.js の実装例
以下の例では、送信と照会を 2 つの関数に分けています。先にタスク ID を取得・保存し、その後で結果を待ちます。照会が中断しても、元の ID で再開でき、生成し直す必要はありません。接続エラー、タイムアウト、HTTP 429、一部の 5xx エラーで再試行するのはステータス照会だけです。送信は自動で再試行しません。
どちらの実装も照会の間隔は 10 秒、最大 60 回、各リクエストのタイムアウトは 30 秒です。そのため全体の待機時間にはリクエストの所要時間も含まれます。これらはサンプルのアプリケーション設定であり、生成時間の保証ではありません。実際の用途に合わせて間隔や再試行方針を調整してください。
Python:タスクの送信と結果のポーリング
python -m pip install requests で依存ライブラリをインストールし、前述の POYO_API_KEY 環境変数を設定します。これは同期 Python スクリプトから非同期の生成タスクをポーリングする例です。
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))
照会を再開する場合は、wait_for_h3(saved_task_id) を直接呼び出します。401、403 などの HTTP エラー、API レベルのエラー、想定外のレスポンスではポーリングが停止するため、原因を解消してから続行してください。
Node.js:組み込みの fetch を使う
以下の JavaScript は Node.js 20 以降の組み込み fetch を使用するため、HTTP クライアントの追加インストールは不要です。.mjs ファイルとして保存し、サーバーで実行してください。
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));
照会を再開する場合は、ファイル末尾の送信・照会コードを waitForH3(savedTaskId) に置き換えます。このポーリング例はスクリプトやバックグラウンドタスク向けです。Web アプリではタスク ID をフロントエンドに返し、生成状況をバックグラウンドで追跡して、ページリクエストを待たせ続けないようにします。
Webhook で結果を受け取る
送信リクエストの最上位に、model、input と並べて callback_url を指定することもできます。例は https://your-domain.com/webhooks/poyo です。タスクが成功または失敗すると、PoYo がその URL に結果を送信します。
受信側ではタスク ID をローカルの記録と照合し、同じ ID の重複通知を処理して後続処理の重複実行を防ぎます。動画のダウンロードや変換など時間のかかる処理はバックグラウンドで実行できます。コールバックの実装中も、ステータス照会で結果を確認できます。
プロンプトとシーン別の例
まず被写体と動作を記述し、次にカメラの動き、環境、光、音を追加します。参照素材を使う場合は Image 1、Video 1、Audio 1 の役割を明確にし、同じ素材に矛盾する要求を持たせないようにします。
以下の 4 つの英語例は書き方を示すもので、実際に検証した生成結果は添付していません。英語の用語は再利用しやすいですが、英語が必ず中国語より優れるという意味ではありません。時間指定や外見を保つ指示は生成の目標なので、実際の出力を確認してください。
商品広告:8 秒、参照画像モード
商品画像を input.reference_image_urls の最初の要素に置き、duration: 8、aspect_ratio: "16:9" を設定して、以下の文章を prompt に指定します。リクエスト構造は前述の参照モードの例を使い、参照動画が不要なら reference_video_urls を削除してください。
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.
まず単純なショットでボトルやラベルの一貫性を確認し、その後で複雑な回り込みのカメラワークを試します。
人物の会話:8 秒、参照画像モード
人物画像を input.reference_image_urls の最初の要素に置き、duration: 8、aspect_ratio: "16:9" を設定します。短いせりふなら、口の動きとの同期、話す速さ、人物の外見を確認しやすくなります。
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.
縦型ゲーム広告:10 秒、テキストから動画生成
duration: 10、aspect_ratio: "9:16" を設定します。時間区分は動作の順序を伝えるためのものです。画面が混み合う場合は、まず動作や登場人物を減らしてください。
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.
連続トラッキングショット:10 秒、テキストから動画生成
duration: 10、aspect_ratio: "16:9" を設定します。1 つの被写体と 1 つの移動経路で構成し、途中のカット、被写体の変化、不連続な動きがないか確認します。
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.
よくある質問とトラブルシューティング
MiniMax 自社 API のリクエスト形式をそのまま使えますか?
本ガイドでは PoYo の POST /api/generate/submit と GET /api/generate/status/{task_id} を使用します。エンドポイント、モデル ID、フィールド構造はプラットフォームによって異なる場合があるため、利用するプラットフォームのドキュメントに従ってください。
not_started のままなら再送信すべきですか?
not_started は処理待ちを意味し、それ自体は失敗ではありません。タスク ID を保持して照会を続けます。アプリの待機上限に達したらタスクを記録して後で確認し、必要に応じて ID を添えてサポートに連絡してください。
タスク ID を受け取る前に送信がタイムアウトしたら?
タイムアウトしても、サーバーがタスクを受け付けなかったとは限りません。まずタスクの記録を確認し、必要であれば送信時刻などを添えてサポートに連絡してください。ステータス照会にはタスク ID が必要です。照会できないことへの対処として再送信を行わないでください。
画像・動画・音声を同時に参照できますか?
はい。参照モードで、前述の数量と長さの制限内で組み合わせられます。参照音声には参照画像または参照動画が必要です。これらのフィールドは、開始・終了フレームモードの image_urls と併用できません。
10 秒の動画はいくらですか?
本ガイドの料金では、参照素材なしなら 10 × 21 = 210 クレジット、つまり $1.05 です。参照動画と 6 枚目以降の参照画像には追加料金がかかります。
アプリに組み込む前に、素材 URL が直接ダウンロードに対応していることを確認し、タスク ID を保存して、ユーザーごとの生成回数と同時実行数に適切な上限を設けてください。公開前には、人物の外見、商品の形状、文字、動作、音が用途に合っているか確認します。
まず MiniMax H3 モデルページで生成を試すか、API キーページから実装を始められます。モデルについては MiniMax H3 レビューと MiniMax H3 と Seedance 2.5 の比較も参照してください。