HiAPI
Blog

Tutorial

Cómo usar la API kling-3.0-omni/transformation: repintado de video con curl y Python

Oct 14, 2026
Cómo usar la API kling-3.0-omni/transformation: repintado de video con curl y Python

kling-3.0-omni/transformation es el modelo de video a video de Kling 3.0 Omni: proporcionas un video de origen y un prompt de texto, y reescribe la apariencia de ese video —escena, estilo, sujeto— conservando el movimiento y la temporalidad originales. En hiapi lo invocas a través del mismo endpoint asíncrono unificado que el resto de los modelos generativos: POST /v1/tasks. Esta guía ofrece una tabla de parámetros verificada en la práctica, solicitudes curl listas para copiar y pegar, un cliente Python completo (que sondea y descarga el resultado) y los patrones de producción que necesitas antes de integrarlo en una aplicación real (callbacks, idempotencia, manejo de errores).

Todos los nombres de campo, valores de enumeración y estructuras de respuesta que aparecen a continuación se han contrastado con la API real.

Lo que vas a construir + requisitos previos

Un pequeño programa: enviar una tarea de repintado, esperar a que termine y descargar el .mp4 repintado. Necesitas dos cosas:

  1. Una clave de API de hiapi. Créala en la consola de hiapi: su formato es similar a sk-.... Cada solicitud usa Authorization: Bearer sk-<your-key>.
  2. Una URL de video de origen accesible públicamente. El modelo descarga tu video en el servidor, así que debe ser una URL pública http(s) (tu propio CDN, R2/S3 con objetos públicos, etc.), no una ruta de archivo local. Solo se permite una URL.

El modelo y sus parámetros

La estructura externa de la solicitud es {"model": ..., "input": {...}}. El schema de input es estricto: solo acepta los siguientes tres campos, y cualquier campo adicional se rechaza con un 400.

Campo Tipo Obligatorio Descripción
prompt string Sí Describe el estilo/escena/sujeto objetivo. La intensidad del repintado también se ajusta aquí: no existe un parámetro numérico strength/fidelity.
video_urls array Sí Exactamente una URL pública de video de origen (minItems es 1, maxItems es 1).
resolution string enum Sí Uno de 720p, 1080p, 4k.

Algunos puntos que suelen inducir a error:

  • No hay parámetro duration. La duración y la relación de aspecto de la salida siguen al video de origen (3–15,5 segundos), y la facturación se calcula según la duración final de la salida.
  • El id del modelo incluye -omni: kling-3.0-omni/transformation (otros endpoints Omni usan kling-3.0/...). Usa directamente ese id como valor de model.
  • La intensidad del repintado se controla mediante el prompt. Para un cambio ligero, escribe «repintado ligero, conserva los rasgos faciales y la iluminación»; para un cambio radical, escribe «reimagina por completo como dibujo animado 2D estilo cel-shading».

Ejemplo mínimo funcional (curl)

# 1) Crear la tarea de repintado
curl -s https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-3.0-omni/transformation",
    "input": {
      "prompt": "Repinta esta escena con un estilo de animación acuarela hecha a mano, con textura de papel suave y luz cálida de atardecer; conserva el movimiento de cámara y el sujeto originales.",
      "video_urls": ["https://your-cdn.example.com/source-clip.mp4"],
      "resolution": "720p"
    }
  }'
# -> {"code":200,"data":{"taskId":"tk-hiapi-01..."},"message":"success"}

# 2) Sondear la tarea hasta que alcance un estado terminal
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01... \
  -H "Authorization: Bearer sk-<your-key>"
# data.status pasa por: queued -> handling -> archiving -> success
# Tras el éxito, data.output[0].url es el .mp4 repintado

El id de tarea que usas para sondear proviene de data.taskId en la respuesta de creación, no del id de nivel superior. Las cadenas de estado son queued / handling / archiving / success (terminal) o fail; no supongas que son succeeded/completed.

Cliente Python completo (crear → sondear → descargar)

import os
import time
import requests

API_KEY = os.environ["HIAPI_KEY"]            # tu clave sk-...
BASE = "https://api.hiapi.ai"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}


def create_restyle(source_video_url: str, prompt: str, resolution: str = "720p") -> str:
    body = {
        "model": "kling-3.0-omni/transformation",
        "input": {
            "prompt": prompt,
            "video_urls": [source_video_url],   # exactamente una URL pública
            "resolution": resolution,           # "720p" | "1080p" | "4k"
        },
    }
    r = requests.post(f"{BASE}/v1/tasks", json=body, headers=HEADERS, timeout=30)
    r.raise_for_status()
    data = r.json()
    if data.get("code") != 200:
        raise RuntimeError(f"Envío rechazado: {data}")
    return data["data"]["taskId"]


def wait_for_video(task_id: str, poll_s: int = 10, timeout_s: int = 900) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{BASE}/v1/tasks/{task_id}", headers=HEADERS, timeout=30)
        r.raise_for_status()
        data = r.json()["data"]
        status = data["status"]
        if status == "success":
            return data["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"Tarea fallida: {data.get('error')}")
        time.sleep(poll_s)                      # queued / handling / archiving
    raise TimeoutError(f"{task_id} no terminó en {timeout_s} segundos")


if __name__ == "__main__":
    task_id = create_restyle(
        source_video_url="https://your-cdn.example.com/source-clip.mp4",
        prompt=(
            "Repinta esta escena con un estilo de animación acuarela hecha a mano, textura de papel suave, "
            "luz cálida de atardecer; conserva el movimiento de cámara y el sujeto originales."
        ),
        resolution="720p",
    )
    print("Tarea:", task_id)

    url = wait_for_video(task_id)
    print("URL del video:", url)

    # El archivo de salida está en temp.hiapi.ai y caduca (aprox. 7 días). Descárgalo ahora mismo.
    clip = requests.get(url, timeout=120).content
    with open("restyled.mp4", "wb") as f:
        f.write(clip)
    print("restyled.mp4 guardado", len(clip), "bytes")

Coloca la clave en una variable de entorno y ejecuta:

export HIAPI_KEY=sk-<your-key>
python restyle.py

Patrones de producción

Usa callbacks en lugar de sondear con frecuencia

Para cualquier caso que vaya más allá de un script, registra un webhook para no mantener un bucle de sondeo. callback es un campo de nivel superior, al mismo nivel que model e input, y nunca debe colocarse dentro de input:

{
  "model": "kling-3.0-omni/transformation",
  "input": {
    "prompt": "Repinta esta escena con un estilo de dibujo animado 2D cel-shading, contornos gruesos; conserva el movimiento original.",
    "video_urls": ["https://your-cdn.example.com/source-clip.mp4"],
    "resolution": "1080p"
  },
  "callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
  • callback.when solo acepta final (el valor predeterminado). Cuando la tarea alcanza un estado terminal, se encola una vez y se dispara tanto en éxito como en fallo. La semántica de entrega es al menos una vez, por lo que el mismo callback aún puede llegar varias veces (ver más abajo).
  • El cuerpo del POST entregado es idéntico al objeto data que se obtiene mediante GET /v1/tasks/<id>, así que tu handler puede leer status, output[].url y error sin volver a consultar.
  • Colocar callback dentro de input falla al enviar, con el error additional properties 'callback' not allowed (el schema de input de cada modelo es estricto).

Idempotencia y semántica de entrega

Los callbacks son al menos una vez y no exactamente una vez: el mismo taskId puede llegar varias veces. Usa taskId como clave de tu handler y haz que el paso de «marcar como completado + almacenar el video» sea idempotente. hiapi reintenta los callbacks no 2xx/que agotan el tiempo con el ritmo inmediato → +1 minuto → +5 minutos → +20 minutos, hasta 4 intentos; tu endpoint debe devolver HTTP 2xx para detener los reintentos.

Descarga la salida de inmediato

data.output[0].url apunta a temp.hiapi.ai y lleva un expireAt (marca de tiempo Unix, TTL de aprox. 7 días). Una vez expirado, el objeto se elimina y esa URL devuelve 404: volver a sondear la tarea devuelve la misma URL, pero no regenera el archivo. En cuanto la tarea tenga éxito, copia los bytes a tu propio almacenamiento de inmediato.

Manejo de errores

Tres formas de fallo que debes ramificar:

  • Error de solicitud (HTTP 400): estructura plana, no se creó la tarea: {"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: resolution: value must be one of '720p', '1080p', '4k'"}
  • Fallo de autenticación (HTTP 401): estructura anidada: {"error":{"code":"permission_denied","type":"hiapi_error", ...}}
  • Tarea fallida: el envío devuelve 200 y un taskId, pero un sondeo posterior muestra data.status == "fail" con data.error. Las tareas fallidas no se cobran (si la tarea termina fallando, se reembolsa el importe retenido). Los casos en que la URL de origen no es accesible o no se puede descargar se reflejan aquí.

Coste

kling-3.0-omni/transformation se factura por segundos de salida, y la tarifa varía según la resolución que solicites (720p $0,143 por segundo, 1080p $0,193 por segundo, 4k $0,479 por segundo, verificado el 21 de octubre de 2026). Antes de procesar videos en lote, consulta la página de precios de hiapi en vivo para obtener la tarifa actual por segundo: el coste de las tareas de video se acumula mucho más rápido que el de las tareas de imagen.

Lecturas relacionadas

Preguntas frecuentes

¿Cómo se controla la intensidad del repintado? Mediante el prompt, no mediante parámetros. No existe ningún campo strength, fidelity ni creativity. Para ediciones ligeras escribe «repintado ligero, conserva el rostro y la iluminación»; para ediciones radicales escribe «reimagina por completo como

Artículos relacionados

Ver todos los artículos →

Empieza a crear con artefactos de IA persistentes

Consigue tu API key y llama a modelos de imagen, vídeo y audio a través de una única API basada en tasks.

Leer la documentación de la API