HiAPI
Blog

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

Nov 3, 2026
深靛蓝底色上三层嵌套的扁平折线箭头依次向右推进,前缘为杏橙色,像信号流程图,是教程文章的封面图。

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, curl suffit. Pour la version Python, vous n'avez besoin que de requests — 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 :

  1. Soumission. Vous envoyez le prompt et l'image en POST au 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.
  2. Interrogation. Vous effectuez des GET répétés sur le statut de la tâche avec cet identifiant, jusqu'à ce qu'elle signale l'achèvement (ou l'échec).
  3. 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 image doivent être vérifiés dans la référence API HiAPI de veo-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.
  • -sS garde 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.
  • timeout est 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.content est 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-video gé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 ffprobe si 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/json avec 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 output dans 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 →

Commencez avec des artefacts IA persistants

Obtenez votre clé API et appelez des modèles d'image, de vidéo et d'audio via une API unique basée sur les tasks.

Lire la documentation de l'API