F-04 Génération vidéo
Brique F de la plateforme Enterprise AI. Technologie : Workers GPU spécialisés (modèles vidéo ouverts, par exemple Wan ou LTX-Video sous licence compatible) + adaptateurs de fournisseurs via /v1/gateway/video/generations. Version anglaise : ../../en/bricks/F-04-video-generation.md.
Rôle et responsabilités
- Génération texte vers vidéo et image vers vidéo avec durée et taille (résolution) explicites ; le FPS et le mode ne sont pas des paramètres de requête de l'API.
- Planifier les jobs sur des pools GPU dédiés (node selectors, tolerations, scaling KEDA sur la file).
Position et interactions
- Chemin d'exécution : workflow asynchrone long avec réservation.
- Estimation (H-03) -> réservation (H-01) -> job GPU -> confirmation avec GPU-secondes mesurées -> média stocké avec provenance.
- Les adaptateurs spécialisés sont listés par GET /v1/adapters (brique B).
Part open source et part développée
- Open source réutilisé : Modèles de diffusion vidéo ouverts, pipelines Diffusers, FFmpeg pour le multiplexage.
- Développé dans la plateforme : Orchestration des jobs, ordonnanceur de pools GPU, événements de progression, provenance, normalisation des adaptateurs fournisseurs.
Modèle de données
Tables du Control Plane (schéma eai) : eai.media, eai.multimodal_jobs, eai.quota_reservations, eai.gpu_samples, eai.usage_events.
Chaque table de tenant a tenant_id uuid NOT NULL et une politique de sécurité au niveau des lignes sur current_setting('app.tenant_id', true)::uuid. ClickHouse usage_events est la réplique analytique de eai.usage_events (ReplacingMergeTree par event_id).
Contrat : contracts/v1/multimodal-contract.schema.json (schema_version 1.0). L'usage est toujours remonté avec contracts/v1/usage-event.schema.json, l'audit avec contracts/v1/audit-event.schema.json.
Endpoints d'API
| Méthode | Chemin |
|---|---|
| POST | /v1/multimodal/video/generate |
| POST | /v1/gateway/video/generations |
| GET | /v1/gateway/video/generations/{id} |
| GET | /v1/multimodal/jobs/{id} |
POST /v1/multimodal/video/generate
Requête :
{
"model": "video-gen-gpu",
"prompt": "15 second product teaser, slow dolly shot",
"seconds": 15,
"size": "1280x720"
}
Réponse :
{
"job_id": "mmj_G15",
"status": "queued",
"estimated": {
"amount": "1.80",
"currency": "EUR"
},
"reservation_id": "qres_51"
}
POST /v1/gateway/video/generations
Requête :
{
"model": "provider-video",
"prompt": "Product teaser",
"seconds": 8,
"size": "1280x720"
}
Réponse :
{
"id": "vid_88",
"status": "in_progress"
}
GET /v1/gateway/video/generations/{id}
Réponse :
{
"id": "vid_88",
"status": "completed",
"media_id": "med_VID9"
}
GET /v1/multimodal/jobs/{id}
Réponse :
{
"job_id": "mmj_V01",
"operation": "video_process",
"status": "succeeded",
"outputs": {
"frames": 118,
"audio_media_id": "med_AUD7"
},
"attempts": 1
}
Exemples SDK
Python
from enterprise_ai import EnterpriseAI
client = EnterpriseAI(base_url="<control-plane-url>", api_key="eai_live_xxx", tenant="acme", locale="fr")
with client.quotas.reservation(agent_id="agt_ap", amount="1.80", currency="EUR") as r:
result = client.multimodal.video.generate("Teaser", model="video-gen-gpu", seconds=15)
r.commit(cost=result.get("cost_measured")) # released automatically on exception
estimate = client.finops.estimate("openai", usage_type="llm", model_id="gpt-4o-mini", units={"input_tokens": 12000, "output_tokens": 2000})
client.multimodal.video.generate("Product teaser", model="video-gen-gpu", seconds=15, size="1280x720")
client.gateway.video(model="provider-video", prompt="Product teaser", seconds=8)
client.gateway.video_status("vid_88")
client.multimodal.job(job_id="mmj_V01")
TypeScript
import { EnterpriseAI } from "@enterprise-ai/sdk";
const client = new EnterpriseAI({ baseUrl: "<control-plane-url>", apiKey: process.env.EAI_API_KEY, tenant: "acme", locale: "fr" });
await client.multimodal.generateVideo({ model: "video-gen-gpu", prompt: "Product teaser", seconds: 15, size: "1280x720" });
await client.gateway.video.generate({ model: "provider-video", prompt: "Product teaser", seconds: 8 });
await client.gateway.video.get({ id: "vid_88" });
await client.multimodal.getJob("mmj_V01");
Java
EnterpriseAIClient client = EnterpriseAIClient.builder()
.baseUrl("<control-plane-url>")
.apiKey(System.getenv("EAI_API_KEY"))
.tenant("acme")
.locale(Locale.FRENCH)
.build();
client.multimodal().generateVideo(Map.of("model", "video-gen-gpu", "prompt", "Product teaser", "seconds", 15, "size", "1280x720"));
client.gateway().videoGenerations(Map.of("model", "provider-video", "prompt", "Product teaser", "seconds", 8));
client.gateway().videoGeneration("vid_88");
client.multimodal().job("mmj_V01");
Go
client, err := eai.NewClient(eai.WithBaseURL("<control-plane-url>"), eai.WithAPIKey(os.Getenv("EAI_API_KEY")), eai.WithTenant("acme"), eai.WithLocale("fr"))
if err != nil { log.Fatal(err) }
ctx := context.Background()
_, err = client.Multimodal.GenerateVideo(ctx, map[string]any{"model": "video-gen-gpu", "prompt": "Product teaser", "seconds": 15, "size": "1280x720"})
_, err = client.Gateway.VideoGenerations(ctx, map[string]any{"model": "provider-video", "prompt": "Product teaser", "seconds": 8})
_, err = client.Gateway.VideoGeneration(ctx, "vid_88")
_, err = client.Multimodal.Job(ctx, "mmj_V01")
// worker package: run a media worker consuming multimodal jobs
w, err := worker.New(worker.Config{Source: jobs, Handler: handle, Client: client, Concurrency: 2})
if err != nil { log.Fatal(err) }
err = w.Run(ctx)
Configuration
Variables d'environnement : EAI_VIDEO_GEN_URL, EAI_MULTIMODAL_API_KEY.
Clés de valeurs Helm (deploy/helm/enterprise-ai/values.yaml) : workers.items[name=video-gen].nodeSelector, workers.items[name=video-gen].keda.maxReplicaCount.
Sécurité
- Une génération au-dessus d'un seuil de coût exige une approbation (POST /v1/approvals) avant la réservation.
- La ressemblance avec des personnes réelles est refusée par politique sauf consentement enregistré.
- Tenant déduit de l'identifiant d'accès, jamais du corps ; sécurité au niveau des lignes PostgreSQL sur chaque table de tenant.
- Chaque mutation et décision de politique écrit un événement d'audit chaîné par hachage (G-11).
- Les erreurs utilisent l'enveloppe standard avec message_i18n en et fr.
Observabilité
- Événements de progression (pourcentage, étape) sur NATS et le job ; utilisation GPU jointe depuis les échantillons DCGM.
- traceparent W3C propagé, X-Request-Id renvoyé, les spans portent eai.tenant_id, eai.project, eai.agent_id, eai.run_id.
Unités FinOps
- usage_type video_generation : video_seconds, video_resolution, video_fps, video_mode ; les exécutions locales ajoutent gpu_seconds, gpu_memory_gb_seconds, energy_wh.
Modes de défaillance et résilience
- Préemption d'un nœud GPU spot -> reprise depuis le dernier checkpoint latent sauvegardé.
- La réservation expire pendant un job long -> prolongation automatique tant que les heartbeats continuent.
Adoption autonome
Une équipe média peut n'exploiter que les workers de génération vidéo et les briques FinOps, avec son propre pool GPU.
Tests d'acceptation
- Une requête 15 s 720p 24 fps renvoie une estimation, une réservation puis un média de 15 s.
- Annuler un job libère la réservation et n'enregistre que les GPU-secondes consommées.