bytedance/seedance-2.0-mini/video-extendDesde 19 créditos por un clip de 5 segundos· Extender video

Continúa un clip con Seedance 2.0 Mini: el último fotograma de tu video abre un nuevo segmento de 4 a 15 segundos con sonido, y recibes un solo archivo con el original y la continuación unidos, en 480p o 720p.

Llámalo con el nombre de modelo bytedance/seedance-2.0-mini/video-extend en POST /jobs/createTask, desde 19 créditos por un clip de 5 segundos (0,19 US$). Las cuentas nuevas reciben 30 créditos gratis para que lo pruebes primero en el Playground.

  • Crear video
  • Imagen a video
  • Referencias a video
  • Extender video
  • Hasta 720p
  • Clips de 4 a 15 s
  • Con sonido
  • Fotograma inicial y final
  • Hasta 9 imágenes de referencia
  • 6 relaciones de aspecto
Nombre del modelobytedance/seedance-2.0-mini/video-extend
EndpointPOST https://api.popnow.ai/api/v1/jobs/createTask
# 1. Create the task. Keep the Idempotency-Key if you retry after a network error.
export IDEMPOTENCY_KEY="$(uuidgen)"
curl -X POST https://api.popnow.ai/api/v1/jobs/createTask \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -d '{
  "model": "bytedance/seedance-2.0-mini/video-extend",
  "input": {
    "video_url": "https://media.popnow.ai/effects/flower-bloom-1abd6efb.mp4",
    "resolution": "720p",
    "duration_seconds": 5,
    "generate_audio": true
  }
}'

# 2. Copy data.taskId from the response, then poll until state is succeeded, failed, canceled or expired.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $POPNOW_API_KEY"

El input se genera a partir del esquema de abajo, así que pasa la validación tal cual. Cambia el prompt y los enlaces por los tuyos.

Precio

OpciónCréditos por segundo≈ USD
resolution 480p3,690,037 US$
enable_web_search trueresolution 480p5,40,054 US$
resolution 720p7,940,079 US$
enable_web_search trueresolution 720p10,80,11 US$

1 crédito = 0,01 $ · Todas las opciones y su precio: GET /models/bytedance/seedance-2.0-mini/video-extend

Cada tarea se redondea al alza a créditos enteros, así que una ejecución en el nivel más bajo cuesta 19 créditos por un clip de 5 segundos (0,19 US$).

Límites

Duración del clip
4–15 s
Resoluciones
480p · 720p
Clip de entrada más largo
60 s

Parámetros

Estos campos salen del mismo esquema con el que validamos cada petición. Los campos que no aparecen se rechazan.

  • video_urlstringObligatorio

    El clip con el que trabajar.

    Rango
    1 – … chars · video/mp4, video/webm, video/quicktime
  • promptstringOpcional

    Describe what happens next: the action that follows, the camera move and the sound.

    Rango
    1 – … chars
  • last_image_urlstringOpcional

    Fotograma final opcional, para que el clip termine justo donde quieres.

    Rango
    image/jpeg, image/png, image/webp, image/gif
  • resolutionstringOpcionalCambia el precio

    Tamaño de salida. Más grande es más nítido y cuesta más.

    Por defecto
    "720p"
    Valores permitidos
    "480p""720p"
  • duration_secondsintegerOpcionalCambia el precio

    Cuánto dura el clip. Se cobra por segundo.

    Por defecto
    5
    Valores permitidos
    -1456789101112131415
  • generate_audiobooleanOpcionalCambia el precio

    Añade sonido acorde a la imagen: voces, ambiente y efectos.

    Por defecto
    true
  • enable_web_searchbooleanOpcionalCambia el precio

    Consulta primero la web para fechas, lugares y datos actuales.

    Por defecto
    false
  • seedintegerOpcional

    Repite el mismo número para obtener un resultado reproducible.

    Rango
    0 – 2147483647
  • bitrate_modestringOpcional

    Encoding bitrate of the new segment: standard, or high for crisper detail and a larger file.

    Por defecto
    "standard"
    Valores permitidos
    "standard""high"
  • watermarkbooleanOpcional

    Add the model’s visible "AI generated" watermark to the new segment.

    Por defecto
    false
Esquema JSON sin procesar
{
  "additionalProperties": false,
  "properties": {
    "bitrate_mode": {
      "default": "standard",
      "description": "Encoding bitrate of the new segment: standard, or high for crisper detail and a larger file.",
      "enum": [
        "standard",
        "high"
      ],
      "type": "string"
    },
    "duration_seconds": {
      "default": 5,
      "description": "Length of the new segment in seconds. The source clip is added on top and is not billed.",
      "enum": [
        -1,
        4,
        5,
        6,
        7,
        8,
        9,
        10,
        11,
        12,
        13,
        14,
        15
      ],
      "type": "integer"
    },
    "enable_web_search": {
      "default": false,
      "description": "Let the model search the web for information related to the prompt before rendering. Requests with it on are billed at the web-search rate.",
      "type": "boolean"
    },
    "generate_audio": {
      "default": true,
      "description": "Generate sound for the new segment. The source keeps its own sound either way.",
      "type": "boolean"
    },
    "last_image_url": {
      "contentMediaType": [
        "image/jpeg",
        "image/png",
        "image/webp",
        "image/gif"
      ],
      "description": "Optional target end frame: the new segment lands on this picture.",
      "type": "string"
    },
    "prompt": {
      "description": "Describe what happens next: the action that follows, the camera move and the sound.",
      "minLength": 1,
      "type": "string"
    },
    "resolution": {
      "default": "720p",
      "description": "Resolution of the new segment; match your source clip.",
      "enum": [
        "480p",
        "720p"
      ],
      "type": "string"
    },
    "seed": {
      "description": "Random seed. Omit to let the model pick one.",
      "maximum": 2147483647,
      "minimum": 0,
      "type": "integer"
    },
    "video_url": {
      "contentMediaType": [
        "video/mp4",
        "video/webm",
        "video/quicktime"
      ],
      "description": "The clip to continue: MP4, MOV or WebM, up to 60 seconds. Its final frame becomes the opening frame of the new segment, and the result is your clip with the new segment joined on.",
      "format": "uri",
      "minLength": 1,
      "type": "string"
    },
    "watermark": {
      "default": false,
      "description": "Add the model’s visible \"AI generated\" watermark to the new segment.",
      "type": "boolean"
    }
  },
  "required": [
    "video_url"
  ],
  "type": "object"
}

Respuestas, consultas y callbacks

Todos los modelos funcionan igual: crea una tarea y luego consulta su estado o espera el callback.

Consulta el precio primero

cURL
curl -X POST https://api.popnow.ai/api/v1/jobs/quote \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "bytedance/seedance-2.0-mini/video-extend",
  "input": {
    "video_url": "https://media.popnow.ai/effects/flower-bloom-1abd6efb.mp4",
    "resolution": "720p",
    "duration_seconds": 5,
    "generate_audio": true
  }
}'

El mismo cuerpo que createTask. Devuelve el cargo esperado y el máximo posible, sin ejecutar nada.

Aceptada

HTTP
HTTP/1.1 202 Accepted

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "state": "queued"
  },
  "request_id": "req_example_create"
}

HTTP 202 significa que la tarea se aceptó y los créditos quedan reservados, todavía sin cobrar. El cargo final nunca supera la reserva.

Consultar estado

cURL
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $POPNOW_API_KEY"

Consulta cada pocos segundos espaciando cada vez más y para cuando state sea succeeded, failed, canceled o expired.

Tarea terminada

JSON
{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "model": "bytedance/seedance-2.0-mini/video-extend",
    "state": "succeeded",
    "output": {
      "assets": [
        {
          "url": "https://cdn.popnow.ai/tasks/task_01k3m8x9q2z4v7n5p6r8s0t1w3/output.mp4?signature=FROM_RESPONSE",
          "expiresAt": "2026-10-17T12:20:00Z",
          "mime": "video/mp4",
          "width": 1280,
          "height": 720,
          "durationSeconds": 5
        }
      ]
    },
    "settled": true
  },
  "request_id": "req_example_record"
}

Descarga desde la url antes de expiresAt. ¿Necesitas un enlace nuevo más tarde? Pídelo con POST /common/download-url.

Verificar un callback

Node.js
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
import express from "express";

const app = express();
// express.raw keeps the exact bytes that were signed; express.json would not match.
app.post("/hooks/popnow", express.raw({ type: "application/json" }), (req, res) => {
  const timestamp = req.header("X-Webhook-Timestamp");
  const signature = req.header("X-Webhook-Signature") ?? "";
  const body = JSON.parse(req.body.toString("utf8"));
  const taskId = body.data?.taskId ?? body.task_id;
  const digest = createHash("sha256").update(req.body).digest("hex");
  const expected = createHmac("sha256", process.env.POPNOW_WEBHOOK_SECRET)
    .update(`${taskId}.${timestamp}.${digest}`)
    .digest("base64");
  const ok = expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
  // Check the signature first, then reject anything older than five minutes.
  if (!ok || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return res.status(401).end();
  res.status(200).end(); // answer fast, then fetch the task and store its files
});

Con callBackUrl te enviamos la tarea terminada. Comprueba la firma sobre el cuerpo sin procesar antes de fiarte de ella.

Enviar un archivo local

cURL
curl -X POST https://api.popnow.ai/api/v1/common/upload-url \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contentType": "image/png", "bytes": 482113}'

# PUT the file bytes to data.uploadUrl with every header in data.headers, then commit it:
curl -X POST https://api.popnow.ai/api/v1/files/$FILE_ID/commit \
  -H "Authorization: Bearer $POPNOW_API_KEY"
# The commit returns a popnow://f/... reference. Put it in any image, video or
# audio field of the task input instead of a public https URL.

Los enlaces https públicos funcionan tal cual. Los archivos locales pasan antes por upload-url y commit.