Tutoriel
API PixVerse V6 image-vers-vidéo : exemples curl et Python directement exécutables
- Modèle
- pixverse-v6
Pour animer une image statique avec pixverse-v6/image-to-video sur hiapi, il suffit d'un appel POST /v1/tasks et d'une interrogation répétée (polling) — exactement le même schéma de tâches asynchrones que celui utilisé par tous les modèles de génération de la plateforme. Sa différence avec le point de terminaison texte-vers-vidéo réside dans les entrées : vous fournissez une image de départ (image_url) ainsi qu'un prompt décrivant le mouvement souhaité. Ce guide fournit des exemples curl et Python directement copiables, les champs d'entrée réellement validés par ce point de terminaison, et un piège inattendu qui surprend ceux qui viennent du texte-vers-vidéo.
Ce dont vous avez besoin
- Une clé API hiapi. Créez-la dans la console et envoyez-la via
Authorization: Bearer sk-<your-key>. Le format de l'en-tête est décrit dans la documentation Authentification. - L'ID de modèle
pixverse-v6/image-to-video(conservez la barre oblique — elle fait partie de l'ID, ce n'est pas un chemin d'URL). Il s'agit d'un ID de modèle différent depixverse-v6/text-to-video. - Une URL d'image accessible publiquement comme première image. La plateforme récupère cette image côté serveur, donc les liens
localhostou ceux d'un bucket privé ne fonctionneront pas — hébergez l'image de départ à un emplacement accessible en GET par l'API. - Avec curl, rien à installer. Pour l'exemple Python, il suffit de la bibliothèque standard et de
requests.
PixVerse V6 image-vers-vidéo prend l'image statique que vous fournissez comme image de départ et l'anime en un clip de 1 à 15 secondes. Il fonctionne via l'API de tâches asynchrones unifiée — vous soumettez la tâche, interrogez le résultat, puis téléchargez l'URL de sortie avant son expiration.
Requête minimale fonctionnelle (curl)
Soumettez la tâche à POST /v1/tasks. image_url et prompt sont tous deux obligatoires :
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": "Slow push-in; the subject turns toward the camera and smiles, soft breeze in the hair",
"duration": 5,
"resolution": "720p"
}
}'
La réponse renvoie un ID de tâche :
{ "code": 200, "data": { "taskId": "a1b2c3d4-...." } }
Interrogez ensuite GET /v1/tasks/<taskId> jusqu'à ce que data.status vaille success :
curl -s https://api.hiapi.ai/v1/tasks/a1b2c3d4-.... \
-H "Authorization: Bearer sk-<your-key>"
En cas de succès, l'URL de la vidéo terminée se trouve dans data.output[0].url :
{
"code": 200,
"data": {
"status": "success",
"output": [{ "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1760000000 }]
}
}
Cette URL de sortie est temporaire — elle porte un horodatage expireAt. Téléchargez immédiatement le fichier .mp4 et enregistrez-le dans votre propre bucket ; ne créez pas de lien direct (hotlink) vers cette URL.
Le même flux en 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": "Slow push-in; the subject turns toward the camera and smiles",
"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")
La boucle de polling vérifie explicitement success et fail, et continue d'attendre pour tout autre statut ; elle gère donc robustement les libellés d'état intermédiaires que la tâche peut rapporter pendant le rendu. Si une requête de polling échoue, patientez puis réinterrogez le même task_id sauvegardé, plutôt que de resoumettre — une resoumission entraînerait des frais de rendu supplémentaires.
Paramètres réellement validés par pixverse-v6/image-to-video
Voici les champs réellement acceptés par le point de terminaison en production. Je les ai confirmés un par un en envoyant des valeurs invalides et en lisant les erreurs de validation, puis j'ai recoupé avec la documentation du modèle :
| Champ | Type | Valeurs / plage | Description |
|---|---|---|---|
image_url |
string | une URL d'image publique | Obligatoire. Première image. Une seule chaîne d'URL — pas un tableau. |
prompt |
string | — | Obligatoire. Décrit le mouvement appliqué à cette image. |
duration |
integer | 1–15, par défaut 5 |
En secondes. Doit être un entier, pas une chaîne. |
resolution |
string | 360p, 540p, 720p, 1080p |
Résolution de sortie. |
negative_prompt |
string | — | Facultatif ; contenu à éviter. |
seed |
integer | — | Facultatif ; à réutiliser pour des résultats reproductibles. |
style |
string | anime, 3d_animation, clay, comic, cyberpunk |
Style prédéfini facultatif. |
generate_audio |
boolean | true / false, par défaut false |
Facultatif ; active/désactive la piste audio/ambiante générée. |
Il n'y a pas de champ aspect_ratio ici. C'est la seule véritable différence avec les requêtes texte-vers-vidéo que vous avez pu voir, et il faut la garder en tête (voir ci-dessous).
Points à surveiller en production
- Pas de
aspect_ratio— la géométrie de sortie suit votre image d'entrée. Le point de terminaison texte-vers-vidéo accepte une énumérationaspect_ratio; celui-ci la rejette. Comme vous fournissez la première image, le clip hérite des dimensions de cette image. Si vous avez besoin d'un clip vertical 9:16, recadrez ou complétez votreimage_urlen 9:16 avant la soumission — aucun réglage de ratio ne peut le remplacer. - La structure de la requête est fermée. Tout champ hors du tableau ci-dessus est rejeté avec l'erreur
invalid input: <root>: additional properties '<field>' not allowed. Une faute de frappe ou un champ deviné échoue bruyamment à la soumission plutôt que d'être ignoré silencieusement. Des champs commefirst_frame,image,input_image,motion_modeetcamera_movementsont tous rejetés — l'image de départ se place dansimage_url, et le mouvement de caméra s'écrit dans le texte duprompt. durationest un entier, contrairement à certains autres modèles vidéo de la plateforme qui acceptent une chaîne ("6"). Envoyer"5"renvoieinvalid input: duration: got string, want integer. Les valeurs hors plage rapportent directement la borne, par exempleduration: maximum: got 999, want 15.- Les erreurs renvoient un champ à la fois, dans une enveloppe plate :
{"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: image_url: missing required field \"image_url\""}. Corrigez le champ signalé et resoumettez ; le champ invalide suivant (s'il y en a un) apparaîtra à l'appel suivant. - Un échec de tâche renvoie quand même HTTP 200. L'échec se trouve dans le corps de la réponse sous la forme
data.status: "fail"— vérifiez le champ de statut, pas seulement le code HTTP. Une URL d'image que la plateforme ne peut pas récupérer est une cause fréquente, donc vérifiez d'abord que votre image de départ est publique. - Facturation à la seconde, qui augmente avec la résolution et la durée ; un clip 1080p/15s coûte donc bien plus qu'un clip 540p/3s. Consultez les tarifs actuels sur la page des prix avant de lancer des générations en lot.
Ce que j'ai vérifié (et ce que je n'ai pas vérifié)
J'ai établi le contrat d'entrée en envoyant des valeurs délibérément invalides au point de terminaison /v1/tasks de production de pixverse-v6/image-to-video et en lisant les réponses de validation de l'API elle-même — une sonde de schéma en lecture seule, sans callback ni frais de rendu. Découvertes notables :
image_urlest le champ obligatoire de la première image, et c'est une chaîne unique, pas un tableau. Envoyer un nombre renvoieimage_url: got number, want string; l'omettre renvoiemissing required field "image_url". Les champs alternatifs devinables (first_frame,image,input_image) sont tous rejetés comme propriétés inconnues.- Ce point de terminaison rejette
aspect_ratio(additional properties 'aspect_ratio' not allowed), même s'il est valide surpixverse-v6/text-to-video. C'est la raison concrète pour laquelle une requête image-vers-vidéo diffère d'une requête texte-vers-vidéo : la forme de sortie est déterminée par votre image, pas par un paramètre. generate_audioest un véritable interrupteur booléen (par défautfalse) — envoyer une chaîne renvoiegenerate_audio: got string, want boolean. Si vous voulez du son, mettez-le àtrue; il n'est ni forcé à l'activation ni à la désactivation.
Je n'ai pas rendu de clip lors de cette sonde, donc ce guide ne se prononce pas sur la qualité du mouvement ni sur la fidélité du modèle à l'image d'entrée — il documente uniquement le contrat de requête exact imposé par ce point de terminaison.
Contenu associé
- PixVerse V6 image-vers-vidéo — page du modèle
- PixVerse V6 image-vers-vidéo — documentation API
- Références Créer une tâche et Obtenir les détails d'une tâche
- Authentification
- Prix
- Autres tutoriels image-vers-vidéo sur hiapi : hailuo-2.3 et Grok Imagine 1.5
Questions fréquentes
Pourquoi image-vers-vidéo n'a-t-il pas de aspect_ratio ?Parce que le clip commence par votre image image_url et hérite de ses dimensions. Pour contrôler le ratio de sortie, redimensionnez ou recadrez l'image d'entrée avant la soumission — ce point de terminaison rejette aspect_ratio comme champ inconnu.
image_url accepte-t-il plusieurs images ?Non. Sur ce point de terminaison, c'est une chaîne d'URL unique ; passer un tableau provoque une erreur de validation. Elle ne définit que l'image de départ.
duration est-il en secondes ou en images ?En secondes — un entier de 1 à 15, par défaut 5. Il doit être un entier ; la chaîne "5" est rejetée.
En quoi cela diffère-t-il du point de terminaison texte-vers-vidéo ?pixverse-v6/image-to-video anime l'image que vous fournissez (image_url + prompt, sans aspect_ratio). pixverse-v6/text-to-video est un ID de modèle distinct, génère uniquement à partir du prompt et accepte bien aspect_ratio. Utilisez image-vers-vidéo lorsque vous disposez déjà de l'image fixe exacte dont vous voulez animer l'ouverture.
Pourquoi ma requête échoue-t-elle avec « additional properties not allowed » ?Vous avez envoyé un champ absent du schéma. Les entrées acceptent uniquement image_url, prompt, duration, resolution, negative_prompt, seed, style et generate_audio.
Articles similaires
Voir tous les articles →-
Tutoriel
Comment appeler hailuo-2.3-fast/image-to-video via l'API HiAPI : curl et Python en pratique
La première requête exploitable du palier image-vers-vidéo rapide et économique — de l'ID du modèle au téléchargement du MP4
-
Tutoriel
Comment appeler hailuo-2.3/text-to-video via l'API HiAPI : curl, Python et exemples de requêtes exécutables
-
Tutoriel
Utiliser Kandinsky 6.0 Pro texte-vers-vidéo sur HiAPI : tutoriel curl et Python
Démonstration pratique axée sur la requête : construire l'appel du prompt au clip vidéo, soumettre la requête, interroger l'état d'achèvement et télécharger le résultat