HiAPI
Blog

Tutoriel

Comment utiliser l'API vidu-q4-preview reference-to-video (curl + Python)

Oct 19, 2026
Comment utiliser l'API vidu-q4-preview reference-to-video (curl + Python)

Ce que vous allez construire

Lancez un appel reference-to-video sur l'API asynchrone /v1/tasks de hiapi, en fusionnant plusieurs images fixes de référence — et éventuellement des extraits audio — en une séquence de 3 à 16 secondes, jusqu'à 4K. Vous soumettez un seul POST, puis vous interrogez (ou recevez un callback) jusqu'à ce que la tâche soit terminée, puis vous téléchargez le MP4.

Commencez par obtenir une clé depuis la console hiapi ; chaque requête ci-dessous utilise Authorization: Bearer sk-<your-key>.

Reference-to-video vs image-to-video. Ce endpoint fusionne 1 à 15 images fixes — passez une image fixe de personnage, une image fixe de décor, une image fixe d'objet, et il les compose en un seul plan. Si vous n'avez qu'une seule première image à animer, utilisez plutôt vidu-q4-preview/image-to-video ; il accepte un seul image_url et rejette reference_image_urls.

Requête minimale exécutable (curl)

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vidu-q4-preview/reference-to-video",
    "input": {
      "prompt": "le personnage de l'image de référence 1 traverse le café de l'image de référence 2, lumière chaude du matin, travelling avant lent",
      "reference_image_urls": [
        "https://your-cdn.com/person.jpg",
        "https://your-cdn.com/cafe.jpg"
      ],
      "resolution": "1080p",
      "duration": 5,
      "aspect_ratio": "16:9"
    }
  }'

Ce POST renvoie un id de tâche, pas la vidéo :

{ "code": 200, "data": { "taskId": "task_abc123" } }

Interrogez GET /v1/tasks/<taskId> jusqu'à ce que data.status vaille success, puis récupérez le MP4 depuis data.output[0].url :

curl https://api.hiapi.ai/v1/tasks/task_abc123 \
  -H "Authorization: Bearer sk-<your-key>"
{
  "code": 200,
  "data": {
    "status": "success",
    "output": [
      { "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1760000000 }
    ]
  }
}

L'URL de sortie est temporaire — elle porte un expireAt (expiration après quelques jours) — donc téléchargez immédiatement les octets, ne faites pas de hotlink.

Python : soumettre → interroger → télécharger

import time
import requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {
    "Authorization": "Bearer sk-<your-key>",
    "Content-Type": "application/json",
}

def submit() -> str:
    payload = {
        "model": "vidu-q4-preview/reference-to-video",
        "input": {
            "prompt": (
                "le personnage de l'image de référence 1 traverse le café de l'image de référence 2, "
                "lumière chaude du matin, travelling avant lent"
            ),
            "reference_image_urls": [
                "https://your-cdn.com/person.jpg",
                "https://your-cdn.com/cafe.jpg",
            ],
            "resolution": "1080p",
            "duration": 5,
            "aspect_ratio": "16:9",
        },
    }
    r = requests.post(BASE, json=payload, headers=HEADERS, timeout=60)
    r.raise_for_status()
    body = r.json()
    task_id = (body.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"submit rejected: {body}")  # les erreurs 400 arrivent ici
    return task_id

def wait(task_id: str, timeout_s: int = 600, interval: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=40)
        task = r.json().get("data") or {}
        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(interval)
    raise TimeoutError(task_id)

def download(url: str, path: str) -> None:
    with requests.get(url, stream=True, timeout=120) as r:
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 16):
                f.write(chunk)

task_id = submit()
url = wait(task_id)
download(url, "out.mp4")

Un point à bien intégrer : un rendu échoué renvoie tout de même un HTTP 200, la raison se trouvant dans data.status: "fail" et data.error.code / data.error.message. Un échec de génération n'est pas une erreur HTTP : branchez donc sur le corps de la réponse, pas sur le code de statut.

Ajouter une référence vocale

Le champ vocal est reference_audio_urls — un tableau de 3 extraits audio maximum. L'audio définit le timbre ; votre prompt porte toujours le texte et pilote la synchronisation labiale.

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": {
    "prompt": "le présentateur de l'image de référence 1 dit avec la voix de l'audio de référence 1 : « Bienvenue sur la chaîne. »",
    "reference_image_urls": ["https://your-cdn.com/presenter.jpg"],
    "reference_audio_urls": ["https://your-cdn.com/voice.mp3"],
    "resolution": "1080p",
    "duration": 8
  }
}

Piège de nommage : le champ intuitif voice_reference_urls est rejeté (le validateur n'autorise que reference_audio_urls). Voir le tableau de sondage ci-dessous.

Production : callbacks et idempotence

Pour les workflows serveur, vous ne voulez généralement pas maintenir une boucle de polling. Ajoutez un callback au niveau supérieur (au même niveau que input, pas à l'intérieur), et hiapi enverra en POST la tâche terminée à votre URL :

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": { "prompt": "...", "reference_image_urls": ["..."] },
  "callback": { "url": "https://your-app.com/hooks/vidu", "when": "final" }
}
  • when n'accepte que "final" — vous ne recevez qu'une seule notification à l'état terminal (succès ou échec), jamais de notification de progression intermédiaire.
  • Le corps du callback est identique au payload renvoyé par GET /v1/tasks/<id>.
  • La livraison est retentée plusieurs fois et peut être dupliquée : dédupliquez donc par taskId et rendez votre gestionnaire idempotent.
  • Conservez le polling comme filet de sécurité pour couvrir les fenêtres où votre endpoint est brièvement injoignable.

Enregistrez le taskId dès que vous l'obtenez. Si votre poller rencontre une erreur réseau transitoire, réinterrogez l'id déjà enregistré — ne soumettez jamais à nouveau, sinon vous paierez un second rendu.

Ce que j'ai vérifié (contrat de schéma)

J'ai sondé le endpoint en direct avec des valeurs volontairement invalides (gratuit — les requêtes rejetées ne sont pas facturées, et une valeur invalide ne crée jamais de tâche). Le validateur est strict, renvoyant un objet plat { "code": 400, "error_code": "INVALID_REQUEST", "message": ... } :

Ce que vous envoyez Ce qui est renvoyé
resolution: "9999p" resolution: value must be one of '540p', '720p', '1080p', '2k', '4k'
duration: 999 duration: maximum: got 999, want 16
aspect_ratio: "banana" aspect_ratio: value must be one of '16:9', '9:16', '1:1', '4:3', '3:4'
voice_reference_urls: [...] additional properties 'voice_reference_urls' not allowed
quatre reference_audio_urls reference_audio_urls: maxItems: got 4, want 3
omission de reference_image_urls missing required field "reference_image_urls"

La structure d'entrée confirmée est donc :

Champ Obligatoire Valeurs
prompt oui texte
reference_image_urls oui 1 à 15 URL d'images
reference_audio_urls non 3 URL audio maximum (champ vocal)
resolution non 540p / 720p / 1080p / 2k / 4k
duration non entier 3–16 (secondes)
aspect_ratio non 16:9 / 9:16 / 1:1 / 4:3 / 3:4

duration est un entier (5), pas une chaîne — contrairement à certains autres modèles vidéo de hiapi qui attendent "6". Passer une clé supplémentaire est une erreur bloquante (additional properties ... not allowed), donc ne copiez pas les champs du schéma image-to-video.

Points d'attention côté sortie avant de brancher le téléchargement

  • Chaque séquence porte une piste audio AAC, même si vous n'avez pas envoyé de reference_audio_urls. Le vocabulaire sonore du prompt pilote la piste d'ambiance, donc ne supposez pas « pas de référence vocale = fichier muet ».
  • La sortie 4K de Vidu Q4 Preview est livrée en HEVC/H.265. Elle est lisible dans la plupart des lecteurs natifs, mais de nombreux navigateurs ne peuvent pas lire un MP4 H.265 en ligne dans une balise <video> — si vous l'intégrez dans une page web, réencodez en H.264. Les niveaux inférieurs renvoient du H.264 standard.

Modèle de prévisualisation — traitez les énumérations comme un instantané

vidu-q4-preview/reference-to-video est un modèle de prévisualisation : il est appelable aujourd'hui, mais n'est pas listé dans /v1/models, et son schéma de prévisualisation peut évoluer. Avant de traiter en gros volume, relancez une fois le sondage avec valeurs invalides (comme dans le tableau ci-dessus) pour confirmer que les énumérations sont toujours valides. La spécification de référence, ce sont les règles réellement appliquées par le validateur, complétées par la page du modèle.

Voir aussi

Questions fréquentes

Le reference-to-video est-il identique à l'image-to-video ? Non. Le reference-to-video fusionne 1 à 15 images fixes (avec éventuellement jusqu'à 3 extraits audio) en un seul plan composite ; l'image-to-video anime une seule première image. Ce sont des endpoints distincts avec des entrées différentes — le reference-to-video rejette même le champ image_url de l'image-to-video, et inversement.

Comment ajouter une voix ? Ajoutez reference_audio_urls (3 extraits maximum) et précisez-le dans le prompt (« ... avec la voix de l'audio de référence 1 »). Le nom du champ doit être exactement reference_audio_urls ; voice_reference_urls et les autres noms sont rejetés.

Quelle est la séquence la plus longue que je peux demander ? 16 secondes. duration est un entier de 3 à 16.

Dois-je forcément faire du polling ? Non — ajoutez callback: { "url": ..., "when": "final" } pour recevoir une notification unique à l'état terminal. Dédupliquez par taskId et conservez le polling comme filet de sécurité.

Combien coûte une séquence 4K ? La facturation est à la seconde, le tarif augmente avec la résolution, et le 4K est le niveau le plus élevé — voir la tarification hiapi. Le workflow pratique consiste à itérer d'abord en 720p, puis à ne refaire le rendu en 4k que pour les versions finales retenues.

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