チュートリアル
hiapi API で omnihuman-1.5 を使う方法:curl、Python、すぐに実行できるリクエスト
omnihuman-1.5 は、1枚の人物写真と音声を組み合わせて、リップシンクされたトーキング動画を生成します。hiapi では、他のすべてのメディアモデルと同様に、同じ非同期タスクプロトコル上で動作します。まず POST /v1/tasks を1回呼び出してタスクを作成し、その後、動画 URL が準備できるまでポーリング(または webhook を受信)します。本ガイドでは実際のリクエスト schema を使用しており、オンライン API とフィールド単位で照合済みです。そのため、以下の curl と Python コードはコピーしてそのまま実行できます。単なる例ではありません。
構築するもの
顔画像と音声トラックを omnihuman-1.5 に送信し、その顔が音声に合わせて話す、リップシンクされた MP4 ファイルを返すスクリプトです。動画クリップの長さは音声に従います。duration フィールドを設定することはできません。
前提条件
- hiapi API key。 dashboard で作成します。各リクエストで Bearer token として送信されます。リクエストヘッダーの形式については 認証ドキュメント を参照してください。
- 公開アクセス可能な画像 URL と音声 URL。 omnihuman-1.5 はサーバー側で両方をダウンロードするため、あなたのマシンから匿名で開ける
http(s)URL で構いません。localhostのパスや、タスクの途中で期限切れになる署名付き URL は使用できません。
必要なのはこれだけです。SDK は不要で、key 以外にアカウントも不要です。
入力 schema
omnihuman-1.5 は厳密な input オブジェクトを受け付けます。未知のフィールドは拒否されるため、利用可能なフィールドはこれで全部です:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
image_url |
string | はい | 人物の URL。明瞭で正面を向いた単一の顔が最も良い結果になります。 |
audio_url |
string | はい | リップシンクに使用する音声トラック。出力の長さを決めます。 |
prompt |
string | いいえ | 任意の動き・表情のガイド。 |
resolution |
string | いいえ | "720p" または "1080p"。 |
テキストのみのモードはありません。audio_url は必須です。スクリプトしかない場合は、先に音声を生成してください(TTS モデル、または heygen-avatar-v のようなテキスト駆動型デジタルヒューマンを使用)。その後、生成された音声 URL をここに渡します。
最小の実行可能な例(curl)
タスクを作成します:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "omnihuman-1.5",
"input": {
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voiceover.mp3",
"resolution": "720p"
}
}'
レスポンスにはタスク id が含まれます:
{ "code": 200, "data": { "taskId": "b3f1c2e8-...", "status": "pending" } }
タスクが終了状態に達するまでポーリングします:
curl -s https://api.hiapi.ai/v1/tasks/b3f1c2e8-... \
-H "Authorization: Bearer sk-YOUR_KEY"
完了すると、data.status は "success" になり、動画は data.output[0].url にあります:
{
"code": 200,
"data": {
"taskId": "b3f1c2e8-...",
"status": "success",
"output": [
{ "url": "https://temp.hiapi.ai/.../omnihuman.mp4", "expireAt": 1760000000 }
]
}
}
この output URL は一時的なものです(expireAt 付き)。タスク成功後はすぐに MP4 をダウンロードしてください。本番環境でこのアドレスを直接ホットリンクしないでください。
Python での同じ呼び出し
import time
import requests # pip install requests
API = "https://api.hiapi.ai/v1/tasks"
KEY = "sk-YOUR_KEY"
HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
def create_task() -> str:
payload = {
"model": "omnihuman-1.5",
"input": {
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voiceover.mp3",
"resolution": "720p",
},
}
r = requests.post(API, headers=HEADERS, json=payload, timeout=60)
r.raise_for_status()
return r.json()["data"]["taskId"]
def wait_for_video(task_id: str, timeout: int = 600, interval: int = 5) -> str:
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30)
data = r.json()["data"]
status = data["status"]
if status == "success":
return data["output"][0]["url"]
if status == "fail":
raise RuntimeError(f"omnihuman-1.5 task failed: {data.get('error')}")
time.sleep(interval)
raise TimeoutError(f"task {task_id} did not finish in {timeout}s")
if __name__ == "__main__":
tid = create_task()
print("task:", tid)
video_url = wait_for_video(tid)
# URLs expire — persist the bytes immediately.
mp4 = requests.get(video_url, timeout=120).content
with open("talking_head.mp4", "wb") as f:
f.write(mp4)
print("saved talking_head.mp4")
本番環境への投入
頻繁なポーリングよりもコールバックを優先してください。 トップレベルの callback オブジェクトを追加すると、hiapi はポーリングさせる代わりに、完了したタスクをあなたのエンドポイントへ POST します:
{
"model": "omnihuman-1.5",
"input": {
"image_url": "https://example.com/portrait.jpg",
"audio_url": "https://example.com/voiceover.mp3",
"resolution": "1080p"
},
"callback": { "url": "https://your.app/webhooks/hiapi", "when": "final" }
}
when は "final" のみを受け付け、成功時と失敗時の両方で発火します。そのため、webhook は data.status に応じて分岐処理する必要があります。配信される body は GET /v1/tasks/{id} で取得するのと同じオブジェクトです。配信は at-least-once セマンティクスであるため、taskId で重複排除してください。
一時的なエラーで再送信しないでください。 ポーリングリクエストがタイムアウトしたり接続が切断された場合は、同じ taskId を再度ポーリングしてください。POST /v1/tasks を再度呼び出さないでください。再送信すると2つ目の課金対象タスクが開始されます。taskId を取得したらすぐに保存してください。
3種類の失敗形態をそれぞれ処理します:
- 認証失敗 → HTTP
401、body{"error": {"code": "permission_denied", "type": "hiapi_error", ...}}。key を修正してください。再試行しないでください。 - 不正なリクエスト(フィールドの欠落/無効)→ HTTP
400、body{"code": 400, "error_code": "INVALID_REQUEST", "message": "..."}。message が問題のあるフィールドを示します。修正して再送信してください。 - 開始されたが失敗したタスク → HTTP
200かつdata.status == "fail"、data.error付き。最も一般的な原因は、サーバーがimage_url/audio_urlをダウンロードできないことです。両方が公開アクセス可能で、まだ有効であることを確認してください。常に HTTP ステータスコードだけでなく、data.statusに応じて分岐処理してください。
価格は出力秒数に基づいて課金され、pricing ページ に記載されています。クリップの長さは音声に従うため、コストは音声の長さに応じて変わります。
関連ガイド
- 統一非同期 API の紹介 —— すべてのモデルが共有する
/v1/tasksの作成とポーリングの契約。 - クイックスタート —— 最初の hiapi リクエストをエンドツーエンドで完了します。
- HeyGen Avatar IV API チュートリアル —— もう1つの写真からトーキング動画へのモデルで、リップシンク手法の比較に使用できます。
- HeyGen Avatar V —— 音声ファイルがない場合に、スクリプト駆動(テキストから動画)のデジタルヒューマンを使用できます。
よくある質問
音声ファイルではなくテキストで omnihuman-1.5 を駆動できますか?
いいえ。audio_url は必須で、モデルはその音声にリップシンクします。スクリプトから動画へのフローが必要な場合は、先に音声を合成する(任意の TTS)か、heygen-avatar-v のようなテキスト駆動型デジタルヒューマンを使用し、その後、音声 URL をここに渡してください。
出力動画はどのくらいの長さですか?
音声クリップに従います。duration パラメータはありません。12秒の音声トラックはおよそ12秒の動画を生成します。
どのような画像が最適ですか? 公開 URL 上にある、明瞭な照明の正面向きの単一人物のポートレートです。集合写真や大きく隠れた顔は、リップシンクの品質が低下します。
720p か 1080p か?
どちらも resolution に使用できます。反復作業中は 720p から始め、最終レンダリング時に 1080p に切り替えてください。高解像度ほど1秒あたりのコストが高くなります。pricing を参照してください。
タスクがすぐに status: "fail" を返します。なぜですか?
ほぼ常に、サーバーが入力 URL のいずれかを取得できないことが原因です。image_url と audio_url が公開アクセス可能(シークレットウィンドウで開く)で、有効期限切れでないことを確認してください。data.error メッセージが原因の特定に役立ちます。
ポーリングは必要ですか、それとも webhook を使用できますか?
どちらも可能です。シンプルなスクリプトでは GET /v1/tasks/{id} でポーリングできます。本番環境では callback.url を登録し、when を "final" に設定すれば、ポーリングループを維持する必要がありません。
関連記事
すべての記事を見る →-
チュートリアル
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 チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする