# Seedance 2.5 Video Edit

> Edit video — replace subjects, add or remove objects, restyle scenes with reference images.

## Overview

- **Model ID**: `seedance-2.5-video-edit`
- **Workflow**: `seedance`
- **Provider**: ByteDance
- **Category**: Video → Video (video)
- **Output**: A video URL.
- **Tags**: new, premium, hot, video input, multi-image input, audio, 1080p, source length
- **Unified endpoint**: `POST https://api.picsart.com/workflows/v1/models/execute` (model id in the body)
- **Compatibility endpoint**: `POST https://api.picsart.com/workflows/seedance/execute` (vendor's own parameters)
- **Execution**: long-running — use the async submit/poll pair or the SDK, which polls for you
- **Model page**: https://picsart.com/api-platform/models/seedance-2.5-video-edit

## Pricing

Rates are in USD. Every row below is an exact rate for the settings it names — the columns are the settings that change the price for this model. Every response reports what was actually charged in `response.usage.credits`.

These rates are charged after the request finishes, on what it actually used.

| Tier | Use case | Rate |
| --- | --- | --- |
| 480p, 720p | Video → video | $0.0129 / 1K tokens |
| 1080p | Video → video | $0.0141 / 1K tokens |
| 480p, 720p | Image → video | $0.0214 / 1K tokens |
| 1080p | Image → video | $0.0234 / 1K tokens |

Published rates. Volume pricing, invoicing and annual agreements: https://picsart.com/api-platform/contact-sales

## Authentication

The SDK and the REST API authenticate with a Picsart API key sent as a bearer token. Create a key in the console at https://picsart.com/api-platform/dashboard/api-keys, keep it in a server-side environment variable, and never ship it in browser code or commit it.

```bash
export PICSART_API_KEY="YOUR_KEY"
```

```http
Authorization: Bearer $PICSART_API_KEY
```

The CLI and the MCP server do not use an API key: `gen-ai login` signs in through the browser once per machine and stores a token locally.

## Interfaces

- **SDK** — `@picsart/ai-sdk` (TypeScript, Node 20+, ESM). Type-safe `ai.generate()` / `ai.generateText()` with per-model parameter types; polls long jobs for you.
- **REST** — the API gateway at `https://api.picsart.com`. Sync `/execute`, or async `/submit` + `/{taskId}/result`.
- **CLI** — `@picsart/gen-ai` (`gen-ai`). Generate from a terminal, quote cost before spending, emit JSON for pipelines.
- **MCP** — the same models inside Claude Code, Cursor, Windsurf and other MCP hosts. Setup: https://picsart.com/gen-ai-mcp/

```bash
npm install @picsart/ai-sdk      # SDK
npm install -g @picsart/gen-ai   # CLI (also drives the MCP server)
```

## Unified API (recommended)

One parameter set, used by the SDK and by REST alike: the names below are what `ai.generate('seedance-2.5-video-edit', …)` takes, and what goes inside the inner `params` of a REST call. Over REST the model id travels in the body, not the path — one workflow, `v1/models`, fronts the whole catalogue.

### Execution modes

- **Sync** — `POST /workflows/v1/models/execute` returns the result in one call. Only for jobs that finish within ~20 seconds; otherwise it times out.
- **Async** — `POST /workflows/v1/models/submit` returns a task id; poll `GET /workflows/v1/models/{taskId}/result` until `response.status` is `COMPLETED` or `FAILED`. Task statuses: `ACCEPTED` · `IN_PROGRESS` · `COMPLETED` · `FAILED`.
- **SDK** — `ai.generate()` always awaits the finished result; polling is hidden.

Video jobs routinely outrun the sync limit: use async over REST, or the SDK, which polls for you.

### Input parameters

- **`prompt`** (`string`, _required_): Prompt
- **`aspectRatio`** (`string`, _optional_)
  - Default: `"adaptive"`
  - Options: `adaptive`
- **`resolution`** (`string`, _optional_)
  - Default: `"1080p"`
  - Options: `480p`, `720p`, `1080p`
- **`generateAudio`** (`boolean`, _optional_)
  - Default: `true`
- **`returnLastFrame`** (`boolean`, _optional_): Capture Last Frame
  - Default: `false`
- **`outputFormat`** (`string`, _optional_): Format
  - Default: `"mp4"`
  - Options: `mp4`, `mov`
- **`colorDepth`** (`string`, _optional_): Color Depth
  - Default: `"10bit"`
  - Options: `10bit`, `8bit`
- **`draft`** (`boolean`, _optional_): Draft
  - Default: `false`
- **`videoUrl`** (`string`, _required_): Source Video
  - Accepts: video URL, up to 30s
- **`imageUrls`** (`list<string>`, _optional_): Reference Images
  - Accepts: image URLs (max 30)

### Input JSON Schema

The inner `params` object. Over REST it is wrapped as `{ "params": { "model": "<id>", "params": <this> } }`; the SDK takes it directly.

```json
{
  "type": "object",
  "required": [
    "prompt",
    "videoUrl"
  ],
  "properties": {
    "prompt": {
      "type": "string",
      "description": "Prompt"
    },
    "aspectRatio": {
      "type": "string",
      "enum": [
        "adaptive"
      ],
      "default": "adaptive"
    },
    "resolution": {
      "type": "string",
      "enum": [
        "480p",
        "720p",
        "1080p"
      ],
      "default": "1080p"
    },
    "generateAudio": {
      "type": "boolean",
      "default": true
    },
    "returnLastFrame": {
      "type": "boolean",
      "default": false,
      "description": "Capture Last Frame"
    },
    "outputFormat": {
      "type": "string",
      "enum": [
        "mp4",
        "mov"
      ],
      "default": "mp4",
      "description": "Format"
    },
    "colorDepth": {
      "type": "string",
      "enum": [
        "10bit",
        "8bit"
      ],
      "default": "10bit",
      "description": "Color Depth"
    },
    "draft": {
      "type": "boolean",
      "default": false,
      "description": "Draft"
    },
    "videoUrl": {
      "type": "string",
      "format": "uri",
      "description": "Source Video"
    },
    "imageUrls": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uri",
        "description": "image URL"
      },
      "maxItems": 30,
      "description": "Reference Images"
    }
  },
  "additionalProperties": false
}
```

### Required parameters example

The required parameters plus the defaults that shape the output, as a REST body:

```json
{
  "params": {
    "model": "seedance-2.5-video-edit",
    "params": {
      "prompt": "A serene mountain lake at golden hour, ultra detailed",
      "aspectRatio": "adaptive",
      "resolution": "1080p",
      "videoUrl": "https://cdn.example.com/input.mp4"
    }
  }
}
```

### Response

The body is the gateway's status envelope: the output is at `response.result`, next to the task id, its status and the credits charged. Asset models return `url` plus an `items` array of results.

```json
{
  "status": "success",
  "response": {
    "id": "task_abc123",
    "status": "COMPLETED",
    "result": {
      "url": "https://cdn.picsart.com/…/result",
      "items": [
        {
          "url": "https://cdn.picsart.com/…/result"
        }
      ],
      "model": "seedance-2.5-video-edit"
    }
  }
}
```

What `ai.generate()` / `ai.generateText()` resolve to (the envelope already unwrapped):

```json
{
  "items": [
    {
      "url": "https://cdn.picsart.com/…/result"
    }
  ],
  "model": "seedance-2.5-video-edit"
}
```

### Usage examples

#### TypeScript (SDK)

```typescript
import { createClient } from '@picsart/ai-sdk';

const ai = createClient({
  apiKey: process.env.PICSART_API_KEY,
  apiUrl: 'https://api.picsart.com',
});

const result = await ai.generate('seedance-2.5-video-edit', {
  prompt: "A serene mountain lake at golden hour, ultra detailed",
  aspectRatio: "adaptive",
  resolution: "1080p",
  videoUrl: "https://cdn.example.com/input.mp4"
});

console.log(result.url); // video URL
```

#### cURL (sync)

```bash
curl -X POST 'https://api.picsart.com/workflows/v1/models/execute' \
  -H 'Authorization: Bearer $PICSART_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "params": {
    "model": "seedance-2.5-video-edit",
    "params": {
      "prompt": "A serene mountain lake at golden hour, ultra detailed",
      "aspectRatio": "adaptive",
      "resolution": "1080p",
      "videoUrl": "https://cdn.example.com/input.mp4"
    }
  }
}'
```

#### cURL (async: submit, then poll)

```bash
# 1. Submit the job
curl -X POST 'https://api.picsart.com/workflows/v1/models/submit' \
  -H 'Authorization: Bearer $PICSART_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "params": {
    "model": "seedance-2.5-video-edit",
    "params": {
      "prompt": "A serene mountain lake at golden hour, ultra detailed",
      "aspectRatio": "adaptive",
      "resolution": "1080p",
      "videoUrl": "https://cdn.example.com/input.mp4"
    }
  }
}'
# → { "status": "success", "response": { "id": "task_abc123" } }

# 2. Poll until response.status is COMPLETED
curl 'https://api.picsart.com/workflows/v1/models/task_abc123/result' \
  -H 'Authorization: Bearer $PICSART_API_KEY'
```

#### CLI

```bash
gen-ai login  # once per machine
gen-ai models info seedance-2.5-video-edit  # this model's parameters
gen-ai pricing seedance-2.5-video-edit  # quote before spending credits
gen-ai generate -m seedance-2.5-video-edit \
  -p "A serene mountain lake at golden hour" \
  --ar adaptive
```

## Compatibility API (vendor parameters)

Alongside the unified API, the `seedance` workflow takes ByteDance's own parameters exactly as the vendor defines them — nothing renamed or reshaped. It is the shortest path onto Picsart for request bodies already written against the vendor; the trade is that a request is written for one vendor, and the result comes back in the vendor's own shape. Same authentication.

- **Endpoint**: `POST https://api.picsart.com/workflows/seedance/execute` (sync) · `POST …/submit` + `GET …/{taskId}/result` (async)
- **SDK**: `ai.apis.run('seedance', params, { mode })` — params forwarded verbatim

### Vendor parameters

| Parameter | Type | Required | Default | Details |
| --- | --- | --- | --- | --- |
| `model` | `string` | no | `seedance_1_0_pro` | Model name that will be resolved to the actual endpoint · Options: `seedance_1_0_pro`, `seedance_1_0_pro_fast`, `seedance_1_5_pro`, `seedance_2_0`, `seedance_2_0_fast`, `seedance_2_0_mini`, `seedance_2_5` |
| `content` | `ContentItem[]` | no | — | Input content items. All models support text and image_url. v2 models also support video_url and audio_url, enabling edit-video and extend-video flows via reference_video role. Limits for v2 (2.0): max 9 images, 3 videos, 3 audios; audio cannot be the only modality. Limits for 2.5: max 30 images, 10 videos, 10 audios; audio-only input is allowed. Roles: first_frame, last_frame (v1+v2), reference_image/reference_video/reference_audio (v2 only). Asset references (asset://<id>) are accepted as URL values for v2. |
| └ `type` | `string` | yes | — | Type of content item · Options: `text`, `image_url`, `video_url`, `audio_url`, `draft_task` |
| └ `text` | `string` | no | — | Text content (only when type is text) |
| └ `image_url` | `object` | no | — | Image URL object (only when type is image_url) |
| └   `url` | `string` | yes | — | URL of the image |
| └ `video_url` | `object` | no | — | Video URL object (only when type is video_url). Only supported by v2 models. |
| └   `url` | `string` | yes | — | URL of the video |
| └ `audio_url` | `object` | no | — | Audio URL object (only when type is audio_url). Only supported by v2 models. |
| └   `url` | `string` | yes | — | URL of the audio |
| └ `draft_task` | `object` | no | — | Draft task object (only when type is draft_task). seedance_2_5 only: renders the final 1080p video from a previously generated 480p draft, referenced by draft_task.id. The final reuses the draft's prompt, inputs, ratio, duration and audio; anything else sent with it is passed to the vendor as-is, which rejects what a final does not take (other content items, ratio, duration, generate_audio, draft: true, a resolution other than 1080p). resolution defaults to 1080p. |
| └   `id` | `string` | yes | — | The id of a succeeded Seedance 2.5 draft, as returned by the draft: true request in its draft_task. Valid for 7 days. Pass the draft_task object back unchanged. |
| └ `role` | `string` | no | — | Role of the content item (first_frame, last_frame, reference_image, reference_video, reference_audio) · Options: `first_frame`, `last_frame`, `reference_image`, `reference_video`, `reference_audio` |
| `draft` | `boolean` | no | — | Draft mode, step 1 (seedance_2_5 only): generate a cheap 480p preview to check scene structure, shots and motion. resolution defaults to 480p (the vendor rejects any other). Requires options.drive — the draft is saved there (the file backs the reference, with its expiry on the seedance~draftExpiresAt attribute) and a draft without it is rejected. The result carries a draft_task object — pass it back unchanged within 7 days as a single { type: "draft_task", draft_task } content item (step 2) to render the final video with the same model, at 1080p. Billed as a regular 480p generation, and the final at 1080p for the draft's input (if any) plus output seconds. |
| `resolution` | `string` | no | — | Video resolution (480p, 720p, 1080p, 4k). 1080p supported by seedance_1_0_pro, seedance_1_0_pro_fast, seedance_2_0 and seedance_2_5 (NOT seedance_2_0_fast, NOT seedance_2_0_mini). 4k supported by seedance_2_0 only (H.265/HEVC, 10-bit). seedance_2_5 supports 480p, 720p and 1080p. Affects billing. · Options: `480p`, `720p`, `1080p`, `4k` |
| `ratio` | `string` | no | — | Video aspect ratio. "adaptive" lets the model choose based on input. For seedance_2_5, first/last-frame generation and video-to-video editing/extension tasks (a video input) require "adaptive" — the worker forces it for those (output proportions follow the input), so any explicit ratio is ignored there — unless omni_reference_task_type is set to anything but "auto", in which case the ratio is sent as-is. Text-to-video and reference-to-video keep the provided ratio. · Options: `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `21:9`, `adaptive` |
| `output_format` | `string` | no | — | Output video container format. seedance_2_5 only. "mp4" (default) is the general-purpose H.264/AAC container; "mov" is a professional H.264 4:4:4 / PCM container with higher color fidelity and larger files. "mp4_8bit" is an mp4 guaranteed to be 8-bit H.264: only 1080p comes back from the vendor as 10-bit H.265/HEVC (which most browsers and editors cannot decode), so at 1080p the video is re-encoded — adding processing time to the request — and at every other resolution the value changes nothing, the vendor already delivers 8-bit. · Options: `mp4`, `mov`, `mp4_8bit` |
| `omni_reference_task_type` | `string` | no | — | Task type hint, seedance_2_5 only. Omni-reference tasks are one of three subtasks: reference-to-video, video editing and video extension, each with its own parameter constraints. "auto" (vendor default) lets the model infer the subtask from the inputs and prompt; a request incompatible with the inferred one fails asynchronously, after the task was created (InvalidParameter.TaskTypeConstraint). An explicit value makes the vendor validate that subtask's constraints at submit, rejecting a non-conforming request immediately; with an explicit value the worker also stops forcing ratio to "adaptive", so the provided ratio goes out as-is and an incompatible one fails at submit. "reference": generate a new video from reference images / videos / audio — no ratio or duration constraint. "edit": edit an original video's visuals or audio — content needs at least one reference_video of 4–30 seconds, ratio must be "adaptive" and duration -1. "extend": extend an original video forward or backward — content needs at least one reference_video and ratio must be "adaptive". · Options: `auto`, `reference`, `edit`, `extend` |
| `duration` | `object \| object` | no | — | Duration in seconds: 3-12 (v1), 4-15 (v2 / 2.0), 4-30 (2.5), or -1 for auto (seedance_1_5_pro and v2 only). Sent to the vendor as-is and billed as-is (charged per second). Input videos are billed too: the usage amount is the total input video duration plus the output duration. When omitted or -1, the vendor picks the length (following the source video for a video input); the output is charged up front at the model's max (an edit's at its source videos' length) and settled to the served length after generation. For seedance_2_5 editing tasks the vendor may require -1. |
| `generate_audio` | `boolean` | no | — | Include synchronized audio. Supported by seedance_1_5_pro and v2 models. v2 defaults to true when omitted; pass false to disable. Affects billing. |
| `return_last_frame` | `boolean` | no | — | Return the last frame of the generated video as a separate image (populates last_frame_url). Supported by all models, including v2 (seedance_2_0 / seedance_2_0_fast / seedance_2_0_mini) — used for last-frame / face-chaining flows. |
| `watermark` | `boolean` | no | `false` | Whether to add AI generated watermark |
| `camerafixed` | `boolean` | no | — | Fix the camera during generation. v1 models only, ignored for v2. |
| `options` | `object` | no | — | Options controlling safety checks and drive integration |
| └ `safety_checks` | `object` | no | — | Safety check settings |
| └   `enabled` | `boolean` | no | — | Whether to run content moderation. Defaults to true. |
| └ `drive` | `object` | no | — | Save result to Picsart Drive |
| └   `name` | `string` | yes | — | File name in Picsart Drive |
| └   `attributes` | `object` | no | — | Custom attributes to attach to the file |
| └   `folder` | `object` | no | — | Target folder in Picsart Drive |
| └ `inputs_transformation` | `object` | no | — | Input transformation settings |
| └   `downscale_oversized_images` | `boolean` | no | — | Whether to downscale oversized input images. Defaults to false. |

### Example request body

```json
{
  "params": {
    "content": [
      {
        "type": "text"
      }
    ]
  }
}
```

### Usage examples

#### TypeScript (`ai.apis.run`)

```typescript
import { createClient, ApiRunMode } from '@picsart/ai-sdk';

const ai = createClient({
  apiKey: process.env.PICSART_API_KEY,
  apiUrl: 'https://api.picsart.com',
});

// Calls the 'seedance' workflow directly — params are sent as-is.
const { result, usage } = await ai.apis.run('seedance', {
  content: [
    {
      type: "text"
    }
  ]
}, {
  mode: ApiRunMode.SYNC,
});

console.log(result); // workflow-specific output
console.log(usage?.credits); // amount charged, in $
```

#### cURL (sync)

```bash
curl -X POST 'https://api.picsart.com/workflows/seedance/execute' \
  -H 'Authorization: Bearer $PICSART_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "params": {
    "content": [
      {
        "type": "text"
      }
    ]
  }
}'
```

#### cURL (async: submit, then poll)

```bash
# 1. Submit the job
curl -X POST 'https://api.picsart.com/workflows/seedance/submit' \
  -H 'Authorization: Bearer $PICSART_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "params": {
    "content": [
      {
        "type": "text"
      }
    ]
  }
}'
# → { "status": "success", "response": { "id": "wf_abc123" } }

# 2. Poll until response.status is COMPLETED
curl 'https://api.picsart.com/workflows/seedance/wf_abc123/result' \
  -H 'Authorization: Bearer $PICSART_API_KEY'
```

### Response

Over HTTP the vendor-shaped result arrives inside the gateway envelope at `response.result`:

```json
{
  "status": "success",
  "response": {
    "result": {
      "video_url": "https://cdn.picsart.com/…/result.mp4",
      "last_frame_url": "https://cdn.picsart.com/…/result.jpg",
      "output_format": "…",
      "draft_task": {},
      "mimeType": "video/mp4",
      "driveFile": {}
    }
  }
}
```

`ai.apis.run()` unwraps that envelope and resolves to `{ result, usage }`:

```json
{
  "result": {
    "video_url": "https://cdn.picsart.com/…/result.mp4",
    "last_frame_url": "https://cdn.picsart.com/…/result.jpg",
    "output_format": "…",
    "draft_task": {},
    "mimeType": "video/mp4",
    "driveFile": {}
  }
}
```

## Additional resources

- Model page: https://picsart.com/api-platform/models/seedance-2.5-video-edit
- Try it: https://picsart.com/api-platform/models/seedance-2.5-video-edit/playground
- SDK: https://picsart.com/api-platform/models/seedance-2.5-video-edit/sdk
- REST API (unified): https://picsart.com/api-platform/models/seedance-2.5-video-edit/api
- Compatibility API (vendor parameters): https://picsart.com/api-platform/models/seedance-2.5-video-edit/advanced
- Pricing: https://picsart.com/api-platform/models/seedance-2.5-video-edit/pricing
- This document: https://picsart.com/api-platform/models/seedance-2.5-video-edit/llms.txt
- All models: https://picsart.com/api-platform/models
- Docs — quickstart https://picsart.com/api-platform/docs/quickstart, authentication https://picsart.com/api-platform/docs/authentication, SDK https://picsart.com/api-platform/docs/sdk, REST https://picsart.com/api-platform/docs/api-reference, CLI https://picsart.com/api-platform/docs/cli, MCP https://picsart.com/api-platform/docs/mcp
- CLI reference: https://picsart.github.io/picsart-mcp-cli-docs/guide/introduction
