HiAPI
Blog

Tutorial

So verwendest du die vidu-q4-preview Reference-to-Video-API (curl + Python)

Oct 19, 2026
So verwendest du die vidu-q4-preview Reference-to-Video-API (curl + Python)

Was du baust

Du startest einen Reference-to-Video-Aufruf über die asynchrone /v1/tasks-API von hiapi und führst mehrere Referenz-Standbilder – sowie optional Audioclips – zu einer 3–16 Sekunden langen Szene mit bis zu 4K zusammen. Du reichst lediglich einen POST ein, pollst dann (oder empfängst einen Callback), bis der Task abgeschlossen ist, und lädst anschließend das MP4 herunter.

Hole dir zuerst deinen Schlüssel aus der hiapi-Konsole; jede Anfrage unten verwendet Authorization: Bearer sk-<your-key>.

Reference-to-Video vs. Image-to-Video. Dieser Endpoint führt 1–15 Standbilder zusammen – übergib ein Personen-Standbild, ein Szenen-Standbild und ein Requisiten-Standbild, und er verschmilzt sie zu einer Einstellung. Wenn du nur ein einzelnes Startbild animieren möchtest, verwende stattdessen vidu-q4-preview/image-to-video; es akzeptiert ein einzelnes image_url und lehnt reference_image_urls ab.

Minimale lauffähige Anfrage (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": "Die Person aus Referenzbild 1 geht an einem Café aus Referenzbild 2 vorbei, warmes Morgenlicht, langsame Kamerafahrt nach vorn",
      "reference_image_urls": [
        "https://your-cdn.com/person.jpg",
        "https://your-cdn.com/cafe.jpg"
      ],
      "resolution": "1080p",
      "duration": 5,
      "aspect_ratio": "16:9"
    }
  }'

Dieser POST gibt eine Task-ID zurück, nicht das Video:

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

Polle GET /v1/tasks/<taskId>, bis data.status gleich success ist, und lies dann das MP4 aus data.output[0].url:

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 }
    ]
  }
}

Die Ausgabe-URL ist temporär – sie hat ein expireAt (läuft nach einigen Tagen ab) –, also lade die Bytes sofort herunter und verwende kein Hotlinking.

Python: übermitteln → pollen → herunterladen

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": (
                "Die Person aus Referenzbild 1 geht an einem Café aus Referenzbild 2 vorbei, "
                "warmes Morgenlicht, langsame Kamerafahrt nach vorn"
            ),
            "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-Fehler landen hier
    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")

Eines musst du verinnerlichen: Ein fehlgeschlagenes Rendering wird weiterhin mit HTTP 200 zurückgegeben, der Grund steht in data.status: "fail" und data.error.code / data.error.message. Eine fehlgeschlagene Generierung ist kein HTTP-Fehler, also verzweige anhand des Response-Bodys und nicht anhand des Statuscodes.

Sprachreferenz hinzufügen

Das Sprachfeld heißt reference_audio_urls – ein Array mit bis zu 3 Audioclips. Das Audio legt die Klangfarbe fest; dein Prompt trägt weiterhin den Text und steuert die Lippensynchronisation.

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": {
    "prompt": "Der Moderator aus Referenzbild 1 sagt mit der Stimme von Referenzaudio 1: 'Willkommen zurück auf dem Kanal.'",
    "reference_image_urls": ["https://your-cdn.com/presenter.jpg"],
    "reference_audio_urls": ["https://your-cdn.com/voice.mp3"],
    "resolution": "1080p",
    "duration": 8
  }
}

Fallensteller bei Feldnamen: Das naheliegende voice_reference_urls wird abgelehnt (der Validator erlaubt nur reference_audio_urls). Siehe die Prüftabelle unten.

Produktion: Callbacks und Idempotenz

Für Server-Workflows möchtest du in der Regel keine dauerhaft laufende Polling-Schleife. Hänge ein Top-Level-callback an (auf derselben Ebene wie input, nicht darin), und hiapi POSTet den abgeschlossenen Task an deine URL:

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": { "prompt": "...", "reference_image_urls": ["..."] },
  "callback": { "url": "https://your-app.com/hooks/vidu", "when": "final" }
}
  • when unterstützt nur "final" – du wirst genau einmal über den Endzustand (Erfolg oder Fehler) benachrichtigt, niemals über Zwischenfortschritt.
  • Der Callback-Body entspricht der Nutzlast, die von GET /v1/tasks/<id> zurückgegeben wird.
  • Zustellungen werden mehrfach wiederholt und können dupliziert werden, also dedupliziere nach taskId und mache deinen Handler idempotent.
  • Behalte Polling als Fallback bei, um Fenster abzudecken, in denen dein Endpoint kurzzeitig nicht erreichbar ist.

Speichere die taskId in dem Moment, in dem du sie erhältst. Wenn dein Poller auf einen temporären Netzwerkfehler stößt, polle die gespeicherte ID erneut – reiche niemals neu ein, sonst zahlst du für ein zweites Rendering.

Was ich verifiziert habe (Schema-Vertrag)

Ich habe den Live-Endpoint mit absichtlich ungültigen Werten geprüft (kostenlos – abgelehnte Anfragen werden nicht berechnet, und ungültige Werte erzeugen nie einen Task). Der Validator ist strikt und gibt ein flaches { "code": 400, "error_code": "INVALID_REQUEST", "message": ... } zurück:

Was du sendest Was zurückkommt
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
vier reference_audio_urls reference_audio_urls: maxItems: got 4, want 3
reference_image_urls weggelassen missing required field "reference_image_urls"

Damit ist die bestätigte Eingabestruktur:

Feld Erforderlich Werte
prompt Ja Text
reference_image_urls Ja 1–15 Bild-URLs
reference_audio_urls Nein bis zu 3 Audio-URLs (Sprachfeld)
resolution Nein 540p / 720p / 1080p / 2k / 4k
duration Nein Ganzzahl 3–16 (Sekunden)
aspect_ratio Nein 16:9 / 9:16 / 1:1 / 4:3 / 3:4

duration ist eine Ganzzahl (5), kein String – anders als bei einigen anderen Videomodellen auf hiapi, die "6" erwarten. Das Übergeben zusätzlicher Schlüssel ist ein harter Fehler (additional properties ... not allowed), also kopiere keine Felder aus dem Image-to-Video-Schema herüber.

Hinweise zur Ausgabeseite vor dem Download

  • Jeder Clip hat eine AAC-Tonspur, selbst wenn du keine reference_audio_urls gesendet hast. Klangbegriffe im Prompt steuern die Ambient-Tonspur, also gehe nicht davon aus, dass "keine Sprachreferenz = stumme Datei" bedeutet.
  • 4K-Ausgaben von Vidu Q4 Preview werden als HEVC/H.265 geliefert. Sie lassen sich in den meisten nativen Playern abspielen, aber viele Browser können H.265-MP4s nicht inline in einem <video>-Tag wiedergeben – wenn du es ins Web einbetten willst, kodiere es in H.264 um. Niedrigere Stufen liefern Standard-H.264.

Preview-Modell – behandle Enumerationen als Momentaufnahme

vidu-q4-preview/reference-to-video ist ein Preview-Modell: Es ist heute aufrufbar, aber nicht in /v1/models aufgeführt, und das Preview-Schema kann sich ändern. Führe vor der Massenverarbeitung die Prüfung mit ungültigen Werten (wie in der Tabelle oben) erneut aus, um zu bestätigen, dass die Enumerationen noch gültig sind. Maßgeblich sind die Regeln, die der Validator tatsächlich durchsetzt, plus die Modellseite.

Verwandt

Häufige Fragen

Sind Reference-to-Video und Image-to-Video dasselbe? Nein. Reference-to-Video führt 1–15 Standbilder (optional plus bis zu 3 Audioclips) zu einer zusammengesetzten Einstellung zusammen; Image-to-Video animiert ein einzelnes Startbild. Es sind eigenständige Endpoints mit unterschiedlichen Eingaben – Reference-to-Video lehnt sogar das image_url-Feld von Image-to-Video ab und umgekehrt.

Wie füge ich Sprache hinzu? Hänge reference_audio_urls an (bis zu 3 Clips) und weise im Prompt darauf hin ("… mit der Stimme von Referenzaudio 1"). Der Feldname muss genau reference_audio_urls lauten; voice_reference_urls und andere Namen werden abgelehnt.

Wie lang ist der längste Clip, den ich anfordern kann? 16 Sekunden. duration ist eine Ganzzahl von 3 bis 16.

Muss ich pollen? Nein – hänge callback: { "url": ..., "when": "final" } an und du erhältst eine Benachrichtigung im Endzustand. Dedupliziere nach taskId und behalte Polling als Fallback bei.

Was kostet ein 4K-Clip? Die Abrechnung erfolgt pro Sekunde, die Rate steigt mit der Auflösung, und 4K ist die höchste Stufe – siehe hiapi-Preise. Ein praktischer Workflow ist, zunächst in 720p zu iterieren und nur die endgültig behaltenen Versionen mit 4k neu zu rendern.

Ähnliche Artikel

Alle Artikel ansehen →

Starte mit persistenten KI-Artefakten

Hol dir deinen API-Key und rufe Bild-, Video- und Audiomodelle über eine einzige task-basierte API auf.

API-Dokumentation lesen