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

# Génération vidéo Gemini Omni 1.2 Flash

> Vidéo à partir de texte ou d’images, références de sujets, interpolation entre images initiale et finale, montage et prolongation. Jusqu’à 4K, 24fps, avec audio.

> [!NOTE]
>
> La génération à partir de texte ou d’images accepte un entier de 3 à 15 secondes, avec 10 par défaut. L’interpolation entre images initiale et finale et le segment ajouté lors d’une prolongation sont limités à 10 secondes. Le montage ignore `duration` et conserve la durée de la vidéo source. Une vidéo en entrée est modifiée par défaut ; la prolongation exige `"omni_reference_task_type": "extend"`.

```bash cURL theme={null}
curl --request POST \
  --url https://api.apimart.ai/v1/videos/generations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "gemini-omni-1.2-flash",
    "prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 15
  }'
```

```python Python theme={null}
import time
import requests

base_url = "https://api.apimart.ai"
headers = {"Authorization": "Bearer <token>"}
payload = {
    "model": "gemini-omni-1.2-flash",
    "prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 15,
}
response = requests.post(
    f"{base_url}/v1/videos/generations",
    headers=headers, json=payload, timeout=30,
)
response.raise_for_status()
task_id = response.json()["data"][0]["task_id"]
print(task_id)

deadline = time.monotonic() + 600
while time.monotonic() < deadline:
    response = requests.get(
        f"{base_url}/v1/tasks/{task_id}", headers=headers, timeout=30,
    )
    response.raise_for_status()
    task = response.json()["data"]
    if task["status"] == "completed":
        print(task["result"]["videos"][0]["url"][0])
        break
    if task["status"] == "failed":
        raise RuntimeError(task["error"]["message"])
    time.sleep(5)
else:
    raise TimeoutError(f"Continue polling task {task_id}")
```

```javascript JavaScript theme={null}
const baseUrl = "https://api.apimart.ai";
const headers = {
  Authorization: "Bearer <token>",
  "Content-Type": "application/json",
};
const response = await fetch(`${baseUrl}/v1/videos/generations`, {
  method: "POST",
  headers,
  signal: AbortSignal.timeout(30_000),
  body: JSON.stringify({
    model: "gemini-omni-1.2-flash",
    prompt: "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
    aspect_ratio: "16:9",
    resolution: "720p",
    duration: 15,
  }),
});
if (!response.ok) throw new Error(await response.text());
const taskId = (await response.json()).data[0].task_id;
console.log(taskId);

async function waitForTask(taskId) {
  const deadline = Date.now() + 600_000;
  while (Date.now() < deadline) {
    const response = await fetch(`${baseUrl}/v1/tasks/${taskId}`, {
      headers,
      signal: AbortSignal.timeout(30_000),
    });
    if (!response.ok) throw new Error(await response.text());
    const task = (await response.json()).data;
    if (task.status === "completed") return task.result.videos[0].url[0];
    if (task.status === "failed") throw new Error(task.error.message);
    await new Promise(resolve => setTimeout(resolve, 5000));
  }
  throw new Error(`Continue polling task ${taskId}`);
}
console.log(await waitForTask(taskId));
```

```json 200 theme={null}
{
  "code": 200,
  "data": [
    {
      "status": "submitted",
      "task_id": "task_01EXAMPLE"
    }
  ]
}
```

## Authentification

**Authorization** `string` *required*

Utilisez un jeton Bearer. Obtenez une clé sur la [page de gestion des clés API](https://apimart.ai/keys) et envoyez les requêtes avec `Content-Type: application/json`.

## Paramètres de requête

**model** `string` *required*

Doit être `gemini-omni-1.2-flash`.

**prompt** `string` *required*

Instructions textuelles obligatoires : décrivez la scène pour le texte vers vidéo, ou les mouvements, le style et les modifications pour les autres modes. `prompt` est obligatoire même avec des images de référence, des images initiale/finale, une vidéo ou `extend_from_task_id`. Son absence renvoie HTTP 400.

**duration** `integer` (default: 10)

Durée de sortie pour la génération à partir de texte ou d’images, entier de `3` à `15`, avec `10` par défaut. L’interpolation initiale/finale et la prolongation acceptent uniquement `3`–`10` secondes. Pour une prolongation, il s’agit de la durée ajoutée ; la vidéo renvoyée contient l’original et le segment ajouté. Le montage ignore `duration` et conserve la durée de la vidéo source. Une valeur de paramètre hors plage fait échouer la tâche avec `invalid_duration`.

**resolution** `string` (default: 720p)

`360p` / `720p` / `1080p` / `4k`, sans distinction de casse ; `2160p` équivaut à `4k`. Les sorties `1080p` et `4k` sont suréchantillonnées. La résolution influe sur les tokens de sortie et le montant réservé. Les autres valeurs font échouer la tâche avec `invalid_resolution`.

**aspect\_ratio** `string` (default: 16:9)

Uniquement `16:9` (paysage, par défaut) et `9:16` (portrait). Les autres valeurs sont traitées comme `16:9`.

**image\_urls** `string[]`

Images de référence uniquement sous forme d’URL HTTP(S) directes et accessibles publiquement. Les Data URL et Base64 ne sont pas pris en charge. Une image sert de départ ; plusieurs images servent de références de sujets. Maximum 10 images au total, images initiale/finale comprises. Pour les personnages, privilégiez au plus 2 personnages et 3 images chacun, soit 6 images au maximum.

**first\_frame\_image** `string`

Image initiale. Seule, elle sert de point de départ ; avec `last_frame_image`, elle active l’interpolation entre les deux images. Seules les URL HTTP(S) directes et accessibles publiquement vers une image sont acceptées.

**last\_frame\_image** `string`

Image finale ; exige `first_frame_image`, sinon la tâche échoue avec `invalid_frame_images`. Utilisez le même ratio pour les deux images, correspondant à `aspect_ratio`. Seules les URL HTTP(S) directes et accessibles publiquement vers une image sont acceptées.

**image\_with\_roles** `object[]`

Tableau d’images avec rôles, équivalent aux champs directs des images initiale/finale. Choisissez une seule méthode. Toutes les images utilisées comptent dans la limite totale de 10.

**Élément du tableau**

**url** `string` *required*

Seules les URL HTTP(S) directes et accessibles publiquement vers une image sont acceptées.

**role** `string` *required*

`first_frame` désigne l’image initiale et `last_frame` l’image finale. Les autres rôles sont des références. Une image finale exige une image initiale.

**video\_urls** `string[]`

Vidéo à modifier ou prolonger : 1 clip maximum, de 15 secondes au plus. Seules les URL HTTP(S) directes et accessibles publiquement vers la vidéo sont acceptées. Les Data URL et Base64 ne sont pas pris en charge. Le mode par défaut est le montage.

**omni\_reference\_task\_type** `string` (default: auto)

Type de tâche : `auto` (par défaut, déduit des entrées) / `edit` (montage) / `extend` (prolongation) / `reference` (plusieurs images de référence). Accepte aussi `text_to_video` / `image_to_video` / `reference_to_video`. Sans valeur ou avec `auto`, `video_urls` et `extend_from_task_id` déclenchent un montage par défaut. Pour prolonger, indiquez explicitement `extend`.

**extend\_from\_task\_id** `string`

Référencez l’ID de votre précédente tâche de génération pour réutiliser la vidéo sans la téléverser. Le mode par défaut est le montage. Avec `"omni_reference_task_type": "extend"`, un segment de 10 secondes au maximum est ajouté à la fin.

## Fonctionnalités et limites

* La sortie est à 24fps, avec dialogues, musique ou effets sonores. Décrivez l’audio souhaité dans `prompt`.
* L’entrée audio, les system prompts, `temperature` et les paramètres de prompt négatif ne sont pas pris en charge. Écrivez les exclusions directement dans `prompt`.
* Restrictions régionales du fournisseur : dans l’EEE, en Suisse et au Royaume-Uni, le montage ou la prolongation de vidéos téléversées et la modification d’images contenant des mineurs ne sont pas pris en charge.
* Toutes les sorties comportent un filigrane invisible SynthID.

## Exemples

Envoyez chaque corps JSON à `POST /v1/videos/generations`. Remplacez les URL et ID d’exemple par vos propres médias et tâches utilisables.

### Vidéo portrait de 15 secondes en 4K

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "Aerial shot over a misty mountain lake at sunrise, birds flying, slow forward camera move.",
  "aspect_ratio": "9:16",
  "resolution": "4k",
  "duration": 15
}
```

### Image vers vidéo et références de sujets

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "The cat playfully bats at the ball of yarn.",
  "image_urls": [
    "https://example.com/cat.png",
    "https://example.com/yarn.png"
  ],
  "duration": 12
}
```

### Interpolation entre images initiale et finale

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "Smooth transition, camera slowly pushes in.",
  "first_frame_image": "https://example.com/start.jpg",
  "last_frame_image": "https://example.com/end.jpg",
  "aspect_ratio": "16:9",
  "duration": 8
}
```

### Déclaration des images avec des rôles

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "A smooth cinematic transition from sunrise to a starry night.",
  "image_with_roles": [
    {
      "url": "https://example.com/sunrise.jpg",
      "role": "first_frame"
    },
    {
      "url": "https://example.com/night.jpg",
      "role": "last_frame"
    }
  ],
  "duration": 8
}
```

### Montage vidéo

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "Make the violin invisible. Keep everything else the same.",
  "video_urls": [
    "https://example.com/clip.mp4"
  ]
}
```

Le montage conserve la durée de la vidéo source ; `duration` est sans effet.

Utilisez des instructions de montage courtes et précises. Pour une modification locale, ajoutez `Keep everything else the same`.

### Prolongation d’une tâche existante

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "The camera continues panning across the mountains.",
  "extend_from_task_id": "task_01PREVIOUS",
  "omni_reference_task_type": "extend",
  "duration": 8
}
```

Pour prolonger une vidéo téléversée, remplacez `extend_from_task_id` par `video_urls` et conservez `"omni_reference_task_type": "extend"`. La vidéo renvoyée contient l’original suivi du segment ajouté. `duration` contrôle uniquement la durée ajoutée, limitée à 10 secondes ; seules les secondes ajoutées sont facturées. Par exemple, une source de 5 secondes avec `duration: 4` produit une vidéo d’environ 9 secondes.

## Réponse de soumission et suivi de tâche

Une soumission réussie renvoie HTTP 200 ; récupérez `data[0].task_id`. Interrogez le [statut de la tâche](https://docs.apimart.ai/fr/api-reference/tasks/status.md) toutes les 5–10 secondes jusqu’à `completed` ou `failed`. Prévoyez une attente globale de 10 minutes. Si le client expire, continuez à interroger la tâche initiale sans la soumettre à nouveau.

```bash theme={null}
curl --request GET \
  --url https://api.apimart.ai/v1/tasks/task_01EXAMPLE \
  --header 'Authorization: Bearer <token>'
```

Durées indicatives : une vidéo de 15 secondes en 360p prend environ 30 secondes, et en 4K environ 5 minutes. Vérifiez toujours le statut de la tâche.

```json theme={null}
{
  "code": 200,
  "data": {
    "id": "task_01EXAMPLE",
    "status": "completed",
    "progress": 100,
    "result": {
      "videos": [
        {
          "url": [
            "https://cdn.example.com/gemini_omni_video.mp4"
          ]
        }
      ]
    }
  }
}
```

`data` dans la réponse de suivi est l’objet tâche. `data.result.videos[0].url` est un tableau ; la première URL est `data.result.videos[0].url[0]`. Elle permet la lecture ou le téléchargement. Archivez le fichier pour le conserver durablement. `data.cost` est le montant final en USD.

| Statut | Action |
| - | - |
| `pending` / `processing` | Continuez le suivi ; consultez `data.progress`. |
| `completed` | Récupérez l’URL et enregistrez la vidéo. |
| `failed` | Consultez `data.error.message`. Les tâches échouées ne sont pas facturées. |

## Facturation et solde réservé

Facturation par tokens : la résolution détermine les tokens de sortie vidéo par seconde. Pour la génération à partir de texte ou d’images, `duration` définit la durée de sortie. Le montage ignore ce paramètre et conserve la durée de la source ; la prolongation l’utilise uniquement pour le segment ajouté. Consultez les [tarifs APIMart](https://apimart.ai/pricing).

À la soumission, le solde réservé dépend de la résolution et de `max(10, duration)` secondes ; une vidéo en entrée entraîne une estimation de 15 secondes. La réserve n’est pas le montant final. Après réussite, elle est ajustée à l’utilisation réelle ; le résultat figure dans `data.cost`.

La prolongation est facturée uniquement sur les secondes ajoutées. Un échec n’est pas facturé. Un solde insuffisant pour la réserve renvoie HTTP 402.

## Gestion des erreurs

Les erreurs de paramètres (`invalid_*` / `unsupported_*`) font immédiatement passer la tâche à `failed`, sans facturation. Vérifiez le statut même après une soumission réussie.

| Erreur / statut | Cause et action |
| - | - |
| `invalid_duration` | `duration` hors de 3–15, ou interpolation / prolongation dépassant 10 secondes. Utilisez un entier autorisé. |
| `invalid_task_type` | Valeur non prise en charge pour `omni_reference_task_type`. Utilisez `auto` / `edit` / `extend` / `reference` ; `text_to_video` / `image_to_video` / `reference_to_video` sont aussi acceptés. |
| `invalid_resolution` | Utilisez `360p` / `720p` / `1080p` / `4k` ; `2160p` est également accepté. |
| `invalid_frame_images` | Seule une image finale a été fournie. Ajoutez l’image initiale. |
| `unsupported_image_count` | Plus de 10 images, images initiale/finale comprises. Réduisez leur nombre. |
| `unsupported_video_count` | Plus d’une vidéo en entrée. Conservez un seul clip de 15 secondes au maximum. |
| `HTTP 400` | Le paramètre obligatoire `prompt` est absent. Fournissez des instructions textuelles même avec un média. |
| `HTTP 401` | Clé invalide. Vérifiez Authorization. |
| `HTTP 402` | Solde insuffisant pour la réserve. Rechargez ou réduisez la résolution. |
| `HTTP 429` | Limite de requêtes atteinte. Réessayez avec un délai croissant. |
| `status: failed` | Erreur du fournisseur ou rejet lié au contenu. Lisez `data.error.message` et ajustez la requête. |

## Questions fréquentes

### `prompt` est-il obligatoire avec des images ou une vidéo ?

Oui. Tous les modes exigent `prompt`, y compris la génération depuis des images, l’interpolation initiale/finale, le montage, la prolongation et la réutilisation d’une vidéo via `extend_from_task_id`. Son absence renvoie HTTP 400.

### Puis-je envoyer directement des images ou une vidéo en Base64 ?

Non. `image_urls`, `first_frame_image`, `last_frame_image`, `image_with_roles[].url` et `video_urls` acceptent uniquement des URL HTTP(S) directes et accessibles publiquement. N’envoyez pas de `data:image/...`, de `data:video/...` ni de chaînes Base64 brutes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.