Skip to main content
A diferencia de chat e imágenes, video toma 30s a 5min dependiendo del modelo. Por eso el flujo es asíncrono con dos endpoints:
POST /v1/videos/generations    → Crea job, regresa job_id en ms
GET  /v1/videos/{job_id}        → Estado actual + URL del video si completed

Modelos disponibles

IDProviderPrecio/segDuración defaultMaxAudio
google/veo-3.1Google$0.408s8s
google/veo-3Google$0.208s8s
fal/veo-3.1fal.ai$0.408s8s
fal/runway-gen-4fal.ai$0.055s10s
fal/luma-ray-2fal.ai$0.205s9s
fal/kling-2fal.ai$0.045s10s
fal/hailuo-02fal.ai$0.046s10s

Patrón de uso

import time
from openai import OpenAI

client = OpenAI(
    base_url="https://api.geekhub.mx/v1",
    api_key="ghub_sk_live_xxx",
)

# 1. Submit
job = client.post("/videos/generations", body={
    "model": "fal/kling-2",
    "prompt": "Un colibrí bebiendo de una flor de cempasúchil al amanecer",
    "duration": 5,
})
job_id = job["id"]
print(f"Job created: {job_id}")

# 2. Poll
while True:
    status = client.get(f"/videos/{job_id}")
    if status["status"] == "completed":
        print(f"Done: {status['video_url']}")
        break
    if status["status"] == "failed":
        print(f"Failed: {status['error']}")
        break
    time.sleep(15)  # Cada 15 seg
El polling es lazy: el job no avanza solo (Kling/Veo procesan en su lado). Pero el provider sigue trabajando aunque no polees — cuando polees verás el estado actualizado.

Estados del job

StatusSignificado
pendingJob creado en nuestra DB, aún no enviado al provider
processingProvider está renderizando
completedListo. video_url apunta a tu Supabase Storage
failedHubo error. error describe la causa
Solo cuando llega a completed cobramos el saldo (al precio del modelo × duración × markup × FX). Si el job falla, no se cobra.

Storage

Igual que imágenes: los videos terminados se suben a tu Supabase Storage (generated-videos) con URLs persistentes y públicas por UUID.

Próximos pasos

POST /v1/videos/generations

Submit de un nuevo video job.

GET /v1/videos/{id}

Poll del estado del job.