Tutorial
So nutzt du kling-4.0/text-to-video über die HiAPI-API: curl, Python und ein lauffähiges Anforderungsbeispiel
Ein praxisnaher Leitfaden für Entwickler: filmische Prompts, synchrones Audio, asynchrones Polling und Download der Ausgabe
Funktionen und Einsatzszenarien von kling-4.0/text-to-video
kling-4.0/text-to-video ist ein generatives Videomodell, das über die einheitliche HiAPI-API bereitgestellt wird. Du gibst ihm einen Text-Prompt, und es liefert einen Videoclip zurück – Bewegung, Kameraführung und Szenenkomposition werden vollständig durch deine Beschreibung bestimmt. Es handelt sich um einen Text-zu-Video-Endpunkt: Es gibt kein Quellbild, das animiert werden müsste, daher hat das Modell volle Kontrolle über Bildausschnitt und Erscheinungsbild des Motivs.
Einsatzszenarien:
- Du möchtest anhand eines Skripts oder einer Prompt-Vorlage kurze filmische Clips erzeugen – B-Roll, Trailer, Concept Boards, Social-Media-Videos.
- Du möchtest, dass synchrones Audio zusammen mit dem Video generiert wird, statt eine stumme Datei zu erhalten, die nachträglich vertont werden muss.
- Du baust eine Pipeline, in der die Videogenerierung nur einer von vielen Schritten ist (Skripterstellung, Materialvorbereitung, Veröffentlichung), weshalb du eine HTTP-API statt einer Weboberfläche benötigst.
Wenn du jedoch eine frame-genaue Kontrolle über ein konkretes reales Motiv benötigst (Bild-zu-Video- oder Bearbeitungsmodelle eignen sich dafür besser) oder wenn du eine synchrone Antwort innerhalb der Nutzeranfrage brauchst, ist dieses Modell weniger geeignet – die Videogenerierung dauert, daher ist dieser Endpunkt konstruktionsbedingt asynchron.
Da alle Anfragen über HiAPI laufen, sind Anmeldedaten, Request-/Response-Format und Task-Lebenszyklus unabhängig vom jeweiligen Modell auf der Plattform identisch. Diese Konsistenz ist der praktische Grund, darauf aufzubauen: Das spätere Hinzufügen oder Austauschen von Modellen erfordert keine Neufassung der Authentifizierungs- oder Polling-Schicht.
Voraussetzungen und Authentifizierung auf HiAPI
Bevor du die erste Anfrage sendest, stelle sicher, dass du Folgendes hast:
- Ein HiAPI-Konto und einen Projekt-API-Schlüssel. Behandle ihn als geheim – committe ihn niemals in ein Repository und platziere ihn niemals im Client-Code.
- Den HTTP-Client deiner Wahl. Die folgenden Beispiele verwenden
curlund Python 3 mitrequests. - Den Modellbezeichner exakt wie im Katalog:
kling-4.0/text-to-video. Ein Tippfehler im Modellnamen ist die häufigste Ursache für einen fehlgeschlagenen ersten Aufruf.
Die Anmeldedaten werden bei jeder Anfrage (auch bei Polling-Anfragen) als HTTP-Header gesendet. Das übliche Muster auf HiAPI ist ein Bearer-Token:
export HIAPI_API_KEY="your-api-key-here"
Dann in der Anfrage:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
Speichere Basis-URL und Schlüssel in Umgebungsvariablen oder einem Secret-Manager, nicht fest im Code. Für die lokale Entwicklung genügen eine .env-Datei und ein os.environ-Zugriff in Python. Für bereitgestellte Dienste injiziere die Secrets zur Laufzeit.
Eine Gewohnheit, die sich früh lohnt: Baue zunächst einen winzigen „Wer bin ich“-artigen Aufruf – eine beliebige leichtgewichtige authentifizierte Anfrage –, um Schlüssel und Basis-URL zu bestätigen, bevor du Video-Tasks debuggst. Die Trennung von Authentifizierung und Modelllogik spart später Zeit.
Eine lauffähige curl-Anfrage
Der minimale Aufruf erstellt einen Task und gibt die Task-Kennung zurück. Die Struktur sieht so aus:
curl -X POST "$HIAPI_BASE_URL/video/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-4.0/text-to-video",
"prompt": "A slow aerial push over a rain-soaked Tokyo alley at night, neon signs reflecting in puddles, steam rising from vents, shallow depth of field, cinematic color grading",
"generate_audio": true
}'
Feldweise Erläuterung des Request-Bodys:
model— der Modellbezeichner. Erforderlich.prompt— deine Szenenbeschreibung. Hier steckt der größte Teil deines Qualitätsbudgets; siehe den Abschnitt zu Prompts.generate_audio— fordert die Generierung synchronen Audios zusammen mit dem Video an. Wenn du nur die Bildspur benötigst, kannst du es weglassen oder auf false setzen.
Die Antwort ist ein Task-Objekt, nicht das fertige Video. Erwarte ein Statusfeld und eine id, die du zum Polling verwendest – zum Beispiel den Status queued oder processing plus eine Task-id. Speichere diese id sofort; falls dein Prozess beendet wird, ist die id dein einziger Beleg für die laufende Arbeit.
Zwei praktische Hinweise. Erstens: Wenn die Prompts länger werden, speichere das JSON in einer Datei und verwende -d @payload.json – die Shell-Quotierung mehrzeiliger Prompts ist eine häufige Fehlerquelle. Zweitens: Erfasse Antwortkörper und HTTP-Statuscode getrennt (curl -s -w "\n%{http_code}"), um abgelehnte Anfragen von Netzwerkfehlern unterscheiden zu können.
Die Anfrage in Python umsetzen
Dieselbe Anfrage in Python, so strukturiert, dass sie sich direkt in ein echtes Skript übernehmen lässt:
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
API_KEY = os.environ["HIAPI_API_KEY"]
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def create_video_job(prompt: str, generate_audio: bool = True) -> dict:
payload = {
"model": "kling-4.0/text-to-video",
"prompt": prompt,
"generate_audio": generate_audio,
}
resp = requests.post(
f"{BASE_URL}/video/generations",
headers=HEADERS,
json=payload,
timeout=30,
)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
job = create_video_job(
"A slow aerial push over a rain-soaked Tokyo alley at night, "
"neon signs reflecting in puddles, steam rising from vents, "
"shallow depth of field, cinematic color grading"
)
print(job)
Warum das so geschrieben ist:
requests.post(..., json=payload)übernimmt Serialisierung und Content-Type in einem, was ein manuellesjson.dumpserspart.raise_for_status()wandelt 4xx/5xx in fangbare Exceptions um, statt einen Fehler-Response-Body stillschweigend als Task zu interpretieren.timeoutist Pflicht. Ohne ihn blockiert eine hängende Verbindung den Worker unbegrenzt.- Die Konfiguration liegt in modulweiten Konstanten, die aus der Umgebung gelesen werden, sodass die Funktion testbar und wiederverwendbar ist.
Diese Funktion erstellt nur den Task. Sie gibt sofort das Task-Handle zurück – genau das, was du in einem Web-Handler oder Queue-Worker möchtest. Die folgenden Abschnitte beschreiben, wie du auf das Ergebnis wartest.
Filmische Prompts schreiben, die überzeugen
Text-zu-Video-Modelle belohnen Struktur. Ein Prompt, der Motiv, Kamera, Bewegung und Stimmung benennt, ist einem Ein-Satz-Idee-Prompt stets überlegen, weil jedes Element eine Mehrdeutigkeit auflöst, die das Modell sonst zufällig entscheiden würde.
Eine brauchbare Vorlage:
[Motiv und Szene], [Kameraposition und Bewegung],
[Bewegung im Bild], [Beleuchtung], [Atmosphäre oder Farbgrading], [Stilreferenz]
Anwendungsbeispiel:
Im Morgengrauen überquert ein einsamer Radfahrer im gelben Regenmantel eine Steinbrücke, eine niedrige Kameraposition folgt ihm parallel auf Radhöhe, Nebel zieht über das Wasser, weiches Blaue-Stunde-Licht mit warmen Laternenakzenten, ruhig und leicht melancholisch, anamorphotischer Breitbild-Look.
Die Aufgabe der einzelnen Teile:
- Motiv und Szene — konkrete Substantive statt abstrakter Konzepte. „Ein einsamer Radfahrer im gelben Regenmantel“ gibt dem Modell etwas Darstellbares; „Freiheit“ nicht.
- Kamera — Position (
niedrige Kameraposition,Luftaufnahme,auf Augenhöhe) und Bewegung (Mitführung,langsames Heranfahren,statisch) sind der stärkste Hebel für den wahrgenommenen Produktionswert. - Bewegung im Bild — Nebel zieht, Stoff weht, Wasser kräuselt sich. Video braucht Bewegung; benenne sie ausdrücklich.
- Beleuchtung und Atmosphäre — Tageszeit, Farbtemperatur, emotionale Grundstimmung. Halte sie untereinander stimmig.
- Stil — Sprache zu Objektiv oder Format (
anamorphotisch,geringe Schärfentiefe,filmisches Farbgrading) prägt die Textur zuverlässiger als die Angabe einer Regieperson.
Halte den Prompt als dichte Beschreibung von ein paar Sätzen, nicht als Absatz konkurrierender Ideen. Wenn eine Einstellung zwei völlig verschiedene Aktionen braucht, generiere zwei Clips. Und iteriere: Ändere jeweils nur eine Variable – zuerst die Kamera, dann die Beleuchtung –, damit du erfährst, worauf das Modell reagiert, statt zu raten.
Asynchrone Tasks und Polling behandeln
Die Videogenerierung ist nicht sofort fertig, daher lautet das Muster zuerst erstellen, dann pollen. Den Erstellungsteil hast du bereits; hier die Schleife:
import time
def wait_for_job(job_id: str, timeout: int = 600) -> dict:
deadline = time.monotonic() + timeout
delay = 2.0
while time.monotonic() < deadline:
resp = requests.get(
f"{BASE_URL}/video/generations/{job_id}",
headers=HEADERS,
timeout=30,
)
resp.raise_for_status()
job = resp.json()
status = job.get("status")
if status == "succeeded":
return job
if status in ("failed", "cancelled"):
raise RuntimeError(f"Job {job_id} ended with status {status}: {job}")
time.sleep(delay)
delay = min(delay * 1.5, 15.0) # back off, cap at 15s
raise TimeoutError(f"Job {job_id} did not finish in {timeout}s")
Wichtige Designentscheidungen für den Produktivbetrieb:
Mit Backoff pollen statt in einer engen Schleife
Beginne mit kurzen Intervallen und erhöhe sie schrittweise – der obige exponentielle Backoff endet bei einer festen Obergrenze. Ständiges schnelles Polling verbraucht dein Ratenlimit ohne Nutzen, denn die Generierungszeit verkürzt sich nicht, wenn du früher fragst.
Immer eine Deadline setzen
Jede Polling-Schleife braucht eine maximale Wall-Clock-Zeit und einen klaren Fehler bei Überschreitung. Andernfalls belegt ein hängender Task still und dauerhaft einen Worker.
Endzustände als endgültig behandeln
Unterscheide laufende Zustände (queued, processing) von Endzuständen (succeeded, failed, cancelled). Nur bei Erfolg gibst du die Ausgabe zurück; bei anderen Zuständen solltest du eine Exception werfen oder in einen Retry-Pfad wechseln, statt weiter zu schleifen.
Polling vom Request-Handler entkoppeln
Lass in einem Webserver die HTTP-Antwort nicht blockierend auf das Video warten. Erstelle den Task, gib die id an den Client zurück und polle aus einem Hintergrund-Worker oder einem Queue-Consumer. Persistiere die Task-id und ihren zuletzt bekannten Status, damit nach einem Neustart die Verfolgung laufender Arbeit nicht verloren geht.
Ausgabe herunterladen und prüfen
Wenn ein Task succeeded erreicht, enthält die Antwort einen Verweis auf das generierte Medium – üblicherweise eine URL zu einer fertigen Datei. Lade sie zeitnah herunter und behandle die URL als temporär: Hole sie, speichere sie und merke dir deinen eigenen dauerhaften Speicherort, statt die Provider-URL direkt an Endnutzer weiterzugeben.
import pathlib
def download_output(job: dict, dest: pathlib.Path) -> pathlib.Path:
url = job["output"]["video_url"]
with requests.get(url, stream=True, timeout=120) as r:
r.raise_for_status()
dest.parent.mkdir(parents=True, exist_ok=True)
with open(dest, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 20):
f.write(chunk)
return dest
Prüfschritte, die sich lohnen, bevor du die Datei an jemanden weitergibst:
- Prüfe, ob die Übertragung abgeschlossen ist. Streame in Chunks, vergleiche die geschriebene Größe mit
Content-Length(falls vorhanden) und scheitere lautstark bei einem zu kurzen Lesen. - Bestätige die Tonspur. Wenn du
generate_audioangefordert hast, sollte die Datei einen Audiostream haben. Eine schnelle Prüfung mitffprobeist der günstigste Test:
ffprobe -v error -show_entries stream=codec_type -of csv=p=0 output.mp4
Du solltest sowohl eine video- als auch eine audio-Zeile sehen. Fehlt das Audio, prüfe erneut, ob das Flag beim Erstellungs-Aufruf gesetzt war – nachträglich lässt es sich nicht hinzufügen.
- Führe eine grundlegende Prüfung von Dauer und Auflösung gegenüber deinen Erwartungen durch, um abgeschnittene oder falsch spezifizierte Renderings vor der Veröffentlichung zu erkennen.
- Speichere mit deterministischem Schlüssel (Task-id plus Hash), schreibe zuerst in einen temporären Pfad, benenne nach Erfolg um und bewahre die Task-id zusammen mit dem Asset zur Nachverfolgung auf.
Wenn ein Download mitten in der Übertragung fehlschlägt, versuche es mit Backoff erneut; wenn die URL abgelaufen ist, musst du den Task-Datensatz erneut abrufen, um einen neuen Verweis zu erhalten.
Als wiederverwendbaren Client kapseln
Die obigen Teile bilden auf natürliche Weise eine Klasse. Fügst du sie zusammen, erhältst du etwas, das du projektübergreifend importieren kannst, ohne zu kopieren:
class KlingTextToVideo:
def __init__(self, base_url: str, api_key: str):
self.base_url = base_url.rstrip("/")
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
def generate(self, prompt: str, generate_audio: bool = True,
timeout: int = 600) -> dict:
job = create_video_job(prompt, generate_audio) # create half
return wait_for_job(job["id"], timeout=timeout) # poll half
Wenn der Client reift, kommen einige Dinge hinzu:
- Strukturierte Logs mit der Task-id als Schlüssel – Zustandsübergänge, Anzahl der Polls, verstrichene Zeit und Fehler. Wenn ein Rendering auffällig ist, ist die Task-id dein Korrelationsschlüssel zwischen den Logs.
- Begrenzte Retries nur bei transienten Fehlern (Netzwerk, 5xx). Wiederhole abgelehnte Anfragen niemals blind; ein fehlerhafter Request-Body schlägt jedes Mal auf dieselbe Weise fehl und verschwendet nur Kontingent.
- Idempotenz in deiner Schicht implementieren. Wenn dein Dienst denselben Prompt zweimal übermitteln könnte, dedupliziere vor dem Aufruf der Erstellung, statt für zwei Tasks zu zahlen.
- Prompt-Vorlagen als Daten statt als Code. Lege die filmischen Vorlagen in Konfigurationsdateien ab, sodass Prompt-Iterationen keine Deployments erfordern.
- Kosten nach Ausgabesekunden abrechnen. Die Abrechnung basiert auf dem generierten Ausgabevolumen, daher ermöglicht die Verfolgung der pro Task generierten Dauer, Ausgaben einem Feature oder Nutzer zuzuordnen.
Sobald der Client fertig ist, ist die Pipeline kurz: Prompt aus der Vorlage bauen, generate aufrufen, Ausgabe herunterladen und prüfen und dann die gespeicherte Datei an deine Anwendung übergeben. Wenn du später weitere Modelle auf HiAPI hinzufügst, gelten dieselben Auth-Header, derselbe Task-Lebenszyklus und dasselbe Download-Muster – das ist das Hauptargument dafür, die Abstraktionsschicht nur einmal zu bauen.
Ähnliche Artikel
Alle Artikel ansehen →-
Tutorial
So rufen Sie hailuo-2.3-fast/image-to-video über die HiAPI API auf: curl und Python in der Praxis
Die erste lauffähige Anfrage für die schnelle, kostengünstige Bild-zu-Video-Stufe – von der Modell-ID bis zum heruntergeladenen MP4
-
Tutorial
So rufen Sie hailuo-2.3/text-to-video über die HiAPI API auf: curl, Python und lauffähige Anfragebeispiele
-
Tutorial
Kandinsky 6.0 Pro Text-zu-Video auf HiAPI: curl- und Python-Tutorial
Eine anfrageorientierte praktische Demonstration: Aufbau des Aufrufs vom Prompt zum Videoclip, Absenden der Anfrage, Abfragen des Fertigstellungsstatus und Herunterladen des Ergebnisses