HiAPI
ブログ

チュートリアル

HiAPI APIでhailuo-2.3/text-to-videoを呼び出す方法:curl、Python、実行可能なリクエスト例

Nov 3, 2026
极简封面图:浅藕紫色与墨黑色两块纯色平面以一道清晰的硬边相接,边缘有一条细紫缝,构图庄重平静。

hailuo-2.3/text-to-video エンドポイントの役割

テキストプロンプトから短い動画クリップを生成したい場合、hailuo-2.3/text-to-video が探しているエンドポイントです。シーン、被写体、そして見たい動きを記述した自然言語のプロンプトを受け取り、生成された動画クリップを返します。このモデルは短編出力にチューニングされているため、長い物語ではなく、コンパクトで完結した一瞬を求める場合に最適な結果が得られます。

HiAPIでは、呼び出し方法は他の非同期生成エンドポイントと同じパターンに従います。リクエストを送信し、サービスがタスクを受け入れ、結果が準備できるまでポーリングします。つまり、このエンドポイントはバックエンドパイプライン(コンテンツツール、プロトタイプ生成器、バッチジョブ、あるいは人間が動画エディタの前に座らなくてもオンデマンドで数秒の動画を取得したいあらゆるシーン)に非常に適しています。

リクエストにはプロンプトと少数の生成制御パラメーターが含まれ、レスポンスにはタスク識別子と、その後で完成した動画のURLが含まれます。GPUやモデルの重みを管理する必要はありません。HiAPIが計算を担い、出力リンクを返します。他のテキストto動画APIを使ったことがあれば、全体的な形は馴染み深いものになるでしょう。ただし、hailuo-2.3のプロンプトスタイルは、単なる視覚的説明よりも物理的な動きへの思考をより評価します(詳細は後述)。

前提条件とAPI資格情報

最初の呼び出しの前に、3つのものを準備してください:

  • HiAPIアカウントのAPIキー。パスワードと同じように扱ってください。バージョン管理に含めず、環境変数から読み込み、漏洩した場合はローテーションしてください。
  • HTTPクライアント。以下のshell例ではcurlだけで十分です。Python例ではPython 3.8+とrequestsライブラリ(pip install requests)が必要です。
  • HiAPI APIのベースURL。すべてのリクエストはHiAPI APIホストに送信され、エンドポイントパスはhailuo-2.3/text-to-videoです。Authorizationヘッダーにbearerトークンを送ることで認証します。

キーを環境変数に設定して、コードに現れないようにします:

export HIAPI_API_KEY="your_api_key_here"

Pythonではos.environ["HIAPI_API_KEY"]で読み取れます。curlでは$HIAPI_API_KEYで同じ変数を参照します。

もう1つ事前に決めておくべきことがあります。生成された動画をどこに保存するかです。APIは出力のURLを返しますが、そのURLは速やかに取得して独自のバケットやファイルシステムに保存すべきです。そのURLが永久資産であると仮定するパイプラインを構築しないでください。

curlによる実行可能なリクエスト

以下はテキストto動画タスクを送信する完全なcurl呼び出しです。プロンプトはご自身のシーン記述に置き換えてください。リクエストボディはJSONで、主要なフィールドはプロンプトと、長さや出力形態を制御する生成パラメーターです。

curl -X POST "https://api.hiapi.ai/v1/hailuo-2.3/text-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "一颗玻璃弹珠沿木质斜坡滚下,加速后落到石质地面上,弹跳两次后静止",
    "duration": 6
  }'

送信が成功すると、タスク識別子を含むJSONオブジェクトが返されます。おおよそ以下のようになります:

{
  "id": "job_abc123",
  "status": "queued"
}

重要な部分はidです。生成は同期的には完了しません。エンドポイントはタスクをキューに追加して即座に返します。idを保存してください。これを使って状態をポーリングし、最終的に動画URLを取得します。

認証エラーが発生した場合は、同じshellセッションでキーがエクスポートされているか確認してください。検証エラーが発生した場合は、JSONリクエストボディの形式が正しいか、プロンプトが存在するかを確認してください。429レスポンスはリクエストの送信が速すぎることを示しており、バックオフすべきです(本番環境のセクションで詳述します)。

Pythonでの同じ呼び出し

Python版は同じことを行いますが、パイプラインに組み込みやすい再利用可能な関数にラップされています。タスクを送信し、タスク識別子を返します。

import os
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def submit_text_to_video(prompt: str, duration: int = 6) -> str:
    """hailuo-2.3/text-to-videoタスクを送信し、そのジョブIDを返します。"""
    api_key = os.environ["HIAPI_API_KEY"]
    response = requests.post(
        f"{HIAPI_BASE}/hailuo-2.3/text-to-video",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json={"prompt": prompt, "duration": duration},
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["id"]


if __name__ == "__main__":
    job_id = submit_text_to_video(
        "一颗玻璃弹珠沿木质斜坡滚下,加速后落到石质地面上,弹跳两次后静止"
    )
    print("submitted job:", job_id)

いくつかの詳細は残しておく価値があります:

  • raise_for_status()は非2xxレスポンスを例外に変換します。これはパイプラインで望ましい動作です。決して作成されなかったタスクをポーリングするより、送信段階で大きく失敗する方が良いです。
  • 送信リクエストのtimeoutは意図的に短く設定されています。送信は迅速であるべきです。長い待機はポーリング段階で発生し、ここではありません。
  • durationパラメーターは独立したパラメーターなので、呼び出し側はリクエスト構築ロジックを重複させることなく、短いまたは長いクリップを要求できます。

この関数が戻れば、状態ポーリングを続けるために必要なものはすべて揃っています。

6〜10秒のクリップ向けに運動物理プロンプトを書く

短いクリップは容赦がありません。6〜10秒では、キャラクターを確立し、世界を構築し、プロットを収束させることはできません。そのため、最も効果的なプロンプトは、明確な物理的結果を伴う単一の連続した動作を記述します。プロンプトは物語ではなく、一瞬のショット記述として考えてください。

被写体と動作から始める

何が動いているのか、それが何をしているのかから始めます。「一颗玻璃弹珠沿木质斜坡滚下」は、被写体、素材、進行方向をすぐにモデルに与えます。「一个美丽的场景」のような曖昧な始まりは、アニメーション化するものを何も与えません。

見た目だけでなく力を描写する

運動物理プロンプトとは、作用する力(重力、摩擦、運動量、重量、弾性)を語ることです。転がる、加速する、弾む、静止する、揺れる、倒れる、跳ねる、裂ける といった言葉は物理モデルを暗示します。弾む物体には、何回弾み、最終的にどこで止まるかを指定します。落下する物体には、何の上に落ち、壊れるのか、へこむのか、跳ね返るのかを指定します。

カメラを明確かつシンプルに保つ

固定カメラまたは1回のゆっくりしたカメラ移動は、短いクリップには通常十分です。カメラと被写体の両方が複雑なことをすると、クリップは雑然とし、動きはノイズのように見えます。カメラタイプが動作にとって重要な場合にのみ指定します(クローズアップ、ワイド、トラッキング)。

イベントの弧を構築する

6〜10秒のクリップに有用なテンプレートは、準備 → 動作 → 結果です。ビー玉は斜面の頂上にあり、転がり落ちて加速し、落下して2回弾んで静止します。この弧は、クリップの長さに収まる形で、モデルに始まり、中間、終わりを与えます。無関係な複数の動作を要求することは避けてください。よく描写された1つの物理イベントは、3つの中途半端なイベントよりもはるかによく読めます。

最後に、プロンプトを具体的に保ちます。素材、照明、表面テクスチャは、モデルが動きを根拠づけるのに役立ちます。木の上のビー玉と氷の上のビー玉は異なる動きをするので、それを明示することで結果を導けます。

ポーリングによる非同期タスクの処理

生成には時間がかかるため、このエンドポイントは非同期です。タスクを送信するとidを受け取ります。その後、タスクが終了状態に達するまで状態エンドポイントをポーリングします。堅牢なポーリングループは3つのことを処理します:間隔、タイムアウト、エラー公開です。

import time
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def wait_for_video(job_id: str, api_key: str, interval: float = 3.0, max_wait: float = 600.0) -> str:
    """タスクが完了するまでポーリングし、出力動画のURLを返します。"""
    deadline = time.time() + max_wait
    url = f"{HIAPI_BASE}/hailuo-2.3/text-to-video/{job_id}"

    while time.time() < deadline:
        response = requests.get(
            url,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30,
        )
        response.raise_for_status()
        data = response.json()
        status = data.get("status")

        if status == "completed":
            return data["output"]["video_url"]
        if status in ("failed", "cancelled"):
            raise RuntimeError(f"タスク {job_id} はステータス {status} で終了しました:{data.get('error')}")

        time.sleep(interval)

    raise TimeoutError(f"タスク {job_id} は {max_wait} 秒以内に完了しませんでした")

このループに関する注記:

  • 間隔をあけてポーリングし、タイトループにしない。チェック間の数秒の間隔で十分であり、APIへの負荷を避けられます。
  • 常に総待機時間を制限する。スタックしたタスクがワーカープロセスを永遠にハングさせてはいけません。ここでのmax_wait値は控えめです。クリップの長さとキューの状況に応じて調整してください。
  • failedを実際の分岐として扱う。盲目的に再試行するのではなく、エラーペイロードを公開します。プロンプトやパラメーターの問題は自然に解決しません。
  • 生のレスポンスではなく動画URLを返す。この関数の呼び出し側はレスポンス構造を知る必要はありません。

より重いワークロードでは、送信とポーリングのステップを別々のワーカープロセスに配置します。1つのワーカーがタスクをキューに入れてタスクIDを保存し、別のワーカーがポーリングとダウンロードを担当します。これにより、リクエスト遅延と生成時間が分離されます。

出力のダウンロードと保存

ポーリングが動画URLを返したら、バイトを取得して永続的な場所に書き込みます。速やかに実行してください。返されたURLは配信リンクであり、永久資産ストレージではありません。ファイル全体をメモリに読み込むのではなく、ストリーミングでダウンロードします。まず一時パスに書き込んでからリネームし、部分ダウンロードが完成ファイルのように見えないようにします。

import os
import tempfile
import requests


def download_video(video_url: str, dest_path: str) -> None:
    """完成した動画をdest_pathにアトミックにストリーミング書き込みします。"""
    os.makedirs(os.path.dirname(dest_path) or ".", exist_ok=True)
    with requests.get(video_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(dest_path) or ".")
        try:
            with os.fdopen(fd, "wb") as f:
                for chunk in response.iter_content(chunk_size=1 << 16):
                    f.write(chunk)
            os.replace(tmp_path, dest_path)
        except Exception:
            if os.path.exists(tmp_path):
                os.unlink(tmp_path)
            raise


api_key = os.environ["HIAPI_API_KEY"]
video_url = wait_for_video("job_abc123", api_key)
download_video(video_url, f"out/{'job_abc123'}.mp4")

いくつかの実用的な選択:

  • ファイルをタスクIDで命名する。これにより安定した衝突耐性のあるキーが得られ、ファイルを生成したリクエストに容易に関連付けられます。
  • メタデータを動画と一緒に保存する。元のプロンプト、長さ、タイムスタンプを付属のJSONまたはデータベースに保存します。6か月後、あるクリップが何から生成されたのか知りたくなるでしょう。
  • 本番環境ではオブジェクトストレージにアップロードする。ローカルディスクへの書き込みはプロトタイプには問題ありませんが、実際のパイプラインではファイルをバケットにプッシュしてオブジェクトキーを記録し、ワーカープロセスの再起動後も動画が存続するようにすべきです。

本番環境のヒントと一般的な障害パターン

ほとんどの初回統合は同じようないくつかの場所で問題が発生します。以下は注意すべき事項です。

正しいものを再試行する

一時的な障害(ネットワークエラー、タイムアウト、429および5xxレスポンス)には、指数バックオフとジッターを使って再試行します。4xx検証エラーには再試行しないでください。形式が不正なプロンプトや誤ったパラメーターは毎回同じように失敗します。生成タスク自体が失敗した場合は、エラーを公開し、再送信するかどうかを慎重に判断してください。

送信とポーリングを分離する

本番環境では、送信とポーリングは別々のステップであるべきで、通常は別々のプロセスで行われます。送信が成功したらすぐにタスクIDをキューまたはデータベースに保存します。ワーカープロセスがクラッシュしても、タスクを失うことなくポーリングを再開できます。

至る所でタイムアウトを設定する

送信リクエスト、状態ポーリング、ファイルダウンロードにはそれぞれタイムアウトを設定すべきです。ダウンロードステップでのタイムアウト欠如は、ワーカープロセスがハングする典型的な原因です。

プロンプトをモデルの強みの範囲内に保つ

6〜10秒の範囲で、単一の物理的に妥当な動作を要求します。プロンプトが多くを求めすぎると、動きが濁った雑然としたクリップになります。出力品質が一貫しない場合は、パラメーターを変更する前に、まずプロンプトを短縮して動作を単純化してください。

資格情報を正しく処理する

APIキーは環境変数またはシークレットマネージャーから読み込み、コミットされたファイルからは決して読み込まないでください。環境ごとに異なるキーを使用し、漏洩した開発キーが本番環境に到達できないようにします。

URLの有効期限に関する仮定に注意する

本番環境で最も一般的な間違いは、返された動画URLを永久リンクとして扱い、数か月後にユーザーインターフェースで直接レンダリングすることです。ファイルをダウンロードして再ホスティングすることをタスクの一部とし、独自のURLを保存してください。

これらの習慣があれば、統合は小さなものになります:送信、ポーリング、ダウンロード、保存。

永続的なAIアーティファクトで開発を始める

APIキーを取得して、タスクベースの1つのAPIで画像・動画・音声モデルを呼び出せます。

APIドキュメントを読む