Ir al contenido principal

El video a video de Wan 2.1 LoRA redibuja a partir de un prompt un clip que ya tienes, conservando su movimiento y su ritmo, con hasta tres archivos LoRA tuyos en el modelo de 14B de Alibaba. Salida en 480p o 720p con la forma de la fuente, sin nada filtrado.

Desde $0.24/solicitud

Playground

Enviar una solicitud

Inicio rápido

Los ejemplos usan las definiciones públicas de parámetros del endpoint seleccionado. Sustituye la clave de API y los medios de ejemplo, y envía la solicitud desde tu servidor.

SDK e integraciones
POSThttps://api.spicyapi.ai/api/v1/jobs/createTask

Autenticación de API

Guarda la clave de API en la variable de entorno del servidor SPICY_API_KEY. Usa autenticación Bearer y Content-Type: application/json en las solicitudes JSON.

Authorization: Bearer $SPICY_API_KEY
Resultado de ejemploUsar este ejemplo
# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
  -H "Authorization: Bearer $SPICY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
  -d '{
  "model": "alibaba/wan-2.1-lora/video-edit",
  "input": {
    "duration_seconds": 5,
    "prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
    "resolution": "480p",
    "video_url": "https://example.com/reference.mp4"
  }
}'

# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $SPICY_API_KEY"

Generado a partir del esquema de entrada de este modelo: el mismo con el que la API valida cada solicitud.

Parámetros de entrada

Incluye estos campos en el objeto input del cuerpo de la solicitud. Los nombres y tipos coinciden con la API. No supongas un valor predeterminado si no está indicado.

video_urlstringObligatorio

El clip de origen. Su movimiento y su ritmo se conservan; el resultado mantiene su forma y nunca es más largo que él. Debe ser un video: un enlace a una imagen no se rechaza y devuelve un clip de un solo cuadro que igualmente se factura.

Valor predeterminado
Sin especificar
Restricciones
minLength:1
format:"uri"
contentMediaType:["video/mp4","video/webm","video/quicktime"]
promptstringObligatorio

Obligatorio. Describe todo el resultado (sujeto, vestuario, lugar, luz, estilo), no solo el cambio. Las palabras activadoras primero, si tu LoRA las tiene.

Valor predeterminado
Sin especificar
Restricciones
minLength:1
seedintegerOpcional

Mantiene las ejecuciones comparables mientras cambias un LoRA o un scale a la vez. No promete un resultado idéntico.

Valor predeterminado
Sin especificar
Restricciones
minimum:0
maximum:2147483647
stepsintegerOpcional

Pasos de eliminación de ruido, de 1 a 40, 30 por defecto. Con menos pasos es más rápido y más suave. No afecta el precio.

Valor predeterminado
30
Restricciones
minimum:1
maximum:40
flow_shiftnumberOpcional

Desplazamiento del paso de tiempo de flow matching, de 1 a 10. Déjalo fuera para usar 3 en 480p y 5 en 720p; cámbialo solo cuando el autor de un LoRA recomiende un valor. No afecta el precio.

Valor predeterminado
Sin especificar
Restricciones
minimum:1
maximum:10
guidance_scalenumberOpcional

Con qué rigor el clip sigue el prompt, de 0 a 20, 5 por defecto. Subirlo mientras se bajan los pasos nos dio cuadros sobresaturados y llenos de artefactos. No afecta el precio.

Valor predeterminado
5
Restricciones
minimum:0
maximum:20
lorasarray<object>Opcional

Hasta tres entradas {path, scale} entrenadas para Wan 2.1 14B; path es un enlace directo público a un archivo .safetensors y scale va de 0 a 4 (1 por defecto). Cargar LoRA no cambia el precio.

Valor predeterminado
[]
Restricciones
maxItems:3
duration_secondsintegerOpcionalAfecta al precio

5 (por defecto) o 10. El resultado nunca es más largo que la fuente, pero 10 se factura a la tarifa de 10 segundos, así que úsalo solo con fuentes de 10 segundos o más. Las demás duraciones se rechazan.

Valor predeterminado
5
Valores permitidos
510
strengthnumberOpcional

Cuánto se aleja de la fuente, de 0.1 a 1, 0.9 por defecto. En nuestra prueba, 0.9 redibujó el clip y 0.5 lo devolvió casi sin cambios. No afecta el precio.

Valor predeterminado
0.9
Restricciones
minimum:0.1
maximum:1
resolutionstringOpcionalAfecta al precio

480p (por defecto) o 720p. 720p cuesta más por clip y tarda más; la forma sigue la de la fuente.

Valor predeterminado
"480p"
Valores permitidos
"480p""720p"
negative_promptstringOpcional

Lo que debe quedar fuera del clip, como desenfoque, dedos de más, texto o marcas de agua. Opcional, no afecta el precio.

Valor predeterminado
Sin especificar

Seguir la tarea

HTTP 202 significa que la tarea se aceptó, no que haya terminado. Guarda el taskId devuelto y consulta esa tarea. No crees otra mientras esperas el resultado.

Solicitud aceptada
HTTP/1.1 202 Accepted
Location: /api/v1/jobs/recordInfo?taskId=job_01k3m8x9q2z4v7n5p6r8s0t1w3

{
  "code": 200,
  "msg": "success",
  "request_id": "req_example_create",
  "data": {
    "taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "state": "queued",
    "estimatedCost": "0.750000"
  }
}

La respuesta de aceptación incluye la estimación para que tu aplicación pueda mostrar el mismo importe en el historial de tareas y en la facturación.

Consultar la tarea
curl --get "https://api.spicyapi.ai/api/v1/jobs/recordInfo" \
  --data-urlencode "taskId=$TASK_ID" \
  -H "Authorization: Bearer $SPICY_API_KEY"

Empieza consultando cada 2 segundos aproximadamente y ve espaciando los intentos. Párate en un estado final. Si se cae la conexión, consulta el taskId original. Vuelve a crear la tarea solo con la clave de idempotencia y el cuerpo originales.

O recibe el resultado por callback
import { verifyWebhook } from "@spicyapi/sdk";

// express.raw keeps the bytes we signed; express.json never matches.
app.post("/hooks/spicy", express.raw({ type: "application/json" }), (req, res) => {
  const { payload } = verifyWebhook({
    rawBody: req.body,
    timestamp: req.header("X-Webhook-Timestamp"),
    signature: req.header("X-Webhook-Signature"),
    payloadVersion: Number(req.header("X-Webhook-Payload-Version")),
    secret: process.env.SPICY_WEBHOOK_SECRET,
  });
  res.status(200).end();
  void handleFinishedTask(payload);
});

Pasa callBackUrl al crear la tarea y recibirás el registro terminado por POST, sin un bucle de consultas de estado. Cada entrega lleva X-Webhook-Timestamp, X-Webhook-Signature y X-Webhook-Payload-Version. La firma es un HMAC-SHA256 en base64 sobre taskId.timestamp.sha256(body), así que debes verificarla con los bytes originales: si analizas el JSON y vuelves a serializarlo, los bytes cambian y la verificación falla. Las entregas fallidas se reintentan, de modo que el mismo taskId puede llegar dos veces; haz que tu manejador sea idempotente. Responde 2xx primero y haz el trabajo después: un manejador lento se trata como una entrega fallida.

Leer el resultado

Procesa output solo cuando state sea succeeded. Si falla, consulta errorCode, errorMessage y request_id. Los costos y estados de ejemplo no representan una factura real.

Ejemplo de respuesta completada
{
  "code": 200,
  "msg": "success",
  "request_id": "req_example_record",
  "data": {
    "taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "model": "alibaba/wan-2.1-lora/video-edit",
    "state": "succeeded",
    "output": {
      "assets": [
        {
          "key": "tasks/2026/08/28/job_01k3m8x9q2z4v7n5p6r8s0t1w3/3f7a1c9e5b2d48f0a6c1e3d5b7f9a1c3.mp4",
          "mime": "video/mp4",
          "url": "https://example.r2.cloudflarestorage.com/results/job_01k3m8x9q2z4v7n5p6r8s0t1w3/result.mp4?X-Amz-Signature=SIGNATURE_FROM_RESPONSE",
          "expiresAt": "2026-08-28T12:20:08.000Z"
        }
      ]
    },
    "cost": "0.750000",
    "settled": true,
    "createdAt": "2026-08-28T12:00:00Z",
    "completedAt": "2026-08-28T12:00:30Z"
  }
}

Para cada archivo disponible, abre o descarga assets[].url directamente, sin la cabecera Authorization de la API. El enlace firmado expira en expiresAt: vuelve a consultar la tarea para renovarlo mientras el archivo siga dentro del periodo de conservación. Un archivo pendiente o no disponible no trae URL. Trata los enlaces firmados como datos privados.

SDK e integraciones

Usa SpicyAPI en tu app, terminal, asistente de IA o flujo visual. Elige una guía de configuración.

Úsalo en ComfyUI

Instala los nodos de SpicyAPI desde ComfyUI Manager o con el comando de abajo y busca Wan 2.1 LoRA · Video to Video en el lienzo. El nodo tiene las mismas opciones que esta página y muestra su precio antes de ejecutarse.

cd ComfyUI/custom_nodes
git clone https://github.com/spicyapi-ai/comfyui-spicyapi