HiAPI
Blog

Tutorial

So verwendest du omnihuman-1.5 über die HiAPI API: curl- und Python-Tutorial

Vollständige Request-Übung, asynchrones Polling und Output-Download für die Audio-zu-Video-Digitalhuman-Generierung

Nov 3, 2026
深棕与燕麦色宽带交织的扁平编织纹理封面图,点缀克制黄铜色调,几何秩序感强

Funktionen und Einsatzszenarien der omnihuman-1.5 API

omnihuman-1.5 wandelt eine Audiospur plus ein Porträtbild in ein sprechendes Digitalhuman-Video um: Das Gesicht im Bild wird animiert, sodass Mund- und Kopfbewegungen der bereitgestellten Sprache folgen. Auf HiAPI wird das Modell als Audio-zu-Video-Endpunkt angeboten – du sendest Audio, ein Referenzbild und einige Generierungsparameter, die API gibt einen Job zurück, und du fragst diesen Job ab, bis das fertige Video vorliegt.

Warum die API gegenüber manuellen Tools überlegen ist

Browser-Tools eignen sich für einmalige Bearbeitungen. Wenn die Videogenerierung ein Glied in einem größeren System ist, ist die API die richtige Wahl:

  • Batch-Pipelines – Erzeuge große Mengen an Digitalhuman-Clips aus Skripten und Audiospur-Warteschlangen, ohne manuelles Eingreifen.
  • Produktfunktionen – In-App-Off-Voice, lokalisierte Onboarding-Videos oder personalisierte Nachrichten, bei denen jede Darstellung anderes Audio und ein anderes Porträt verwendet.
  • Backend-Automatisierung – Content-Workflows erzeugen Videos und übergeben sie anschließend an ein CMS, einen Storage-Bucket oder einen Delivery-Dienst.

Aufbau des Requests

Jeder omnihuman-1.5-Aufruf auf HiAPI folgt demselben Muster: ein POST reicht den Job ein, nachfolgende Requests prüfen seinen Status. Da das Rendering nicht sofort abgeschlossen ist, lautet das Integrationsmuster Einreichen → Pollen → Herunterladen und nicht Einreichen → Video in derselben Antwort erhalten. Der Rest dieses Tutorials baut diesen Ablauf zuerst mit curl auf und implementiert ihn dann in Python.

Voraussetzungen und deine HiAPI-Zugangsdaten

Bevor du den ersten Aufruf machst, bestätige drei Dinge.

1. Konto und API-Schlüssel

Du benötigst ein HiAPI-Konto und einen in der Konsole erstellten API-Schlüssel. Behandle den Schlüssel als geheim: nicht in die Versionsverwaltung, in Client-Code oder in Logs aufnehmen. Lade ihn in der Entwicklung aus einer Umgebungsvariable und in der Produktion aus dem Secret-Manager der Plattform.

export HIAPI_API_KEY="your-api-key-here"

2. Netzwerkzugriff und Request-Tools

Für curl reicht jede neuere Shell. Für die Python-Version brauchst du nur die requests-Bibliothek – kein herstellerspezifisches SDK, denn die API ist schlicht HTTPS mit JSON-Request-Body.

pip install requests

3. Vom Modell benötigte Eingaben

Halte vor dem Schreiben des Requests Folgendes bereit:

  • Audio – die Sprachspur, die die Mundanimation antreibt, bereitgestellt als URL, die die API lesen kann, oder als Referenz auf eine hochgeladene Datei, je nachdem, welche Eingabeformate der Endpunkt akzeptiert.
  • Porträtbild – das Gesicht, das animiert werden soll. Ein klares Frontalbild mit sichtbarem Mund liefert die vorhersehbarsten Ergebnisse.
  • Generierungsparameter – alle vom Modell angebotenen Auflösungs-, Dauer- oder Qualitätsoptionen. Sende nur die Felder, die du tatsächlich brauchst; für einen ersten Test sind die Standardwerte meist sinnvoll.

Jeder Request übergibt den Schlüssel im Authorization-Header in der Form Bearer <your-key>. Wenn der erste Aufruf 401 zurückgibt, prüfe zuerst diesen Header.

Request mit curl ausführen

Der Einreichungsaufruf ist ein POST mit JSON-Body. Der genaue Pfad und die Feldnamen von omnihuman-1.5 stehen auf der API-Referenzseite des Modells; die untenstehende Struktur zeigt die Aufrufform und die Felder, die du ausfüllst.

curl -X POST "https://api.hiapi.ai/v1/omnihuman-1.5/generate" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_url": "https://your-bucket.example.com/speech.mp3",
    "image_url": "https://your-bucket.example.com/portrait.jpg"
  }'

Feldweise Erklärung

  • Authorization – enthält den API-Schlüssel. Fehlt er, wird der Request abgelehnt, bevor irgendeine Arbeit beginnt.
  • Content-Type: application/json – der Body ist JSON; ein fehlender Header ist eine häufige Ursache für verwirrende Validierungsfehler.
  • audio_url – die Sprachspur. Verwende eine öffentlich lesbare oder anderweitig für die API erreichbare URL und bevorzuge stabile Speicherorte gegenüber signierten Links, die mitten im Rendering ablaufen.
  • image_url – das zu animierende Porträt. Es gelten dieselben Erreichbarkeitsregeln.

Was zurückgegeben wird

Eine erfolgreiche Einreichung liefert kein Video, sondern ein Job-Objekt mit einer Kennung (üblicherweise im Feld id) und einem Status wie queued oder processing. Speichere diese Kennung; sie ist der Handle für jede spätere Statusprüfung.

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

Du kannst eine erfolgreiche Einreichung bestätigen, indem du den HTTP-Statuscode prüfst und ob die Job-Kennung vorhanden ist. Enthält die Antwort Validierungsmeldungen, verweisen sie auf das fehlerhafte Feld – meist eine fehlende oder fehlerhaft formatierte URL.

Denselben Request in Python implementieren

Der curl-Aufruf lässt sich direkt nach Python übertragen. Die folgende Version ist für den direkten Einsatz in einem Dienst gedacht: Der Schlüssel kommt aus einer Umgebungsvariable, der Payload ist ein dynamisch aufbaubares Dictionary, und Fehler werden geworfen statt verschluckt.

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"

HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

def submit_omnihuman_job(audio_url: str, image_url: str, **options) -> str:
    payload = {
        "audio_url": audio_url,
        "image_url": image_url,
    }
    payload.update(options)

    response = requests.post(
        f"{BASE_URL}/omnihuman-1.5/generate",
        headers=HEADERS,
        json=payload,
        timeout=60,
    )
    response.raise_for_status()

    data = response.json()
    return data["id"]

Warum diese Schreibweise

  • json=payload lässt requests den Body serialisieren und den Content-Type setzen, sodass du den JSON-Header nicht vergessen kannst.
  • **options hält die Funktion flexibel: Generierungsparameter werden als Keyword-Argumente übergeben, ohne das Payload-Literal zu ändern.
  • timeout=60 verhindert, dass hängende Verbindungen einen Worker-Prozess unbegrenzt blockieren. Die Einreichung ist ein schneller Aufruf; langes Warten gehört in den Polling-Schritt, nicht hierhin.
  • raise_for_status() verwandelt Nicht-2xx-Antworten in abfangbare und protokollierbare Exceptions, wobei der Response-Body zur Diagnose verfügbar bleibt.

Behalte die zurückgegebene Job-Kennung und übergib sie an die Polling-Hilfsfunktion – diese wird im nächsten Abschnitt aufgebaut.

Den asynchronen Lebenszyklus behandeln: Pollen bis zur Fertigstellung

Die Videogenerierung dauert Zeit, daher ist die API bewusst asynchron. Nach der Einreichung fragst du wiederholt den Job-Status ab, bis ein Endzustand erreicht ist.

Polling-Schleife

import time

def wait_for_job(job_id: str, interval: int = 5, max_wait: int = 600) -> dict:
    waited = 0
    while waited < max_wait:
        response = requests.get(
            f"{BASE_URL}/omnihuman-1.5/jobs/{job_id}",
            headers=HEADERS,
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()
        status = job["status"]

        if status == "succeeded" or status == "completed":
            return job
        if status == "failed" or status == "error":
            raise RuntimeError(f"Job {job_id} failed: {job}")

        time.sleep(interval)
        waited += interval

    raise TimeoutError(f"Job {job_id} did not finish within {max_wait}s")

Festlegen, wann gestoppt wird

Drei Ergebnisse beenden die Schleife, und dein Code muss jedes davon behandeln:

  • Erfolg – der Job meldet einen Abschlussstatus und enthält einen Verweis auf das Ausgabevideo. Schleife verlassen und mit dem Download fortfahren.
  • Fehlschlag – der Job meldet einen Fehlerstatus. Nicht blind wiederholen; prüfe zuerst die Fehlermeldung, denn Fehlschläge werden meist durch nicht lesbare Eingabe-URLs oder nicht unterstütztes Audio verursacht.
  • Timeout – deine eigene Obergrenze der Laufzeit ist erreicht. Behandle dies anders als einen Fehlschlag: Der Job könnte serverseitig noch abgeschlossen werden, also entscheide bewusst, ob du weiter pollst, das Zeitfenster verlängerst oder aufgibst.

Polling-Etikette

Verwende ein angemessenes Intervall statt einer engen Schleife. Bei Videorendering reichen einige Sekunden zwischen den Prüfungen und halten das Request-Volumen vorhersagbar. Bei erwartetem langem Warten in der Warteschlange erhöhe schrittweise das Intervall und setze immer eine Obergrenze, damit ein hängender Worker-Prozess nicht ewig pollt. In der Produktion bevorzuge einen Hintergrund-Worker oder eine Task-Queue, statt innerhalb eines Web-Request-Handlers zu pollen.

Das Ausgabevideo herunterladen und speichern

Wenn das Polling einen abgeschlossenen Job zurückgibt, enthält die Antwort einen Video-Verweis – meist ein URL-Feld innerhalb eines Ergebnisobjekts. Rufe ihn ab und speichere ihn dauerhaft in deinem eigenen Storage, statt dich langfristig auf den Link zu verlassen.

def download_video(job: dict, destination: str) -> None:
    video_url = job.get("output_url") or job.get("result", {}).get("video_url")
    if not video_url:
        raise ValueError(f"No video reference in job payload: {job}")

    with requests.get(video_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        with open(destination, "wb") as file:
            for chunk in response.iter_content(chunk_size=8192):
                file.write(chunk)

Hinweise, die Debugging-Zeit sparen

  • Streaming-Download. Videos sind groß; das schreibweiseweise Schreiben vermeidet es, die gesamte Datei in den Speicher zu laden, was bei speicherbeschränkten Worker-Prozessen wichtig ist.
  • Deterministische Dateinamen. Leite sie aus der Job-Kennung plus Zeitstempel ab, damit Läufe nachvollziehbar sind und erneute Läufe nicht kollidieren.
  • Erst in eine temporäre Datei laden, dann verschieben. Schreibe in einen temporären Pfad und benenne nach Abschluss um, sodass Teil-Downloads nie für vollständige Dateien gehalten werden.
  • Die zurückgegebene URL als temporär betrachten. Kopiere die Bytes in deinen eigenen Bucket oder dein Dateisystem und protokolliere die Job-Kennung zusammen mit dem gespeicherten Objekt für spätere Nachschläge.
  • Vor dem Erfolgsmarkieren validieren. Bevor du den Job in der Datenbank als abgeschlossen markierst, prüfe, dass die heruntergeladene Datei nicht leer und ihre Größe plausibel ist.

Häufige Request- und Polling-Fehler beheben

Die meisten Integrationsprobleme lassen sich in einige Kategorien einordnen. Arbeite sie der Reihe nach ab.

Authentifizierungs- und Request-Fehler

  • 401 Unauthorized – Schlüssel fehlt, ist fehlerhaft formatiert oder wird nicht als Bearer-Token gesendet. Prüfe den Header genau, einschließlich des Leerzeichens nach Bearer.
  • 403 – der Schlüssel ist gültig, hat aber keinen Zugriff auf diesen Endpunkt; bestätige, dass der Schlüssel zum vorgesehenen Projekt gehört.
  • 422 / 400 Validierungsfehler – lies die Meldung. Häufige Ursachen sind fehlende audio_url, fehlende image_url, nicht lesbare URLs oder nicht unterstützte Audioformate.
  • Unerwartetes HTML in der Antwort – du hast den falschen Host oder Pfad angesprochen. Verifiziere die Basis-URL anhand der API-Referenz, statt sie aus dem Gedächtnis zu rekonstruieren.

Jobs schlagen fehl oder werden nie fertig

  • Die API kann die Eingabe-URL nicht erreichen – ein im Browser funktionierender Link kann durch privates Netzwerk, abgelaufene Signaturen oder Hotlink-Schutz blockiert werden. Teste zuerst mit einer stabilen öffentlichen URL.
  • Audio und Bild passen nicht zusammen – stumme, sehr lange oder in nicht unterstützten Formaten vorliegende Spuren können das Rendering zum Stocken bringen oder scheitern lassen. Validiere die Pipeline zuerst mit einem kurzen Clip in einem Standardformat.
  • Zu häufiges Pollen – eine enge Schleife kann Rate-Limits auslösen und Fehler erzeugen, die wie Job-Fehlschläge aussehen. Verlangsame und führe Backoff ein.
  • Zu kurze Polling-Dauer – einen in der Warteschlange befindlichen Job nach wenigen Sekunden aufzugeben, erzeugt falsche Timeouts. Setze eine realistische maximale Wartezeit und protokolliere den zuletzt gesehenen Status vor dem Abbruch.
  • Endzustände nicht behandelt – wenn die Schleife nur Erfolg prüft, läuft sie bei Fehlschlägen bis zum Timeout im Leerlauf. Verzweige explizit auf Fehlerstatus.

Minimaler Validierungs-Workflow

Wenn etwas nicht funktioniert, reduziere auf den kleinsten Test: ein kurzes Audioclip, ein kleines Porträt, eine Einreichung und eine Statusprüfung nach einigen Sekunden. Klappt das, liegt der Fehler in deinem Payload, deiner Polling-Logik oder im Hosting der Eingaben – nicht im API-Aufruf selbst.

Ä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