チュートリアル
HiAPI API で kling-3.0-omni/image-to-video を使う方法:curl と Python ガイド
image-to-video エンドポイントの役割
動画生成は同期呼び出しではありません。HiAPI では、kling-3.0-omni/image-to-video はまず送信し、その後ポーリングするパターンに従います。タスクを記述した HTTP リクエストを送信すると、API がリクエストを受け付けてタスク識別子を返し、その後、動画の生成が完了するまでそのタスクをクエリします。
この 2 段階構造には十分な理由があります。静止画像から動画をレンダリングするには時間がかかり、典型的な HTTP リクエストを開いたままにしておくべき時間をはるかに超えます。エンドポイントがファイルの準備完了までブロックすると、毎回の呼び出しでゲートウェイタイムアウトや接続切断に遭遇します。タスクハンドルを即座に返すことで、API はあなたのコードに、どれだけ待つか、どのくらいの頻度で確認するか、エラー時にどう処理するかを委ねます。
典型的なタスクは 3 つの論理部分で構成されます:
- 入力メディア——ショットのアンカーとなる画像(または画像セット)。
- 生成設定——プロンプトテキスト、モーション関連オプション、音声、解像度の選択。
- ライフサイクル——タスク ID を含む送信レスポンス、続いて最終的な動画 URL または失敗理由を返すステータスチェック。
このエンドポイントはレシート付きのキューと考えると役立ちます。送信呼び出しは作業票の提出、レシートはタスク ID、ポーリング呼び出しはカウンターで注文が準備できたか尋ねる行為です。送信時に動画そのものは返らないため、作成するクライアントは最初からこの 2 つのフェーズを中心に構成すべきです。
そこから 2 つの帰結が生まれます。第一に、エラーハンドリングは分ける必要があります。拒否されたリクエストボディは送信時の問題であり、コードで修正できます。一方、レンダリング失敗はタスクレベルの問題であり、同じリクエストボディを何度再試行しても解決しません。第二に、タスク ID を保存する場所——ログ行、データベース行、スクリプト内の変数——が必要です。これは進行中の作業を掌握する唯一のハンドルだからです。
このメンタルモデルを確立すれば、このガイドの残りは主に配管作業です。リクエストを構築し、それを正しく待つことです。
動作する curl リクエストの構築
まず最小限の動作するリクエストから始め、受け付けられることを確認してからオプションを追加します。正確な JSON フィールド名とエンドポイントパスは HiAPI 上のこのモデルのリファレンスページで定義されています——ブログ記事(この記事を含む)の断片を信じるのではなく、そのページを参照して現在のスキーマを確認してください。
送信呼び出しは予測可能な構造を持ちます。Authorization ヘッダーで HiAPI API キーを使って認証し、Content-Type: application/json を宣言し、JSON リクエストボディを送信します。概念的にはリクエストボディは次のようになります:
{
"model": "kling-3.0-omni/image-to-video",
"input": {
"image": "https://your-cdn.example.com/frame-first.jpg",
"prompt": "A slow dolly-in as morning light crosses the room"
}
}
構造はリテラル値よりも重要です。モデル識別子、ソース画像参照とプロンプトを運ぶ入力オブジェクト、そして生成オプションのための空間です。すべてのキーをハードコードする前に、現在のドキュメントと照合して検証してください。
同等の curl 呼び出しは一般的なパターンに従います:
curl -sS -X POST "$HIAPI_BASE_URL/v1/video/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @request.json
リクエストボディをインラインではなく request.json に保存すると、反復がはるかに楽になります——シェルの履歴エントリではなくファイルを編集するからです。
レスポンスの読み取り
成功した送信は意図的に地味です。タスク識別子と、受け付けられたが未完了であることを示すステータスが返ることを期待してください。それを解析し、出力し、保存します:
curl -sS -X POST "$HIAPI_BASE_URL/v1/video/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @request.json | tee submit.json
まず HTTP ステータスコードを確認します。4xx はリクエスト自体が拒否されたことを意味します——誤ったキー、形式不正な JSON、サポートされていないオプション、無効な画像 URL など。2xx はタスクがシステムに投入されたことを意味し、その瞬間から有用なシグナルは HTTP ステータスコードではなくタスクステータスから得られます。
ポーリングコードを書く前に、まず送信を一度手動で実行してください。出力にタスク ID が見えることを確認します。この手動の往復は、ほとんどの設定ミスを早期に発見します。
最初のフレームと最後のフレームの入力の扱い
送信する画像は単なる参考情報ではありません——ショットの起点を制約します。この違いが、このセクションの設計判断の大部分を決めます。
最初のフレームのみ
単一の画像を提供する場合、それを開始フレームとして扱います。プロンプトはその後、そのフレームから何が起こるべきかを記述します:カメラの動き、被写体の動作、照明の変化、テンポ。モデルは最初のフレーム以降のすべてを創造しなければならないため、軌跡を記述するプロンプトは静的なシーンを記述するプロンプトよりもうまく機能します。「静止したままで美しく見える」はモデルにアニメートするものを何も与えません。「彼女が窓の方を向き、光も暖かくなる」は方向を与えます。
最後のフレームの追加
最後のフレームの入力を追加すると、タスクは補間問題に変わります。2 つの端点を提供し、モデルがその間の経路を生成します。これは制御されたトランジションに非常に強力です——製品が正面図から背面図へ回転する、キャラクターが 2 つのポーズ間で切り替わる——なぜなら終点が想像されるのではなく固定されるからです。
実用的な注意点が 3 つあります:
- 2 つのフレームの互換性を保つ。 類似したフレーミング、パースペクティブ、被写体の比率が補間を信頼できるものにします。大きく異なる構図は、存在しないかもしれない橋をモデルに発明させることになります。
- プロンプトを書き直す。 2 つのフレームがある場合、テキストは終点ではなくそれらの間の動きを記述すべきです。運動スタイルと継続時間を名指しする方が、すでに提供した最終状態を物語るよりも自然です。
- リクエスト構造が変わることを予期する。 最後のフレームは別の入力フィールドであるため、リクエストボディにはキーが 1 つ増えます。オプションフィールドをすべてを再構築せずに追加できるようにリクエストオブジェクトを構築してください。
コードでは、フレームを緩い URL の集合ではなく、名前付き入力の小さなセットとして扱います:
inputs = {"image": first_frame_url}
if last_frame_url:
inputs["last_frame"] = last_frame_url
この条件分岐により、単一フレーム呼び出しと 2 フレーム呼び出しを同じコードパスに保てます。バリエーションを生成し始めるときに重要になります。
最後に、フレームは確実に到達可能な場所にホストしてください。タスク途中で期限切れになる URL は送信後に失敗し、そのエラーはリソース問題ではなく生成失敗のように見えます。
音声と出力解像度の設定
音声と解像度はリクエストレベルの選択であり、グローバル設定ではありません。タスクごとに決定するものであり、一度設定して忘れる構成定数ではなく、プロンプトの隣のリクエストボディビルダーに置くべきです。
音声
音声オプションは通常、動画とともに音声をリクエストするか、省略するかを可能にします。これをユースケースに関連するモデリング判断として扱ってください。ソーシャル向けの短いクリップは生成音声の恩恵を受けるかもしれませんが、エディターで音楽を付ける予定のクリップには音声を持たせるべきではないでしょう。使わない音声をリクエストすることは、何の利益もなく生成時間を浪費します。
音声の挙動は最も変化しやすい領域の一つであるため、音声トラックの内容やプロンプトとの関係についての仮定をハードコードしないでください。現在のモデルドキュメントを読み、実際のタスクで出力を検証してから、それを中心に下流のフローを設計してください。
解像度
解像度が高いほどフレームあたりのピクセル数が増え、計算量も大幅に増えます。実用的なワークフローは、プロンプトとフレーム選択を調整する間は中程度の解像度で反復し、勝ち残った構成を最終解像度で再生成することです。最良の結果が誤った設定で生成されていたことに最後に気づくより、良い結果を再生成する方がはるかに安価です。
身につける価値のある習慣がいくつかあります:
- 送信前に検証する。 モデルがサポートしない解像度を渡した場合、数分後の混乱するタスクレベル失敗ではなく、明確な送信時拒否を得たいものです。
- 設定をタスクと一緒に保存する。 複数の結果を比較するとき、各結果がどの解像度と音声選択によって生成されたかを知る必要があります。
- フレーム間の対等性を仮定しない。 大きなソース画像を使う 2 フレームタスクは単一フレームタスクと異なる挙動をするかもしれません。両方の経路をテストしてください。
コード内での配置場所
生成オプションを独自のオブジェクトにグループ化すると、意図が明確になり、デフォルト値を 1 か所で置き換えられます:
options = {
"resolution": "1080p", # confirm supported values in the model docs
"audio": True,
}
ドキュメントの値に依存する行にはコメントを追加してください。未来のあなた——またはチームメイト——は、どのフィールドが安全で、どれがリリース前にリファレンスページと照合する必要があるかを即座に判別できるべきです。疑わしい場合、HiAPI 上のモデルドキュメントが信頼できる情報源であり、サンプルリクエストボディではありません。
Python での完了状態のポーリング
ポーリングコードは、ほとんどの統合が静かに脆弱になる場所です。目標は、毎回コピー&ペーストして編集するスクリプトではなく、タスクを送信し、合理的な制限でそれを待つ、小さく再利用可能なクライアントを構築することです。
最小クライアント構造
import os, time, requests
BASE = os.environ["HIAPI_BASE_URL"]
KEY = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}"}
def submit(payload: dict) -> str:
r = requests.post(f"{BASE}/v1/video/generations",
headers=HEADERS, json=payload, timeout=30)
r.raise_for_status()
return r.json()["id"]
def wait(task_id: str, interval: float = 5.0, max_wait: float = 600.0) -> dict:
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
r = requests.get(f"{BASE}/v1/video/generations/{task_id}",
headers=HEADERS, timeout=30)
r.raise_for_status()
job = r.json()
if job["status"] in ("succeeded", "failed"):
return job
time.sleep(interval)
raise TimeoutError(f"task {task_id} not finished in {max_wait}s")
このコードの 4 つの詳細が大部分の重みを担っています:
- すべての HTTP 呼び出しに明示的なタイムアウト。 ハングしたリクエストは失敗したリクエストより悪いです。
- 最大待機時間。 無制限のループはスタックしたタスクをスタックしたサービスに変えます。
- 終端状態のチェック。 ステータスが真に最終的なときだけ停止し、認識できないステータスを含む他のすべてはまだ実行中として扱います。
- タスクオブジェクト全体を返す。 呼び出し側は通常、ブール値だけでなく出力 URL とエラー詳細を必要とします。
ポーリングのペース
動画タスクでは 5 秒が妥当なデフォルトです。200ms ごとのポーリングはレンダリングに数分かかるにもかかわらず、クォータを消費するだけで何の利益もありません。多数のタスクを送信する場合、ポーリングループをリクエストハンドラーではなくワーカーに置き、長時間実行タスクには少しバックオフを入れます。
つなぎ合わせる
payload = {
"model": "kling-3.0-omni/image-to-video",
"input": {"image": first_frame_url, "prompt": prompt},
"options": options,
}
job = wait(submit(payload))
if job["status"] == "failed":
raise RuntimeError(job.get("error") or "generation failed")
print(job["output"]["url"])
submit はプレーンな文字列を返し、wait は dict を返すため、それぞれを独立してテストできます。モックの送信レスポンスでポーリングロジックをテストし、submit を単独で呼び出してリクエストボディをライブ API と照合できます。
一般的な障害のデバッグ
障害は 3 つの層に集中し、層を特定することが診断の大部分です。
層 1:送信時の拒否
これらはタスクが存在する前に 4xx レスポンスとして現れます。一般的な原因:
- 認証——ヘッダーの欠落、形式不正な bearer トークン、想定した環境にエクスポートされていないキー。
- リクエストボディの構造——フィールド名の誤り、配列位置での文字列の使用、オプションのネスト階層の誤り。
- サポートされていない値——モデルが受け付けない解像度や音声の組み合わせ。
- リソースの問題——到達不能、期限切れ、または画像でないファイル URL。
エラーレスポンスボディを読んでください。API は通常、問題のあるフィールドを指摘し、最も速い修正はメッセージが示唆するものです。curl で失敗した呼び出しを再現し、問題がクライアントコードではなくリクエストボディにあることを確認してください。
層 2:転送の問題
ネットワークはコードとタスクライフサイクルの間に位置します。送信呼び出しでのタイムアウトと接続リセットは曖昧です。タスクは作成されたかもしれないし、されていないかもしれません。盲目的に再試行すると重複タスクが生成される可能性があります。
安全なパターンは、冪等で安全な操作のみを再試行し、すべての送信試行とそのレスポンスをログに記録することです。送信が成功したかどうかを本当に判断できない場合は、再送信する前にタスク履歴を確認してください。ポーリングに関しては、1 回のステータスチェック失敗はタスク失敗ではありません——例外をキャッチし、待って、再度尋ねてください。
層 3:タスクレベルの失敗
これらは受け入れられたタスクに終端状態として到達します。通常、コンテンツが指定どおりに生成できないことを意味します。2 つのフレームが離れすぎて補間できない、プロンプトとソース画像が調和できない、またはレンダリング中の内部エラーなどです。
コードではこれらを明確に区別してください。対策が異なるからです。4xx はリクエストを修正することを意味します。失敗したタスクは入力を変更するか再試行することを意味します——同じリクエストボディが 2 回失敗したら、再試行をやめて何かを変えてください:プロンプトを単純化する、より近いフレームを選ぶ、解像度を下げる。
迅速なトリアージチェックリスト
- HTTP ステータスは
4xxですか?リクエストボディまたは認証情報を修正してください。ポーリングしないでください。 - 送信は成功したのにタスクが完了しない?待機制限が短すぎるかタスクがスタックしています——永遠にループするのではなく、タスク ID を記録して調査してください。
- タスクは失敗しましたか?エラー詳細を読み、そのまま再送信するのではなく入力を調整してください。
- 成功したのに動画が違う?それはプロンプトとフレーム選択の問題であり、API の問題ではありません。
リリース:本番チェックリスト
ユーザーに公開する前に、静かに失敗する部分を強化してください。
設定。 ベース URL と API キーは環境変数またはシークレットマネージャーに保存し、ソースコードには絶対に置かないでください。いずれかが欠けている場合は、最初のユーザーリクエスト時ではなく起動時に即座に失敗させてください。
タイムアウトと再試行。 すべてのアウトバウンド呼び出しに明示的なタイムアウトが必要です。再試行が許容される場合にのみ送信を再試行し、ポーリングの再試行は安全——冪等な状態読み取り——として扱ってください。総待機時間を制限し、呼び出し側に明確なタイムアウトを公開してください。
タスク ID は記録です。 タスク ID を送信したリクエストボディとともに永続化してください:フレーム、プロンプト、解像度、音声選択、タイムスタンプ。2 週間後に誰かが動画がおかしい理由を尋ねたら、その 1 行がすべての答えです。
出力は一時的です。 返された動画 URL は一時的なものとして扱ってください。タスクが成功したらすぐにダウンロードして独自の永続ストレージに保存し、保存場所をタスクに記録してください。
コスト意識。 動画生成は生成出力に応じて課金されるため、解像度、継続時間、生成回数が重要なレバーです。低解像度で反復し、最終版は意図的に生成し、設定を記録して支出を特定のユースケースに帰属できるようにしてください——請求書で初めて気づくのではなく。
可観測性。 送信時と終端状態時に、タスク ID、レイテンシ、ステータスを含むログ行を出力してください。モデルごとの単純な成功率指標は、プロンプト変更やオプション調整がいつタスク失敗を引き起こし始めたかを教えてくれます。
サンプルではなくドキュメントと照合する。 音声、解像度、フレーム入力を伴う各リリースの前に、モデルリファレンスページでフィールド名と受け入れられる値を確認してください。これらが最も変動しやすい設定だからです。
クライアント、ポーリングループ、そしてこれらのセーフガードがあれば、kling-3.0-omni/image-to-video は動作を祈るスクリプトではなく、予測可能なコンポーネントになります。
関連記事
すべての記事を見る →-
チュートリアル
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 チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする