チュートリアル
hailuo 2.3 Fast 画像-to-動画 API の使い方:curl、Python、実行可能なリクエスト
手元に静止画像があり、それを短い動画にしたいとします。このガイドでは hiapi タスク API を通じて hailuo-2.3-fast/image-to-video に接続します。正確な入力スキーマ(オンラインのバリデータで検証済み)、そのままコピーできる curl リクエスト、タスク完了までポーリングできる完全な Python スクリプト、そして本番環境の詳細——コールバック、冪等なリトライ、実際に遭遇するエラーレスポンス——を扱います。
準備するもの
- hiapi API キー——コンソールから取得します。キーは
sk-...の形式で、Authorization: Bearerリクエストヘッダーに含めます。 - 公的にアクセス可能な HTTPS URL 上でホストされたソース画像。API が受け取るのは URL であり、ファイルのアップロードではありません。
- 任意の HTTP クライアント。以下の例では curl と Python の
requestsを使用します。
このモデルの秒単位の課金価格は料金ページに記載されています。
入力スキーマ(検証済み)
hailuo-2.3-fast/image-to-video は統一された非同期タスクエンドポイントを使用します:POST /v1/tasks でタスクを作成し、GET /v1/tasks/<taskId> でタスクをポーリングします。入力スキーマは厳格で、未知のフィールドは黙って無視されるのではなく、400 を返して拒否されます。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
prompt |
string | ✅ | 望む動きを記述する |
image_url |
string | ✅ | 単数形——1 つの URL 文字列であり、image_urls 配列ではない |
duration |
string | 任意 | "6" または "10"——数値ではなく文字列 |
prompt_optimizer |
boolean | 任意 | バックエンドに動きのためのプロンプトを書き換えさせる |
バリデータが捕まえる 3 つの落とし穴:
durationは文字列でなければならない。"duration": 6を送ると400が返り、duration: got number, want stringと表示されます。"duration": "6"を送ってください。- フィールドは単数形の
image_url。 プラットフォーム上の他の多くの動画モデル(Grok Imagine、Kling)はimage_urls配列を受け取ります。このモデルは単一の文字列を受け取ります。 resolution、aspect_ratio、seed、watermark、end_image_urlは存在しない。 これらはいずれもadditional properties ... not allowedを返します。出力の画角はソース画像に従い、動きの制御はプロンプトによってのみ行えます。
最小限の実行可能なリクエスト:curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": "カメラがゆっくりと寄り、コーヒーカップから湯気が立ち上り、柔らかな朝の光",
"image_url": "https://your-cdn.example.com/coffee.jpg",
"duration": "6"
}
}'
成功時のレスポンス:
{
"code": 200,
"data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
"message": "success"
}
次にポーリングします:
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V \
-H "Authorization: Bearer sk-YOUR_KEY"
動画のレンダリング中、data.status は "handling" です:
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
"model": "hailuo-2.3-fast/image-to-video",
"status": "handling",
"storage": "temp",
"completed": 0,
"created": 1783648872
},
"message": "success"
}
終端状態は "success"(動画 URL は data.output[0].url)と "fail"(詳細は data.error)です。
完全な Python スクリプト
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
resp = requests.post(
API_BASE,
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": prompt,
"image_url": image_url,
"duration": duration, # 文字列: "6" または "10"
},
},
timeout=60,
)
body = resp.json()
if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
raise RuntimeError(f"create failed: {resp.status_code} {body}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="猫がまばたきをし、窓のほうに頭を向け、そよ風が毛並みを撫でる",
image_url="https://your-cdn.example.com/cat.jpg",
duration="6",
)
print("task:", task_id)
task = wait_task(task_id)
video_url = task["output"][0]["url"]
print("video:", video_url)
# URL は有効期限付きの一時ストレージ上にある——すぐにダウンロードし、直接外部リンクしないこと。
mp4 = requests.get(video_url, timeout=120).content
with open("output.mp4", "wb") as f:
f.write(mp4)
print(f"saved output.mp4 ({len(mp4)} bytes)")
このスクリプトは、素早く継ぎ合わせた実装が見落としがちな 2 つのことを正しく行っています:
- 動画をすぐにダウンロードする。
storage: "temp"は、出力 URL に有効期限(expireAt)があることを意味します。バイトを自分のストレージに永続化してください。返された URL をデータベースに保存してはいけません。 failを終端状態として扱う。 失敗したタスクを再ポーリングしても復活しません——新しいタスクを作成してください。
本番環境での注意点
ポーリングの代わりにコールバックを使う
スクリプト以外の用途では、タスク作成時に webhook を登録して、ポーリングループを完全に省略します:
{
"model": "hailuo-2.3-fast/image-to-video",
"input": { "prompt": "...", "image_url": "https://...", "duration": "6" },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
"when": "final" を使うと、タスクが success または fail に到達したとき、エンドポイントが 1 回呼び出されます。経験則:ポーリングは CLI、バッチ処理、その他あらゆる一時的な用途に適しています。すでに待ち受けているサーバーがある場合はコールバックの方が優れています——動画タスクは数分間実行され、ポーリングループはその数分間、接続スロットを 1 つ占有し、ワーカーを 1 つ浪費するからです。
冪等性
作成呼び出し自体は冪等ではありません——検証を通るたびに POST /v1/tasks は新しい(課金対象の)タスクを作成します。タスクランナーがタイムアウトでリトライする場合は、結果を処理する前に、取得した taskId を独自のリクエスト id をキーとして保存してください。リトライ時、そのキーにすでに taskId があれば、重複タスクを作成するのではなく、それをポーリングしてください。
実際に遭遇するエラー
| 症状 | 意味 | 修正 |
|---|---|---|
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}} |
キーが無効、またはそのキーではこのモデルを使用できない | コンソールでキーを確認する。レスポンスにはサポート用の request_id が含まれる |
400 INVALID_REQUEST — duration: got number, want string |
JSON の数値を使ってしまった(文字列ではない) | "duration": "6" |
400 INVALID_REQUEST — additional properties '...' not allowed |
スキーマ外のフィールドを送信した | それを削除する——メッセージが違反している各フィールドを指し示す |
400 INVALID_REQUEST — missing required field "prompt" / "image_url" |
入力が空、またはフィールド名が誤っている | 両方のフィールドが必須 |
タスク作成後に fail に到達 |
実行時の失敗——よくある原因はバックエンドが取得できない画像 URL | バリデータは作成時に画像を取得しない。URL が公的にアクセス可能であることを確認する |
最後の行は強調に値します:作成時の検証はスキーマのみを対象とします。スペルミスやプライベートな image_url は、一見正常な taskId と、数分後に死ぬタスクを返します——ですから HTTP エラーだけでなく、fail に対してもアラートを出すべきです。
関連記事
- hailuo-2.3-fast/image-to-video モデルページ — プレイグラウンドと秒単位の料金
- 画像-to-動画 API ワークフロー:本番ガイド — i2v エンドポイントを中心としたバッチ処理、ストレージ、リトライのアーキテクチャ
- テキスト-to-動画 vs 画像-to-動画 API — ソース画像を基準に生成すべき場面
- Kling 画像-to-動画 API ガイド — 同じタスク API、異なる入力スキーマという有用な対照
よくある質問
解像度やアスペクト比を設定できますか?
いいえ。hailuo-2.3-fast/image-to-video のスキーマは resolution と aspect_ratio を未知のフィールドとして拒否します。画角はソース画像に従います。特定のアスペクト比が必要な場合は、入力画像を事前にトリミングしてください。
対応している長さは?
ちょうど 2 つ:"6" と "10" 秒で、文字列として渡します。それ以外の値は 400 を返し、value must be one of '6', '10' と表示されます。
複数の参照画像を渡せますか?
いいえ——そのフィールドは単一の image_url 文字列です。画像配列を受け入れるモデル(例えば Grok Imagine の image_urls)は異なるスキーマを使用します。確認せずにモデル間でリクエストボディをコピーしないでください。
動きを制御するには?
prompt によってのみ可能です——動きの強さやカメラのパラメータはありません。動きを明示的に記述してください(「カメラがゆっくりと寄る」、「髪が風に揺れる」)。任意で "prompt_optimizer": true を設定すると、バックエンドがプロンプトを拡張します。
より遅く、高品質なバリエーションはありますか?
はい——hailuo-2.3/image-to-video(-fast なし)もプラットフォームに公開されており、hailuo-2.3/text-to-video はソース画像なしのシナリオをカバーします。切り替える前に各バリエーションのスキーマを確認してください。入力フィールドが一致する保証はありません。
料金はいくらですか? 課金は生成された動画の秒数に基づいて計算され、モデルごとに異なります。現在の料金は料金ページを確認してください。
試用に API キーは必要ですか?
はい——すべてのタスク API 呼び出しには Bearer sk-... キーが必要です。コンソールで作成でき、まずモデルページのプレイグラウンドでテストできます。
関連記事
すべての記事を見る →-
チュートリアル
HiAPI API で hailuo-2.3-fast/image-to-video を呼び出す方法:curl と Python の実践
高速・低コストな画像から動画へのティアにおける最初の実行可能なリクエスト — モデル ID から MP4 のダウンロードまで
-
チュートリアル
HiAPI APIでhailuo-2.3/text-to-videoを呼び出す方法:curl、Python、実行可能なリクエスト例
-
チュートリアル
HiAPI で Kandinsky 6.0 Pro のテキストto動画を使用する:curl と Python チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする