Tutorial
PixVerse V6 Bild-zu-Video-API: direkt ausführbare curl- und Python-Beispiele
- Modell
- pixverse-v6
Um mit pixverse-v6/image-to-video auf hiapi ein statisches Bild zu animieren, genügt ein einziger POST /v1/tasks-Aufruf plus ein Polling – genau dasselbe asynchrone Aufgabenmuster, das alle generativen Modelle auf der Plattform verwenden. Der Unterschied zum Text-zu-Video-Endpunkt liegt in der Eingabe: Sie müssen ein Startbild (image_url) sowie einen Prompt angeben, der beschreibt, wie es sich bewegen soll. Dieser Leitfaden enthält direkt kopierbare curl- und Python-Beispiele, die Eingabefelder, die dieser Endpunkt tatsächlich validiert, sowie eine Überraschung, über die alle stolpern, die von Text-zu-Video kommen.
Was Sie vorbereiten müssen
- Einen hiapi-API-Schlüssel. Erstellen Sie ihn in der Konsole und senden Sie ihn über
Authorization: Bearer sk-<your-key>. Das Header-Format finden Sie in der Authentifizierungsdokumentation. - Die Modell-ID
pixverse-v6/image-to-video(der Schrägstrich bleibt erhalten – er gehört zur ID, nicht zum URL-Pfad). Dies ist eine andere Modell-ID alspixverse-v6/text-to-video. - Eine öffentlich erreichbare Bild-URL als erstes Frame. Die Plattform ruft das Bild serverseitig ab, daher funktionieren
localhost- oder Links zu privaten Buckets nicht – hosten Sie das Startbild an einem Ort, der für die API per GET erreichbar ist. - Mit curl müssen Sie nichts installieren. Für das Python-Beispiel benötigen Sie nur die Standardbibliothek plus
requests.
PixVerse V6 Bild-zu-Video verwendet Ihr statisches Bild als Startframe und animiert es zu einem Clip von 1–15 Sekunden. Es läuft über die einheitliche asynchrone Aufgaben-API – Sie reichen eine Aufgabe ein, fragen das Ergebnis ab und laden es herunter, bevor die Ausgabe-URL abläuft.
Minimal funktionierende Anfrage (curl)
Reichen Sie die Aufgabe bei POST /v1/tasks ein. image_url und prompt sind beide erforderlich:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "pixverse-v6/image-to-video",
"input": {
"image_url": "https://cdn.example.com/your-first-frame.jpg",
"prompt": "Langsamer Push-in; die Person dreht sich zur Kamera und lächelt, sanfte Brise im Haar",
"duration": 5,
"resolution": "720p"
}
}'
Die Antwort liefert eine Aufgaben-ID zurück:
{ "code": 200, "data": { "taskId": "a1b2c3d4-...." } }
Fragen Sie dann GET /v1/tasks/<taskId> ab, bis data.status gleich success ist:
curl -s https://api.hiapi.ai/v1/tasks/a1b2c3d4-.... \
-H "Authorization: Bearer sk-<your-key>"
Bei Erfolg befindet sich die URL des fertigen Videos in data.output[0].url:
{
"code": 200,
"data": {
"status": "success",
"output": [{ "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1760000000 }]
}
}
Diese Ausgabe-URL ist temporär – sie trägt einen expireAt-Zeitstempel. Laden Sie die .mp4 sofort herunter und speichern Sie sie in Ihrem eigenen Bucket; verlinken Sie sie nicht direkt per Hotlink.
Derselbe Ablauf in Python
import time, requests
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-<your-key>", "Content-Type": "application/json"}
def create_task():
payload = {
"model": "pixverse-v6/image-to-video",
"input": {
"image_url": "https://cdn.example.com/your-first-frame.jpg",
"prompt": "Langsamer Push-in; die Person dreht sich zur Kamera und lächelt",
"duration": 5,
"resolution": "720p",
},
}
r = requests.post(BASE, json=payload, headers=HEADERS, timeout=60)
r.raise_for_status()
data = r.json()
task_id = (data.get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError(f"create failed: {data}") # 400s echo the exact bad field
return task_id
def wait_for(task_id, timeout_s=600):
deadline = time.time() + timeout_s
while time.time() < deadline:
try:
r = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
task = (r.json().get("data") or {})
except requests.RequestException:
time.sleep(5) # one transient network blip should not abort the whole poll
continue
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(5) # still pending — keep the SAME task_id, re-poll
raise TimeoutError(task_id)
task_id = create_task()
url = wait_for(task_id)
video = requests.get(url, timeout=120).content
open("out.mp4", "wb").write(video)
print("saved out.mp4")
Die Polling-Schleife prüft explizit auf success und fail und wartet bei jedem anderen Status weiter, sodass sie robust mit allen Zwischenstatus-Labels umgeht, die die Aufgabe während des Renderns meldet. Wenn eine Polling-Anfrage fehlschlägt, schlafen Sie kurz und fragen Sie die gleiche gespeicherte task_id erneut ab, statt neu einzureichen – eine erneute Einreichung verursacht ein zweites Rendering und damit erneut Kosten.
Parameter, die pixverse-v6/image-to-video tatsächlich validiert
Im Folgenden finden Sie die Felder, die der Live-Endpunkt tatsächlich akzeptiert. Ich habe sie einzeln bestätigt, indem ich ungültige Werte gesendet und die Validierungsfehler gelesen habe, und sie anschließend mit der Modelldokumentation abgeglichen:
| Feld | Typ | Wert / Bereich | Beschreibung |
|---|---|---|---|
image_url |
string | eine öffentliche Bild-URL | Erforderlich. Erstes Frame. Ein einzelner URL-String – kein Array. |
prompt |
string | — | Erforderlich. Beschreibt die auf das Frame angewendete Bewegung. |
duration |
integer | 1–15, Standard 5 |
In Sekunden. Muss eine Ganzzahl sein, kein String. |
resolution |
string | 360p, 540p, 720p, 1080p |
Ausgabauflösung. |
negative_prompt |
string | — | Optional; Inhalte, die vermieden werden sollen. |
seed |
integer | — | Optional; wiederverwenden für reproduzierbare Ergebnisse. |
style |
string | anime, 3d_animation, clay, comic, cyberpunk |
Optionaler voreingestellter Stil. |
generate_audio |
boolean | true / false, Standard false |
Optional; schaltet generierte Tonspur/Umgebungsgeräusche ein oder aus. |
Es gibt hier kein aspect_ratio-Feld. Dies ist der einzige wirkliche Unterschied zu Text-zu-Video-Anfragen, die Sie vielleicht kennen, und es lohnt sich, ihn im Hinterkopf zu behalten (siehe unten).
Hinweise für den Produktivbetrieb
- Kein
aspect_ratio– die Ausgabegeometrie folgt Ihrem Eingabebild. Der Text-zu-Video-Endpunkt akzeptiert einaspect_ratio-Enum; dieser Endpunkt lehnt es ab. Da Sie das erste Frame liefern, übernimmt der Clip dessen Abmessungen. Wenn Sie einen 9:16-Hochformat-Clip benötigen, schneiden Sieimage_urlvor dem Einreichen auf 9:16 zu oder füllen Sie es entsprechend auf – es gibt keinen Seitenverhältnis-Regler, der das überschreiben könnte. - Die Anfragestruktur ist geschlossen. Jedes Feld außerhalb der obigen Tabelle wird abgelehnt mit dem Fehler
invalid input: <root>: additional properties '<field>' not allowed. Tippfehler oder geratene Felder schlagen beim Einreichen laut fehl, statt still ignoriert zu werden. Felder wiefirst_frame,image,input_image,motion_modeundcamera_movementwerden alle abgelehnt – das Startbild gehört inimage_url, Kamerabewegungen werden imprompt-Text beschrieben. durationist eine Ganzzahl, anders als bei einigen anderen Videomodellen der Plattform, die Strings ("6") akzeptieren. Das Senden von"5"liefertinvalid input: duration: got string, want integer. Werte außerhalb des Bereichs melden die Grenze direkt, z. B.duration: maximum: got 999, want 15.- Fehler werden jeweils für ein Feld zurückgegeben, im flachen Envelope-Format:
{"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: image_url: missing required field \"image_url\""}. Korrigieren Sie das gemeldete Feld und reichen Sie erneut ein; das nächste ungültige Feld (falls vorhanden) taucht beim nächsten Aufruf auf. - Aufgabenfehler liefern trotzdem HTTP 200. Die Fehlerinformation steht im Antworttext als
data.status: "fail"– prüfen Sie das Statusfeld, nicht nur den HTTP-Statuscode. Eine Bild-URL, die die Plattform nicht abrufen kann, ist eine häufige Ursache, stellen Sie also zuerst sicher, dass Ihr Startframe öffentlich ist. - Abrechnung pro Sekunde, die mit Auflösung und Dauer steigt, sodass ein 1080p/15s-Clip deutlich teurer ist als ein 540p/3s-Clip. Prüfen Sie die aktuellen Tarife auf der Preisseite, bevor Sie in großem Umfang generieren.
Was ich verifiziert habe (und was nicht)
Ich habe den Eingabevertrag ermittelt, indem ich absichtlich ungültige Werte an den Live-Endpunkt /v1/tasks von pixverse-v6/image-to-video gesendet und die Validierungsantworten der API selbst gelesen habe – eine reine Lese-Schema-Sondierung ohne Callback und ohne Rendering-Kosten. Konkrete Erkenntnisse, die es sich zu merken lohnt:
image_urlist das erforderliche Feld für das erste Frame und ein einzelner String, kein Array. Das Senden einer Zahl liefertimage_url: got number, want string; das Weglassen liefertmissing required field "image_url". Naheliegende Alternativfelder (first_frame,image,input_image) werden alle als unbekannte Eigenschaften abgelehnt.- Dieser Endpunkt lehnt
aspect_ratioab (additional properties 'aspect_ratio' not allowed), obwohl es beipixverse-v6/text-to-videogültig ist. Das ist der konkrete Grund, warum Bild-zu-Video-Anfragen anders aussehen als Text-zu-Video-Anfragen: Die Ausgabeform wird durch Ihr Frame bestimmt, nicht durch einen Parameter. generate_audioist ein echter boolescher Schalter (Standardfalse) – das Senden eines Strings liefertgenerate_audio: got string, want boolean. Wenn Sie Ton wünschen, setzen Sie ihn auftrue; er wird nicht zwangsweise ein- oder ausgeschaltet.
Bei dieser Sondierung habe ich keine Clips gerendert, daher macht dieser Leitfaden keine Aussagen über die Bewegungsqualität oder darüber, wie treu das Modell das Eingabeframe beibehält – er dokumentiert lediglich den exakten Anfragevertrag, den dieser Endpunkt durchsetzt.
Verwandte Inhalte
- PixVerse V6 Bild-zu-Video – Modellseite
- PixVerse V6 Bild-zu-Video – API-Dokumentation
- Aufgabe erstellen und Aufgabendetails abrufen als Referenz
- Authentifizierung
- Preise
- Weitere Bild-zu-Video-Tutorials auf hiapi: hailuo-2.3 und Grok Imagine 1.5
Häufig gestellte Fragen
Warum gibt es bei Bild-zu-Video kein aspect_ratio?Weil der Clip mit Ihrem image_url-Frame beginnt und dessen Abmessungen übernimmt. Um das Ausgabeverhältnis zu steuern, ändern Sie die Größe des Eingabebilds oder schneiden Sie es vor dem Einreichen zu – der Endpunkt lehnt aspect_ratio als unbekanntes Feld ab.
Akzeptiert image_url mehrere Bilder?Nein. Bei diesem Endpunkt ist es ein einzelner URL-String; das Übergeben eines Arrays führt zu einem Validierungsfehler. Es legt ausschließlich das Startframe fest.
Ist die Einheit von duration Sekunden oder Frames?Sekunden – eine beliebige Ganzzahl von 1 bis 15, Standard 5. Muss eine Ganzzahl sein; der String "5" wird abgelehnt.
Worin unterscheidet sich das vom Text-zu-Video-Endpunkt?pixverse-v6/image-to-video animiert das von Ihnen bereitgestellte Frame (image_url + prompt, kein aspect_ratio). pixverse-v6/text-to-video ist eine separate Modell-ID, generiert nur aus dem Prompt und akzeptiert tatsächlich aspect_ratio. Verwenden Sie Bild-zu-Video, wenn Sie bereits das exakte statische Startbild haben, das Sie in Bewegung setzen möchten.
Warum schlägt meine Anfrage mit „additional properties not allowed“ fehl?Sie haben ein Feld gesendet, das im Schema nicht existiert. Die Eingabe akzeptiert nur image_url, prompt, duration, resolution, negative_prompt, seed, style und generate_audio.
Ä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