HiAPI
ブログ

チュートリアル

vidu-q4-preview リファレンス動画生成 API の使い方(curl + Python)

Oct 19, 2026
vidu-q4-preview リファレンス動画生成 API の使い方(curl + Python)

構築するもの

hiapi の非同期 /v1/tasks API 上でリファレンス動画生成を 1 回呼び出し、複数の参照静止画——さらに任意で音声クリップ——を融合して 3〜16 秒、最大 4K の映像を生成します。POST を 1 回送信し、タスクが完了するまでポーリング(またはコールバック受信)してから MP4 をダウンロードするだけです。

まず hiapi コンソールでキーを取得してください。以下の各リクエストは Authorization: Bearer sk-<your-key> を使用します。

リファレンス動画生成 vs 画像からの動画生成。 このエンドポイントは1〜15 枚の静止画を融合します——人物の静止画を 1 枚、風景の静止画を 1 枚、小道具の静止画を 1 枚渡せば、それらを 1 つのショットに合成します。動かしたい最初のフレームが 1 枚だけの場合は、代わりに vidu-q4-preview/image-to-video を使用してください。こちらは単一の image_url を受け取り、reference_image_urls を拒否します。

最小構成の実行可能なリクエスト(curl)

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vidu-q4-preview/reference-to-video",
    "input": {
      "prompt": "参考画像 1 の人物が参考画像 2 のカフェを通り過ぎる。暖かな朝の光、ゆっくりとしたプッシュイン",
      "reference_image_urls": [
        "https://your-cdn.com/person.jpg",
        "https://your-cdn.com/cafe.jpg"
      ],
      "resolution": "1080p",
      "duration": 5,
      "aspect_ratio": "16:9"
    }
  }'

この POST は動画ではなくタスク id を返します:

{ "code": 200, "data": { "taskId": "task_abc123" } }

GET /v1/tasks/<taskId> を data.status が success になるまでポーリングし、data.output[0].url から MP4 を取得します:

curl https://api.hiapi.ai/v1/tasks/task_abc123 \
  -H "Authorization: Bearer sk-<your-key>"
{
  "code": 200,
  "data": {
    "status": "success",
    "output": [
      { "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1760000000 }
    ]
  }
}

出力 URL は一時的なものです——expireAt(数日後に期限切れ)が付いています——そのため、すぐにバイト内容をダウンロードし、ホットリンクしないでください。

Python:送信 → ポーリング → ダウンロード

import time
import requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {
    "Authorization": "Bearer sk-<your-key>",
    "Content-Type": "application/json",
}

def submit() -> str:
    payload = {
        "model": "vidu-q4-preview/reference-to-video",
        "input": {
            "prompt": (
                "参考画像 1 の人物が参考画像 2 のカフェを通り過ぎる。"
                "暖かな朝の光、ゆっくりとしたプッシュイン"
            ),
            "reference_image_urls": [
                "https://your-cdn.com/person.jpg",
                "https://your-cdn.com/cafe.jpg",
            ],
            "resolution": "1080p",
            "duration": 5,
            "aspect_ratio": "16:9",
        },
    }
    r = requests.post(BASE, json=payload, headers=HEADERS, timeout=60)
    r.raise_for_status()
    body = r.json()
    task_id = (body.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"submit rejected: {body}")  # 400 エラーはここに到達します
    return task_id

def wait(task_id: str, timeout_s: int = 600, interval: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=40)
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"task failed: {task.get('error')}")
        time.sleep(interval)
    raise TimeoutError(task_id)

def download(url: str, path: str) -> None:
    with requests.get(url, stream=True, timeout=120) as r:
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 16):
                f.write(chunk)

task_id = submit()
url = wait(task_id)
download(url, "out.mp4")

1 つ内面化すべき点:失敗したレンダリングも HTTP 200 で返り、理由は data.status: "fail" と data.error.code / data.error.message に含まれます。生成失敗は HTTP エラーではないため、ステータスコードではなくレスポンスボディに基づいて分岐してください。

音声リファレンスを追加する

音声フィールドは reference_audio_urls——最大 3 つの音声クリップからなる配列です。音声は声質を設定します。プロンプトは依然としてテキストを担い、リップシンクを駆動します。

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": {
    "prompt": "参考画像 1 の配信者が参考音声 1 の声で言う:『チャンネルへおかえりなさい。』",
    "reference_image_urls": ["https://your-cdn.com/presenter.jpg"],
    "reference_audio_urls": ["https://your-cdn.com/voice.mp3"],
    "resolution": "1080p",
    "duration": 8
  }
}

フィールド名の落とし穴:直感的な voice_reference_urls は拒否されます(バリデータは reference_audio_urls のみを許可します)。下のプローブ表を参照してください。

本番環境:コールバックと冪等性

サーバーワークフローでは、通常、ポーリングループを保持し続けたくありません。トップレベルの callback(input と同じ階層で、その内部ではない)を付加すると、hiapi は完了したタスクをあなたの URL に POST します:

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": { "prompt": "...", "reference_image_urls": ["..."] },
  "callback": { "url": "https://your-app.com/hooks/vidu", "when": "final" }
}
  • when は "final" のみをサポートします——終端状態(成功または失敗)での通知を 1 回だけ受け取り、中間の進捗通知は決して受け取りません。
  • コールバックボディは GET /v1/tasks/<id> が返すペイロードと同じです。
  • 配信は数回リトライされ、重複する可能性があるため、taskId で重複排除し、ハンドラを冪等にしてください。
  • あなたのエンドポイントが一時的に到達不能な時間帯をカバーするため、フォールバックとしてポーリングを維持してください。

taskId を取得した瞬間に保存してください。ポーラーが一時的なネットワークエラーに遭遇した場合、保存済みのid を再ポーリングしてください——決して再送信しないでください。さもないと 2 回目のレンダリングに対して課金されます。

私が検証したこと(スキーマ契約)

意図的に無効な値でライブエンドポイントをプローブしました(無料——拒否されたリクエストは課金されず、無効な値がタスクを作成することは決してありません)。バリデータは厳格で、フラットな { "code": 400, "error_code": "INVALID_REQUEST", "message": ... } を返します:

送信した内容 返された内容
resolution: "9999p" resolution: value must be one of '540p', '720p', '1080p', '2k', '4k'
duration: 999 duration: maximum: got 999, want 16
aspect_ratio: "banana" aspect_ratio: value must be one of '16:9', '9:16', '1:1', '4:3', '3:4'
voice_reference_urls: [...] additional properties 'voice_reference_urls' not allowed
reference_audio_urls を 4 つ reference_audio_urls: maxItems: got 4, want 3
reference_image_urls を省略 missing required field "reference_image_urls"

したがって確認された入力構造は次のとおりです:

フィールド 必須 値
prompt はい テキスト
reference_image_urls はい 1〜15 個の画像 URL
reference_audio_urls いいえ 最大 3 個の音声 URL(音声フィールド)
resolution いいえ 540p / 720p / 1080p / 2k / 4k
duration いいえ 整数 3〜16(秒)
aspect_ratio いいえ 16:9 / 9:16 / 1:1 / 4:3 / 3:4

duration は整数(5)であり、文字列ではありません——hiapi 上の他の一部の動画モデルは "6" を期待する点と異なります。追加のキーを渡すとハードエラーになります(additional properties ... not allowed)。そのため、画像からの動画生成スキーマからフィールドをコピーしてこないでください。

ダウンロードを実装する前の出力側の注意点

  • reference_audio_urls を送信しなかった場合でも、各クリップには AAC 音声トラックが付きます。 プロンプト内の音の語彙が環境音トラックを駆動するため、「音声リファレンスなし = 無音ファイル」と仮定しないでください。
  • Vidu Q4 Preview の 4K 出力は HEVC/H.265 で配信されます。 ほとんどのネイティブプレーヤーでは再生できますが、多くのブラウザは <video> タグ内で H.265 MP4 をインライン再生できません——Web に埋め込む場合は H.264 に再エンコードしてください。低いティアは標準の H.264 を返します。

プレビューモデル——列挙をスナップショットとして扱う

vidu-q4-preview/reference-to-video はプレビューモデルです:今日呼び出せますが、/v1/models にはリストされておらず、プレビュースキーマは変更される可能性があります。大量処理の前に、無効値プローブ(上の表など)を再度実行して列挙が依然として有効であることを確認してください。権威ある仕様は、バリデータが実際に適用するルールとモデルページです。

関連

よくある質問

リファレンス動画生成と画像からの動画生成は同じですか? いいえ。リファレンス動画生成は 1〜15 枚の静止画(任意で最大 3 つの音声クリップ)を融合して 1 つの合成ショットを作ります。画像からの動画生成は単一の最初のフレームを動かします。それらは独立したエンドポイントで、入力が異なります——リファレンス動画生成は画像からの動画生成の image_url フィールドを拒否し、逆もまた同様です。

音声はどう追加しますか? reference_audio_urls(最大 3 クリップ)を付加し、プロンプトで指定します(「……参考音声 1 の声で」)。フィールド名は正確に reference_audio_urls でなければなりません。voice_reference_urls その他の名前は拒否されます。

要求できる最長クリップは? 16 秒です。duration は 3〜16 の整数です。

ポーリングは必須ですか? いいえ——callback: { "url": ..., "when": "final" } を付加すれば、終端状態で通知を 1 回受け取れます。taskId で重複排除し、フォールバックとしてポーリングを維持してください。

4K クリップのコストはいくらですか? 秒単位の課金で、レートは解像度が上がるにつれて上昇し、4K が最上位です——hiapi の料金を参照してください。実用的なワークフローは、まず 720p で反復し、最終的に残すバージョンのみ 4k で再レンダリングすることです。

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

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

APIドキュメントを読む