Tutoriel
API de génération de vidéo à partir de texte PixVerse V6 : un exemple curl et Python qui fonctionne
- Modèle
- pixverse-v6
Générer une vidéo sur hiapi avec pixverse-v6/text-to-video revient essentiellement à faire un POST /v1/tasks suivi d'une boucle de polling — exactement le même modèle de tâche asynchrone que celui utilisé par chaque modèle de génération de la plateforme. Cet article vous donne des exemples curl et Python directement copiables, les champs d'entrée que l'endpoint valide réellement, ainsi que le cycle de vie des tâches et les pièges que j'ai notés lors d'une génération réellement exécutée.
Ce qu'il faut avant de commencer
- Une clé API hiapi. Créez-la dans la console, puis transmettez-la avec l'en-tête
Authorization: Bearer sk-<votre key>. Le format de l'en-tête est décrit dans la documentation d'authentification. - L'id du modèle est
pixverse-v6/text-to-video. Conservez la barre oblique du milieu — elle fait partie de l'id, ce n'est pas un chemin d'URL. - curl ne nécessite aucune installation ; l'exemple Python n'utilise que la bibliothèque standard et
requests.
PixVerse V6 text-to-video transforme un prompt textuel en un clip vidéo de 1 à 15 secondes, de 360p à 1080p. Il passe par l'interface de tâches asynchrones unifiée : soumettre la tâche → interroger le résultat → télécharger la vidéo avant l'expiration de l'URL de sortie.
Requête minimale fonctionnelle (curl)
Soumettez la tâche à POST /v1/tasks :
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<votre key>" \
-H "Content-Type: application/json" \
-d '{
"model": "pixverse-v6/text-to-video",
"input": {
"prompt": "Au soleil du matin, un renard roux traverse la neige fraîche au petit trot, rendu cinématographique, ralenti",
"aspect_ratio": "16:9",
"duration": 5,
"resolution": "720p"
}
}'
La réponse fournit un id de tâche :
{ "code": 200, "data": { "taskId": "tk-hiapi-...." }, "message": "success" }
Interrogez ensuite GET /v1/tasks/<taskId> jusqu'à ce que data.status passe à success :
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-.... \
-H "Authorization: Bearer sk-<votre key>"
En cas de succès, l'URL de la vidéo finale se trouve dans data.output[0].url :
{
"code": 200,
"data": {
"status": "success",
"storage": "temp",
"output": [
{ "type": "video", "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1793036664 }
]
},
"message": "success"
}
Cette URL de sortie est temporaire — elle contient un horodatage expireAt (d'après mes tests, 7 jours après la génération). Téléchargez immédiatement le fichier .mp4 et stockez-le dans votre propre stockage objet ; ne créez pas de lien direct vers cette adresse.
Le même flux (Python)
import time, requests
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-<votre key>", "Content-Type": "application/json"}
def create_task():
payload = {
"model": "pixverse-v6/text-to-video",
"input": {
"prompt": "Au soleil du matin, un renard roux traverse la neige fraîche au petit trot, rendu cinématographique, ralenti",
"aspect_ratio": "16:9",
"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"Échec de la création : {data}")
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) # une instabilité réseau ponctuelle ne doit pas interrompre tout le polling
continue
status = task.get("status")
if status == "success":
return task["output"][0]["url"]
if status == "fail":
raise RuntimeError(f"Échec de la tâche : {task.get('error')}")
time.sleep(5) # toujours en file d'attente/rendu — continuez d'interroger avec le même task_id
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("out.mp4 enregistré")
La boucle de polling ne teste que les deux états finaux success et fail, et continue d'attendre pour tout autre état — ainsi, que le rendu en cours signale handling ou archiving, le code ne se trompe pas. Point essentiel : si une requête de polling échoue elle-même, patientez puis réinterrogez avec le même task_id conservé, ne soumettez pas à nouveau la tâche — une nouvelle soumission relancerait un rendu et facturerait une seconde fois.
Les paramètres réellement validés par pixverse-v6/text-to-video
Voici les champs que l'endpoint accepte réellement. Pour chacun, j'ai confirmé en envoyant une valeur invalide et en relisant son propre message de validation, puis j'ai recoupé avec la documentation du modèle :
| Champ | Type | Valeurs / plage | Valeur par défaut | Description |
|---|---|---|---|---|
prompt |
string | 1–2048 octets UTF-8 (1 caractère chinois = 3 octets, environ 682 caractères) | — | Obligatoire. |
aspect_ratio |
enum | 16:9, 4:3, 1:1, 3:4, 9:16, 2:3, 3:2, 21:9 |
16:9 |
Notez qu'il prend en charge 21:9 (ultra-large) et 2:3/3:2. |
duration |
integer | 1–15 |
5 |
En secondes, doit être un entier, pas une chaîne. |
resolution |
enum | 360p, 540p, 720p, 1080p |
720p |
Résolution de sortie. |
generate_audio |
boolean | true / false |
false |
Générer également musique de fond, effets sonores et dialogues ; désactivé par défaut, activez-le explicitement pour avoir de l'audio. |
negative_prompt |
string | 2048 octets UTF-8 maximum | — | Facultatif ; ce que vous voulez éviter. |
seed |
integer | N'importe quel entier | — | Facultatif ; même seed + même prompt permet de reproduire le même résultat. |
style |
enum | anime, 3d_animation, clay, comic, cyberpunk |
aucune | Préréglage de style facultatif ; laissez vide pour conserver un rendu naturel. |
Pour utiliser un callback plutôt que le polling, vous pouvez aussi ajouter un objet callback au même niveau que input : url (adresse de callback HTTPS) + when (actuellement uniquement final, c'est-à-dire un callback à l'état final de la tâche).
Bonnes pratiques en production
- Le schéma est fermé. Tout champ absent du tableau ci-dessus est directement rejeté, avec
invalid input: <root>: additional properties '<champ>' not allowed. C'est en fait une bonne chose : un champ mal orthographié ou inventé échoue bruyamment dès la soumission, au lieu d'être silencieusement ignoré. durationest un entier, ce qui diffère de certains modèles vidéo de la plateforme qui acceptent une chaîne ("6"). Envoyer"5"donneinvalid input: duration: got string, want integer; une valeur hors limites indique directement la borne, par exempleduration: maximum: got 999, want 15,duration: minimum: got 0, want 1.- Les erreurs ne signalent qu'un seul champ à la fois, l'enveloppe est plate :
{"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: aspect_ratio: value must be one of ..."}. Corrigez le champ signalé puis renvoyez ; le prochain champ invalide (s'il y en a) apparaîtra à l'appel suivant. - En cas d'échec de la tâche, le HTTP reste 200. L'information d'échec se trouve dans
data.status: "fail"du corps de la réponse ; c'est ce champ status qu'il faut évaluer, pas le code de statut HTTP. - Polling ou callback ? Le polling est le plus simple pour un script léger ; pour passer à l'échelle sans maintenir de connexion, utilisez
callback. Dans les deux cas, dès que vous obtenezoutput[0].url, téléchargez immédiatement — l'URL contientexpireAtet renverra 404 après expiration.
Journal de test : je l'ai vraiment exécuté
Cet article ne se limite pas à des sondes en lecture seule — j'ai parcouru tout le cycle de vie avec une vraie requête, consigné ci-dessous :
- Création : la requête 720p / 5 secondes / 16:9 ci-dessus a renvoyé immédiatement
{"code":200,"data":{"taskId":"tk-hiapi-01M5AM..."},"message":"success"}. Notez que le taskId est une chaîne préfixée partk-hiapi-, pas un UUID. - Polling : le
data.statusdeGET /v1/tasks/<id>est passé successivement parhandling→archiving→success, le clip de 5 secondes a pris environ 74 secondes de la création à l'achèvement. - Sortie : à l'état final,
data.output[0]vaut{"type":"video","url":"https://temp.hiapi.ai/....mp4","expireAt":...,"artifactId":"...","storage":"temp"}.expireAtmoins l'heure de création donne exactement 604800 secondes, soit 7 jours. - Artefact : un HEAD sur cette URL de sortie renvoie
content-type: video/mp4, une taille d'environ 2,2 Mo, confirmant un fichier mp4 valide.
Une correction concernant l'audio mérite d'être notée à part : j'ai sondé plusieurs noms de champs voisins avec des valeurs invalides — generate_audio renvoie got string, want boolean (ce qui indique que c'est un champ booléen valide), tandis que sound et audio renvoient tous additional properties not allowed (inexistants). Autrement dit, l'audio est contrôlé par l'interrupteur generate_audio, par défaut false ; la page de tarification propose d'ailleurs deux niveaux « Sound On / Sound Off ». Lors de ce test, je n'ai pas activé generate_audio, la sortie est donc une vidéo muette.
Je n'ai pas porté d'évaluation subjective sur la qualité visuelle (cette fois, je n'ai vérifié que le contrat de requête, le cycle de vie de la tâche et le fait que le produit est un mp4 valide) ; jugez cette partie vous-même après avoir généré avec vos propres prompts.
Comment le coût est calculé
pixverse-v6/text-to-video est facturé à la seconde (le facteur de facturation estduration), plus la durée est longue plus c'est cher ; une résolution plus élevée, ainsi que l'activation de generate_audio en mode « Sound On », augmentent le prix par seconde. Les tarifs précis à la seconde sont ceux des données en temps réel de la page de tarification ; jetez-y un œil avant toute génération en lot.
Liens utiles
- PixVerse V6 text-to-video — page du modèle
- PixVerse V6 text-to-video — documentation API
- Références des endpoints Créer une tâche et Consulter le détail d'une tâche
- Démarrage rapide et Authentification
- Vous voulez partir d'une image pour faire une vidéo ? Voir PixVerse V6 image-to-video
- Tarification
Questions fréquentes
duration est en secondes ou en images ? En secondes — n'importe quel entier entre 1 et 15, par défaut 5.
Peut-on générer une vidéo avec du son ? Oui. Réglez generate_audio sur true, le modèle génère alors musique de fond, effets sonores et dialogues ; la valeur par défaut est false (muet). L'activation de l'audio passe par un niveau de facturation plus élevé, voir la page de tarification.
Quelle est la longueur maximale du prompt ? La limite est de 2048 octets UTF-8. Un caractère chinois compte pour 3 octets, donc environ 682 caractères chinois au maximum.
Quelle différence avec image-to-video ? Cet endpoint (pixverse-v6/text-to-video) part uniquement d'un prompt textuel. Image-to-video est un autre model id, qui reçoit une image de départ et l'anime — pour animer une image existante plutôt que générer à partir de rien, utilisez celui-là.
Pourquoi ma requête renvoie-t-elle « additional properties not allowed » ? Vous avez transmis un champ absent du schéma. L'entrée n'accepte que prompt, aspect_ratio, duration, resolution, generate_audio, negative_prompt, seed et style.
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