> ## Documentation Index
> Fetch the complete documentation index at: https://docs.venice.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Génération vidéo

> Générez des vidéos à partir de prompts ou d'images de départ via l'API asynchrone de Venice : soumettez, suivez et téléchargez la vidéo finie.

La génération vidéo est asynchrone. Soumettez une tâche, enregistrez le `queue_id`, puis interrogez `/video/retrieve` jusqu'à ce que la réponse soit `video/mp4`.

## Endpoints

| Endpoint               | Objectif                                   | Requis |
| ---------------------- | ------------------------------------------ | ------ |
| `POST /video/quote`    | Obtenir le prix en USD avant la génération | Non    |
| `POST /video/queue`    | Soumettre une requête de génération        | Oui    |
| `POST /video/retrieve` | Sonder le statut ou télécharger la vidéo   | Oui    |
| `POST /video/complete` | Supprimer la vidéo du stockage             | Non    |

## Étape 1 : Mettre en file d'attente la génération

**Requête :**

```bash theme={"system"}
POST https://api.venice.ai/api/v1/video/queue
Authorization: Bearer $VENICE_API_KEY
Content-Type: application/json

{
  "model": "wan-2.5-preview-text-to-video",
  "prompt": "A gondola gliding through Venice canals at sunset",
  "duration": "5s",
  "resolution": "720p",
  "aspect_ratio": "16:9"
}
```

**Réponse (200) :**

```json theme={"system"}
{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000"
}
```

Pour les modèles Grok Imagine Private, la réponse de mise en file d'attente inclut un champ supplémentaire `download_url` :

```json theme={"system"}
{
  "model": "grok-imagine-text-to-video-private",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000",
  "download_url": "https://private-share.venice.ai/v1/share/read/..."
}
```

`download_url` est une URL pré-signée que vous utilisez pour télécharger la vidéo finie au lieu de la lire depuis la réponse retrieve. Elle n'est renvoyée qu'une seule fois dans la réponse de mise en file d'attente, alors persistez-la à côté du `queue_id`. Cela s'applique aux quatre variantes Grok Imagine Private :

* `grok-imagine-text-to-video-private`
* `grok-imagine-image-to-video-private`
* `grok-imagine-reference-to-video-private`
* `grok-imagine-video-to-video-private`

Contrairement aux variantes publiques `grok-imagine-*-video`, les modèles Grok Imagine Private ne sont pas facturés pour les rejets dus à la modération de contenu, donc vous ne payez que pour les générations réussies.

Enregistrez `model`, `queue_id` et `download_url` (s'il est présent) pour tous les appels ultérieurs.

### Liens de téléchargement privés

Pour les modèles privés, `download_url` est la manière de récupérer le fichier fini une fois la tâche terminée. Le lien est **éphémère et à usage unique** : il sert à vous livrer le MP4, pas à servir d'URL durable ou largement partagée.

Si un téléchargement est interrompu, vous pouvez **réessayer le même `GET` plusieurs fois** depuis le même environnement jusqu'à ce que le fichier soit terminé. Ces nouvelles tentatives servent à récupérer après des coupures réseau — pas à sonder le même lien indéfiniment, le partager entre de nombreux clients ou l'intégrer comme une URL média permanente. De tels schémas se manifestent souvent sous forme de **`429`** ou de **`410`**, ce qui peut surprendre si vous vous attendiez à ce que le lien se comporte comme un hébergement de fichier classique.

Pour plus de fiabilité, **les requêtes `GET` doivent provenir d'un seul réseau client**. Une certaine souplesse est possible si votre IP change une fois (par exemple si vous déconnectez un VPN et réessayez), mais une large variation des IP sources ne fonctionnera généralement pas.

L'URL reste valide jusqu'à **24 heures**, ou jusqu'à ce que l'objet soit supprimé.

<Note>
  Si vous avez besoin d'une URL stable, d'une lecture publique ou d'un accès répété dans le temps, enregistrez d'abord le fichier dans **votre propre stockage** et servez-le à partir de là.
</Note>

**Confidentialité : révoquer le lien avec `DELETE`**

Lorsque vous avez fini de récupérer le fichier — ou si vous décidez de ne pas le conserver — vous pouvez appeler **`DELETE`** sur la même `download_url`. Aucune clé API Venice n'est requise pour cette requête. C'est facultatif mais **recommandé lorsque la confidentialité importe**, car certains proxys et middleboxes en dehors de Venice conservent des journaux des URL complètes, et supprimer le lien est le moyen le plus simple de réduire la fenêtre pendant laquelle l'URL pré-signée existe.

```bash theme={"system"}
curl -X DELETE "$DOWNLOAD_URL"
```

**Flux :** interrogez `/video/retrieve` jusqu'à `COMPLETED` → `GET` la `download_url` (réessayez légèrement si le transfert échoue) → enregistrez le fichier où nécessaire → `DELETE` la `download_url` si vous souhaitez invalider le lien → optionnellement, appelez `/video/complete` si vous utilisez toujours le nettoyage basé sur la file d'attente.

## Étape 2 : Sonder jusqu'à la fin

**Requête :**

```bash theme={"system"}
POST https://api.venice.ai/api/v1/video/retrieve
Authorization: Bearer $VENICE_API_KEY
Content-Type: application/json

{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000"
}
```

**La réponse dépend du statut :**

| Content-Type                          | Signification                   | Action                                                              |
| ------------------------------------- | ------------------------------- | ------------------------------------------------------------------- |
| `application/json`                    | Toujours en cours de traitement | Attendre 5 s, sonder à nouveau                                      |
| `video/mp4`                           | Terminé                         | Le corps de la réponse est le fichier vidéo                         |
| `application/json` avec `"COMPLETED"` | Terminé, vidéo non inline       | `GET` la `download_url` depuis la réponse de mise en file d'attente |

**Réponse de traitement (200, application/json) :**

```json theme={"system"}
{
  "status": "PROCESSING",
  "average_execution_time": 145000,
  "execution_duration": 53200
}
```

Les durées sont en millisecondes. Utilisez `average_execution_time` pour estimer l'attente restante.

**Réponse terminée (200, video/mp4) :**
Le corps de la réponse contient des données vidéo binaires brutes. Enregistrez-les dans un fichier.

**Réponse terminée (200, application/json avec `"COMPLETED"`) :**
Pour les modèles qui ont renvoyé une `download_url` au moment de la mise en file d'attente, retrieve renvoie toujours du JSON. Récupérez la vidéo avec `GET download_url` (sans en-tête d'authentification). Voir [Liens de téléchargement privés](#liens-de-t%C3%A9l%C3%A9chargement-priv%C3%A9s) pour comprendre comment ces URL fonctionnent, les nouvelles tentatives et le `DELETE` optionnel.

## Étape 3 : Nettoyage (optionnel)

Soit auto-suppression à la récupération :

```json theme={"system"}
{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000",
  "delete_media_on_completion": true
}
```

Soit appel à `/video/complete` après enregistrement :

```bash theme={"system"}
POST https://api.venice.ai/api/v1/video/complete
Authorization: Bearer $VENICE_API_KEY
Content-Type: application/json

{
  "model": "wan-2.5-preview-text-to-video",
  "queue_id": "123e4567-e89b-12d3-a456-426614174000"
}
```

**Réponse (200) :**

```json theme={"system"}
{
  "success": true
}
```

***

## Exemple complet

<CodeGroup>
  ```python Python theme={"system"}
  import os
  import time
  import requests

  API_KEY = os.environ.get("VENICE_API_KEY")
  BASE_URL = "https://api.venice.ai/api/v1"
  HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

  # Queue
  resp = requests.post(f"{BASE_URL}/video/queue", headers=HEADERS, json={
      "model": "wan-2.5-preview-text-to-video",
      "prompt": "A gondola gliding through Venice canals at sunset",
      "duration": "5s",
      "resolution": "720p",
      "aspect_ratio": "16:9"
  })
  data = resp.json()
  model, queue_id = data["model"], data["queue_id"]
  download_url = data.get("download_url")

  # Poll
  while True:
      resp = requests.post(f"{BASE_URL}/video/retrieve", headers=HEADERS,
                           json={"model": model, "queue_id": queue_id})
      if "video/mp4" in resp.headers.get("Content-Type", ""):
          with open("output.mp4", "wb") as f:
              f.write(resp.content)
          break
      if resp.json().get("status") == "COMPLETED" and download_url:
          with open("output.mp4", "wb") as f:
              f.write(requests.get(download_url).content)
          break
      time.sleep(5)

  # Cleanup
  requests.post(f"{BASE_URL}/video/complete", headers=HEADERS,
                json={"model": model, "queue_id": queue_id})
  ```

  ```javascript Node.js theme={"system"}
  const API_KEY = process.env.VENICE_API_KEY;
  const BASE_URL = "https://api.venice.ai/api/v1";
  const headers = {"Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json"};

  // Queue
  const queueResp = await fetch(`${BASE_URL}/video/queue`, {
      method: "POST", headers,
      body: JSON.stringify({
          model: "wan-2.5-preview-text-to-video",
          prompt: "A gondola gliding through Venice canals at sunset",
          duration: "5s", resolution: "720p", aspect_ratio: "16:9"
      })
  });
  const {model, queue_id, download_url} = await queueResp.json();

  // Poll
  while (true) {
      const resp = await fetch(`${BASE_URL}/video/retrieve`, {
          method: "POST", headers,
          body: JSON.stringify({model, queue_id})
      });
      if (resp.headers.get("Content-Type")?.includes("video/mp4")) {
          const fs = await import("fs");
          fs.writeFileSync("output.mp4", Buffer.from(await resp.arrayBuffer()));
          break;
      }
      const status = await resp.json();
      if (status.status === "COMPLETED" && download_url) {
          const fs = await import("fs");
          const video = await fetch(download_url);
          fs.writeFileSync("output.mp4", Buffer.from(await video.arrayBuffer()));
          break;
      }
      await new Promise(r => setTimeout(r, 5000));
  }

  // Cleanup
  await fetch(`${BASE_URL}/video/complete`, {
      method: "POST", headers,
      body: JSON.stringify({model, queue_id})
  });
  ```
</CodeGroup>

***

## Paramètres de la requête

### Requête Queue

| Paramètre         | Type    | Requis                         | Par défaut                                                     | Description                                                                                                                                                                  |
| ----------------- | ------- | ------------------------------ | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`           | string  | Oui                            | -                                                              | Identifiant du modèle. Utilisez `wan-2.5-preview-text-to-video` pour text-to-video, `wan-2.5-preview-image-to-video` pour image-to-video                                     |
| `prompt`          | string  | Oui                            | -                                                              | Ce qu'il faut générer. Max 2500 caractères                                                                                                                                   |
| `negative_prompt` | string  | Non                            | `"low resolution, error, worst quality, low quality, defects"` | Ce qu'il faut éviter                                                                                                                                                         |
| `duration`        | string  | Oui                            | -                                                              | `"5s"` ou `"10s"`                                                                                                                                                            |
| `resolution`      | string  | Non                            | `"720p"`                                                       | `"480p"`, `"720p"` ou `"1080p"`                                                                                                                                              |
| `aspect_ratio`    | string  | Conditionnel                   | -                                                              | Dépend du modèle. Requis pour les modèles qui exposent des options de ratio d'aspect ; omettre pour les modèles qui ne prennent pas en charge la sélection du ratio d'aspect |
| `audio`           | boolean | Conditionnel                   | `true` (lorsque pris en charge)                                | Valide uniquement pour les modèles avec `supportsAudioConfig: true` ; omettre pour les modèles sans prise en charge de configuration audio                                   |
| `image_url`       | string  | Uniquement pour image-to-video | -                                                              | URL ou URL data base64 de l'image source                                                                                                                                     |
| `audio_url`       | string  | Conditionnel                   | -                                                              | URL ou URL data base64 d'audio de référence pour les modèles qui prennent en charge l'entrée audio                                                                           |

La validation de la mise en file d'attente est spécifique au modèle. Vérifiez `/models?type=video` pour les champs de requête pris en charge par chaque modèle avant d'appeler `/video/queue`.

### Requête Quote

| Paramètre      | Type    | Requis       | Par défaut                      | Description                                                                                        |
| -------------- | ------- | ------------ | ------------------------------- | -------------------------------------------------------------------------------------------------- |
| `model`        | string  | Oui          | -                               | Identifiant du modèle à tarifer                                                                    |
| `duration`     | string  | Oui          | -                               | `"5s"` ou `"10s"`                                                                                  |
| `resolution`   | string  | Non          | `"720p"`                        | `"480p"`, `"720p"` ou `"1080p"`                                                                    |
| `aspect_ratio` | string  | Conditionnel | -                               | À inclure lorsque le modèle sélectionné prend en charge ou requiert la sélection du ratio d'aspect |
| `audio`        | boolean | Conditionnel | `true` (lorsque pris en charge) | Valide uniquement pour les modèles avec `supportsAudioConfig: true`                                |

### Requête Retrieve

| Paramètre                    | Type    | Requis | Par défaut | Description                                   |
| ---------------------------- | ------- | ------ | ---------- | --------------------------------------------- |
| `model`                      | string  | Oui    | -          | Depuis la réponse queue                       |
| `queue_id`                   | string  | Oui    | -          | Depuis la réponse queue                       |
| `delete_media_on_completion` | boolean | Non    | `false`    | Supprimer la vidéo après récupération réussie |

### Requête Complete

| Paramètre  | Type   | Requis | Description             |
| ---------- | ------ | ------ | ----------------------- |
| `model`    | string | Oui    | Depuis la réponse queue |
| `queue_id` | string | Oui    | Depuis la réponse queue |

***

## Image to Video

Pour les modèles image-to-video, transmettez l'image source via `image_url`. Le prompt décrit le mouvement souhaité, pas le contenu de l'image.

```json theme={"system"}
{
  "model": "wan-2.5-preview-image-to-video",
  "prompt": "Camera slowly zooms in as leaves rustle in the wind",
  "image_url": "https://example.com/image.jpg",
  "duration": "5s"
}
```

Ou avec base64 :

```json theme={"system"}
{
  "model": "wan-2.5-preview-image-to-video",
  "prompt": "Camera slowly zooms in as leaves rustle in the wind",
  "image_url": "data:image/jpeg;base64,/9j/4AAQ...",
  "duration": "5s"
}
```

***

## Devis de prix

Obtenez le coût exact avant la génération. Envoyez uniquement les entrées de tarification (`model`, `duration`, et optionnellement `resolution`, `aspect_ratio`, `audio`) :

**Requête :**

```json theme={"system"}
{
  "model": "wan-2.5-preview-text-to-video",
  "duration": "10s",
  "resolution": "1080p"
}
```

**Réponse :**

```json theme={"system"}
{
  "quote": 0.085
}
```

Le devis est en USD.

***

## Erreurs

| Statut | Renvoyé par                              | Signification                                                                                                      | Action                                                                                                                                                                                                                                     |
| ------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 400    | `queue`, `quote`, `retrieve`, `complete` | Paramètres invalides                                                                                               | Vérifiez le corps de la requête par rapport au schéma                                                                                                                                                                                      |
| 401    | `queue`, `retrieve`, `complete`          | Échec d'authentification                                                                                           | Vérifiez la clé API                                                                                                                                                                                                                        |
| 402    | `queue`                                  | Solde insuffisant                                                                                                  | Ajoutez des fonds                                                                                                                                                                                                                          |
| 404    | `retrieve`, `download_url`               | Média non trouvé (invalide, expiré ou supprimé)                                                                    | Vérifiez `model`/`queue_id` ou remettez en file d'attente                                                                                                                                                                                  |
| 410    | `download_url`                           | URL pré-signée expirée, entièrement utilisée ou révoquée (par exemple après `DELETE`)                              | Lancez une nouvelle génération si vous avez besoin d'un autre fichier ; chaque lien est intentionnellement éphémère                                                                                                                        |
| 429    | `download_url`                           | Limite de débit atteinte — souvent due à de nombreuses nouvelles tentatives ou récupérations répétées du même lien | Terminez le téléchargement (quelques nouvelles tentatives sont acceptables si la connexion lâche), enregistrez une copie locale, et utilisez `DELETE` si vous voulez effacer le lien ; conservez l'accès continu sur votre propre stockage |
| 413    | `queue`                                  | Charge utile trop volumineuse                                                                                      | Réduisez la taille de l'image/audio                                                                                                                                                                                                        |
| 422    | `queue`, `retrieve`                      | Violation de contenu                                                                                               | Modifiez le prompt                                                                                                                                                                                                                         |
| 500    | `queue`, `retrieve`, `complete`          | Échec d'inférence/traitement                                                                                       | Réessayez avec backoff ; contactez le support si persistant                                                                                                                                                                                |
| 503    | `retrieve`                               | Modèle à pleine capacité                                                                                           | Réessayez avec backoff                                                                                                                                                                                                                     |

***

## Stratégie de sondage

1. Sondez `/video/retrieve` à intervalle régulier (par exemple, toutes les 5 secondes)
2. Si le `Content-Type` est `application/json` et que le `status` est `"PROCESSING"`, attendez et sondez à nouveau. Utilisez `average_execution_time` et `execution_duration` (millisecondes) pour estimer le temps restant
3. Si le `Content-Type` est `video/mp4`, enregistrez le corps de la réponse comme fichier de sortie
4. Si le `Content-Type` est `application/json` et que le `status` est `"COMPLETED"`, faites un `GET` sur la `download_url` depuis la réponse queue pour récupérer la vidéo (voir [Liens de téléchargement privés](#liens-de-t%C3%A9l%C3%A9chargement-priv%C3%A9s))
5. Si vous avez utilisé `download_url`, envisagez un `DELETE` sur cette URL lorsque vous avez terminé pour réduire la durée d'existence de l'URL pré-signée ; puis définissez optionnellement `delete_media_on_completion: true` sur retrieve ou appelez `/video/complete` pour un nettoyage basé sur la file d'attente
6. Traitez `404` comme un média invalide, expiré ou supprimé ; traitez `500/503` avec des nouvelles tentatives/backoff

***

## Modèles disponibles

Voir [Modèles vidéo](/models/video) pour la liste actuelle des modèles et la tarification.
