Tutoriel
Comment appeler veo-3.1-fast/image-to-video via l'API HiAPI (curl + Python)
Une démonstration de requête exécutable : image de première frame, audio natif, interrogation asynchrone et téléchargement du résultat
Ce que ce tutoriel construit, et ce qu'il faut préparer au préalable
Ce tutoriel présente de bout en bout une intégration HiAPI exécutable, utilisant veo-3.1-fast/image-to-video : vous envoyez une image de première frame et un prompt, recevez une tâche asynchrone, l'interrogez jusqu'à son achèvement, puis téléchargez la vidéo générée avec son audio natif.
À la fin du tutoriel, vous disposerez de deux implémentations équivalentes — une commande curl exécutable dans un terminal, et un client Python intégrable dans un script ou un service — toutes deux accédant au même point de terminaison HiAPI.
Prérequis
Avant de commencer, préparez les éléments suivants :
- Une clé API HiAPI. Ne la validez pas dans le système de gestion de code source. Dans les exemples ci-dessous, elle est lue depuis une variable d'environnement plutôt que collée en ligne.
- L'URL de base HiAPI. Utilisez l'adresse indiquée dans votre tableau de bord HiAPI ou la référence API ; stockez-la dans une variable pour ne la configurer qu'une seule fois.
- Une image de première frame. Une URL accessible publiquement est l'entrée la plus simple. Utilisez une vraie image que vous avez le droit d'utiliser, dans un format courant comme JPEG ou PNG.
- Un client HTTP. Pour cette démonstration,
curlsuffit. Pour la version Python, vous n'avez besoin que derequests— aucun SDK fournisseur n'est nécessaire. - Un répertoire local pour stocker les vidéos téléchargées.
Configurer votre environnement
Exportez la clé et l'URL de base afin que les exemples shell et Python puissent les réutiliser :
export HIAPI_API_KEY="your-api-key"
export HIAPI_BASE_URL="https://api.hiapi.ai"
export FIRST_FRAME_URL="https://example.com/your-first-frame.jpg"
Le chemin exact du point de terminaison et les noms de paramètres de veo-3.1-fast/image-to-video sont documentés dans la référence API HiAPI, à côté de l'entrée du modèle — consultez-y la liste normative des champs plutôt que de vous fier à des extraits copiés ailleurs. Ce tutoriel se concentre sur la structure de la requête et le flux de travail, qui restent inchangés même si les détails des champs doivent être confirmés dans la documentation.
Il vaut la peine de garder à l'esprit dès maintenant : il s'agit d'un modèle basé sur des tâches, et non synchrone. Vous n'obtiendrez pas directement la vidéo dans la réponse de soumission. Vous obtiendrez un identifiant de tâche, et la vidéo arrivera plus tard.
Structure d'une requête image-vers-vidéo
Avant d'écrire du code, il est utile de comprendre ce que vous envoyez réellement et ce qui est renvoyé. La génération image-vers-vidéo est plus lourde que la génération de texte, c'est pourquoi l'API la modélise comme une tâche en arrière-plan.
Entrée : prompt et première frame
Une requête veo-3.1-fast/image-to-video comporte deux parties conceptuelles :
- Un prompt textuel qui décrit le mouvement, le comportement de la caméra et l'intention de la scène — c'est-à-dire ce qui doit se produire après la première frame.
- Une image de référence qui ancre la première frame de la sortie. C'est ce qui distingue image-vers-vidéo de texte-vers-vidéo : le modèle continue à partir de votre image au lieu de créer une frame d'ouverture de toutes pièces.
Le nom du modèle vous indique déjà le compromis : la variante fast est optimisée pour un délai d'exécution plus rapide sur les tâches image-vers-vidéo, ce qui la rend idéale pour l'itération et pour les pipelines où la latence compte plus que la fidélité maximale.
La sortie générée inclut un audio natif, de sorte que le fichier final est une vidéo complète avec son, et non un clip muet nécessitant une musique séparée.
Cycle de vie d'une tâche
La génération prenant du temps, l'interaction se décompose en trois phases :
- Soumission. Vous envoyez le prompt et l'image en
POSTau point de terminaison du modèle. La réponse est une confirmation légère contenant un identifiant de tâche — pas la vidéo. - Interrogation. Vous effectuez des
GETrépétés sur le statut de la tâche avec cet identifiant, jusqu'à ce qu'elle signale l'achèvement (ou l'échec). - Récupération. Une fois terminée, la réponse de la tâche pointe vers la vidéo générée, que vous téléchargez et stockez.
Maintenir ces phases séparées dans le code est la décision structurelle la plus importante. Si vous les mélangez, les nouvelles tentatives, les délais d'attente et la gestion des erreurs deviennent flous.
À quoi ressemble une soumission correctement formée
Quel que soit le mode exact de sérialisation, prévoyez une requête contenant :
- L'identifiant du modèle
veo-3.1-fast/image-to-video. - Le texte de votre prompt.
- La référence de l'image de première frame.
- L'authentification par clé API dans l'en-tête de la requête.
Tout le reste — paramètres optionnels, valeurs par défaut, options de résolution de sortie — relève de la référence API HiAPI de ce modèle. Lisez-la une fois, placez les noms de champs confirmés dans des constantes, et ne les dispersez pas dans votre base de code.
Considérez la réponse de soumission comme un reçu. Enregistrez-la, stockez l'ID de tâche, puis passez à l'interrogation.
Lancer l'appel avec curl
Soumettons une tâche. La commande ci-dessous envoie un corps JSON contenant le prompt et l'image de première frame au point de terminaison du modèle sur HiAPI, en s'authentifiant avec la clé issue de l'environnement.
curl -sS -X POST "$HIAPI_BASE_URL/v1/videos/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-fast/image-to-video",
"prompt": "Travelling avant lent à travers un sentier forestier ensoleillé, feuilles dérivant, ambiance douce de chants d'oiseaux",
"image": "'"$FIRST_FRAME_URL"'"
}'
Quelques remarques sur cette commande :
- Le chemin du point de terminaison et le nom du champ
imagedoivent être vérifiés dans la référence API HiAPI deveo-3.1-fast/image-to-video; s'ils diffèrent, remplacez-les par les valeurs normatives. La structure ici — modèle, prompt, image — est ce qui compte. - Le prompt joue réellement un rôle. Décrivez explicitement le mouvement et les déplacements de caméra (« travelling avant lent », « feuilles dérivant »), et mentionnez l'ambiance audio souhaitée, car le modèle génère simultanément l'image et l'audio natif.
-sSgarde la sortie silencieuse tout en affichant les erreurs, ce qui est exactement ce que vous voulez dans une démonstration en terminal.- L'image est transmise sous forme de chaîne URL. Si vous préférez envoyer des octets, consultez les formes d'entrée prises en charge dans la référence plutôt que de deviner.
Lire la réponse de soumission
Une soumission réussie renvoie un objet JSON compact contenant l'identifiant de tâche et le statut — approximativement comme ceci :
{
"id": "job_abc123",
"status": "queued"
}
Les noms de champs ne sont donnés qu'à titre d'exemple ; confirmez-les avec la réponse réelle. L'important est que vous disposez maintenant d'un ID utilisable pour l'interrogation, et d'un statut qui n'est pas celui d'une vidéo terminée.
Capturez cet ID dans le shell pour simplifier les étapes suivantes :
JOB_ID="job_abc123"
Si vous recevez une erreur d'authentification, cela signifie que votre clé est absente ou mal formée. Une erreur de validation signifie généralement que le corps de la requête ne correspond pas au schéma documenté — vérifiez d'abord les noms et types de champs. Une réponse de limitation de débit signifie que vous envoyez trop fréquemment ; reculez plutôt que de réessayer en boucle serrée.
La même requête en Python
Voici la soumission équivalente en Python. Elle n'utilise que requests, lit la configuration depuis les variables d'environnement et sépare l'étape de soumission de l'interrogation, afin que vous puissiez réutiliser chaque partie.
import os
import time
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
FIRST_FRAME_URL = os.environ["FIRST_FRAME_URL"]
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
MODEL = "veo-3.1-fast/image-to-video"
def submit_job(prompt: str, image_url: str) -> str:
payload = {
"model": MODEL,
"prompt": prompt,
"image": image_url,
}
resp = requests.post(
f"{BASE_URL}/v1/videos/generations",
headers=HEADERS,
json=payload,
timeout=60,
)
resp.raise_for_status()
data = resp.json()
job_id = data["id"]
print(f"submitted job: {job_id} (status={data.get('status')})")
return job_id
if __name__ == "__main__":
job_id = submit_job(
prompt="Travelling avant lent à travers un sentier forestier ensoleillé, "
"feuilles dérivant, ambiance douce de chants d'oiseaux",
image_url=FIRST_FRAME_URL,
)
Pourquoi cette structure
- La configuration dans des constantes. L'URL de base, les en-têtes, le chemin du point de terminaison et le nom du modèle ne sont définis qu'une seule fois. Lorsque la référence API vous indique un nom de champ différent, vous ne modifiez qu'une ligne.
timeoutest explicite. Une soumission qui reste bloquée indéfiniment est pire qu'un échec rapide. Pour un petit corps JSON, soixante secondes sont amplement suffisantes.raise_for_status()expose rapidement les échecs. En cas de 4xx et 5xx, vous obtenez une exception au lieu d'analyser silencieusement un corps d'erreur comme une tâche.- La fonction ne renvoie que l'ID de tâche. L'appelant n'a pas besoin de savoir à quoi ressemble la charge utile de soumission ; il a juste besoin de quelque chose pour interroger.
Si votre application est un service web, appelez submit_job dans le gestionnaire de requêtes et confiez l'ID renvoyé à un processus de travail en arrière-plan. Ne bloquez pas la requête HTTP pendant le rendu de la vidéo.
Interroger la tâche asynchrone jusqu'à ce que la vidéo soit prête
La tâche existe maintenant et est en file d'attente. L'interrogation est le moyen de savoir quand elle est terminée.
La boucle d'interrogation de base
def poll_job(job_id: str, timeout_s: int = 900, initial_delay: float = 5.0) -> dict:
url = f"{BASE_URL}/v1/videos/generations/{job_id}"
delay = initial_delay
deadline = time.time() + timeout_s
while time.time() < deadline:
resp = requests.get(url, headers=HEADERS, timeout=30)
resp.raise_for_status()
data = resp.json()
status = data.get("status")
print(f"status={status}")
if status == "succeeded":
return data
if status in ("failed", "cancelled"):
raise RuntimeError(f"job {job_id} ended with status={status}: {data}")
time.sleep(delay)
delay = min(delay * 1.5, 30.0) # back off, cap at 30s
raise TimeoutError(f"job {job_id} did not finish within {timeout_s}s")
Pourquoi chaque partie existe
- Interrogation plutôt que webhook. L'intégration fiable la plus simple consiste à demander le statut à intervalles planifiés. Les webhooks sont préférables à grande échelle, mais nécessitent un point de terminaison public ; l'interrogation fonctionne partout.
- Retrait exponentiel avec plafond. Les interrogations précoces sont peu coûteuses et fréquentes ; les interrogations ultérieures s'espacent. Le plafond empêche les intervalles de s'emballer sur les tâches longues. Commencez autour de cinq secondes et augmentez progressivement.
- États terminaux explicites. Le succès est un état ; l'échec et l'annulation en sont d'autres. Traitez tout le reste comme « continuez d'attendre », mais n'attendez jamais indéfiniment.
- Une échéance temporelle réelle. Comparée au texte, la génération vidéo est lente. Choisissez un délai global généreux correspondant à la patience de votre produit, et échouez proprement en cas de dépassement plutôt que de boucler indéfiniment.
- Journalisation des statuts. Imprimez ou enregistrez chaque transition de statut. En cas de problème, c'est la première chose que vous voudrez consulter.
Interroger depuis le shell
Pour une vérification manuelle rapide lors du débogage, un seul appel curl suffit :
curl -sS "$HIAPI_BASE_URL/v1/videos/generations/$JOB_ID" \
-H "Authorization: Bearer $HIAPI_API_KEY"
Relancez-le toutes les quelques secondes, ou enveloppez-le dans une petite boucle while jusqu'à ce que le statut bascule vers un état terminal. Confirmez les noms exacts des champs et du chemin dans la référence API HiAPI — le cycle de vie est stable, mais les détails en ligne sont la source de vérité.
Une fois que poll_job renvoie, la réponse doit contenir une référence à la vidéo terminée. C'est ce que vous téléchargerez ensuite.
Télécharger et vérifier la sortie
La tâche est terminée, la réponse pointe vers le fichier généré. Le télécharger est un simple GET HTTP, mais faites deux choses : l'écrire en flux sur le disque et vérifier ce que vous avez obtenu.
Récupérer la vidéo
import os
from urllib.parse import urlparse
def download_video(job: dict, out_dir: str = "outputs") -> str:
video_url = job["output"]["url"] # confirm the field path in the API reference
os.makedirs(out_dir, exist_ok=True)
parsed = urlparse(video_url)
ext = os.path.splitext(parsed.path)[1] or ".mp4"
dest = os.path.join(out_dir, f"{job['id']}{ext}")
with requests.get(video_url, stream=True, timeout=120) as r:
r.raise_for_status()
with open(dest, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
f.write(chunk)
size = os.path.getsize(dest)
if size == 0:
raise IOError(f"downloaded file is empty: {dest}")
print(f"saved {dest} ({size} bytes)")
return dest
Explications :
- Diffusion en continu par blocs. Les fichiers vidéo sont volumineux ; les charger en mémoire avec
r.contentest un gaspillage et peut échouer sur des hôtes à ressources limitées. - Conservez l'extension afin que les lecteurs et les outils en aval identifient le format du conteneur.
- Nommez selon l'ID de tâche. Il est unique et traçable, et évite les collisions lors de l'exécution de lots.
- Rejetez les fichiers vides. Un téléchargement de zéro octet est un téléchargement échoué, même si le code de statut affiche 200.
Si l'URL de la vidéo est signée ou limitée dans le temps, téléchargez-la immédiatement après l'achèvement de la tâche, plutôt que de stocker l'URL pour plus tard.
Vérifier qu'il s'agit d'une vraie vidéo avec de l'audio
L'existence du fichier ne signifie pas que le fichier est utilisable. Vérifiez-le :
- Lisez-la localement avec un lecteur multimédia et confirmez l'image et le son.
veo-3.1-fast/image-to-videogénère un audio natif ; un résultat silencieux est donc un signal d'alarme qui mérite une enquête avant d'atteindre vos utilisateurs. - Vérifiez le conteneur avec
ffprobesi vous avez installé ffmpeg :
ffprobe -hide_banner outputs/job_abc123.mp4
Recherchez dans la sortie un flux vidéo et un flux audio, ainsi qu'une durée plausible. C'est aussi le moyen le plus rapide de détecter un fichier tronqué.
- Effectuez une vérification de base sur la première frame. Elle devrait ressembler à votre image d'entrée. Sinon, soupçonnez l'URL de l'image ou le champ utilisé pour la transmettre avant de soupçonner le modèle.
Une fois le téléchargement vérifié, persistez le fichier dans un stockage durable et enregistrez simultanément l'ID de tâche. Cette correspondance permet le débogage ultérieur, les réexécutions et le rapprochement de facturation.
Pièges et vérifications avant la mise à l'échelle
La plupart des problèmes d'intégration des API vidéo asynchrones ne proviennent pas du modèle, mais du pipeline. Voici ce qu'il faut vérifier en premier.
Entrée image
- L'image est-elle réellement accessible ? Une URL qui fonctionne dans votre navigateur peut nécessiter une authentification, bloquer le hotlinking ou expirer. Privilégiez une URL stable et lisible publiquement.
- Est-elle dans un format pris en charge ? Sauf indication contraire de la référence API, tenez-vous à des formats courants comme JPEG et PNG.
- Le contenu est-il correct ? La première frame ancre tout le clip. Une image de mauvaise qualité ou hors sujet produira une vidéo décevante, qu'aucun ajustement de prompt ne pourra corriger.
Structure de la requête
- Noms et types de champs. Validez-les dans la référence API HiAPI de
veo-3.1-fast/image-to-video. Des extraits copiés depuis d'autres plateformes échoueront — le point de terminaison est celui de HiAPI, et les noms de champs sont sensibles à la casse. - Type de contenu. Envoyez
Content-Type: application/jsonavec un véritable corps JSON, et non des données de formulaire. - Identifiant du modèle. Utilisez la chaîne complète
veo-3.1-fast/image-to-video; les noms tronqués renvoient des erreurs apparemment sans rapport.
Délais d'attente et nouvelles tentatives
- Des délais d'attente distincts par phase. La soumission, les requêtes d'interrogation et le téléchargement de fichier méritent chacun le leur. Un délai global unique serait soit trop serré pour le téléchargement, soit trop lâche pour les vérifications de statut.
- Réessayez en toute sécurité. La soumission peut être réessayée sur des erreurs réseau transitoires et des réponses 5xx, mais seulement si vous pouvez déterminer si la tâche a réellement été créée — sinon vous risquez de facturer et de générer deux fois. L'interrogation et le téléchargement sont idempotents et peuvent être réessayés librement.
- Reculez en cas de limitation de débit. Respectez la réponse et ralentissez plutôt que de marteler le point de terminaison.
Comportement d'interrogation
- N'interrogez jamais en boucle serrée. Cela gaspille du quota et ressemble à un abus.
- Ayez toujours une condition de terminaison. Une échéance qui lève une exception vaut mieux qu'une tâche bloquée en mémoire.
- Enregistrez chaque transition de statut avec un horodatage. Vous en aurez besoin pour déduire la latence.
Hygiène opérationnelle
- Gardez les clés API côté serveur. Ne les envoyez jamais au navigateur et ne les intégrez jamais dans une application mobile.
- Stockez l'ID de tâche avec chaque artefact. C'est votre clé de corrélation entre les journaux, les fichiers et les enregistrements d'utilisation.
- Validez les téléchargements avant de les livrer. Vérifiez la taille, et idéalement le flux. Un fichier vide ou muet qui atteint l'utilisateur coûte bien plus cher à corriger qu'un téléchargement échoué que vous réessayez.
- Ne présumez pas des chemins de champs. L'emplacement de
outputdans la réponse de tâche est exactement le genre de détail qui change — lisez-le dans la référence API, pas dans un tutoriel, y compris celui-ci.
Avant d'ouvrir un ticket concernant le modèle, parcourez cette liste dans l'ordre. La plupart du temps, le correctif concerne l'URL, un nom de champ ou un retrait manquant.
Voilà la boucle complète : soumettre avec une image de première frame et un prompt, interroger la tâche jusqu'à son achèvement, puis télécharger et vérifier la vidéo avec audio natif. Commencez par la page du modèle veo-3.1-fast/image-to-video sur HiAPI, confirmez les champs de requête actuels, puis transplantez les deux fonctions ci-dessus dans votre propre service.
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