# Mirelo SFX 2.0 (Video to Audio)

> Generate a soundtrack synced to your video with Mirelo SFX 2.0 — returns the audio track.

## Overview

- **Model ID**: `mirelo-sfx-2.0-video-to-audio`
- **Workflow**: `mirelo-ai/sfx2.0/video-to-audio`
- **Provider**: Mirelo
- **Category**: Video → Audio (audio)
- **Output**: An audio URL.
- **Tags**: video to audio, video required, sound effects
- **Unified endpoint**: `POST https://api.picsart.com/workflows/v1/models/execute` (model id in the body)
- **Compatibility endpoint**: `POST https://api.picsart.com/workflows/mirelo-ai/sfx2.0/video-to-audio/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/mirelo-sfx-2.0-video-to-audio

## Pricing

Live pricing for this model is not published yet. See https://picsart.com/pricing/ or the Pricing tab of the model page (https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/pricing).

## 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('mirelo-sfx-2.0-video-to-audio', …)` 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.

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

### Input parameters

- **`videoUrl`** (`string`, _required_): Source Video
  - Accepts: video URL
- **`prompt`** (`string`, _optional_): Prompt
  - Max length: 2000 characters
- **`negativePrompt`** (`string`, _optional_): Negative Prompt
  - Max length: 1000 characters
- **`preserveSpeech`** (`boolean`, _optional_): Preserve Speech
  - Default: `true`
- **`duration`** (`number`, _optional_)
  - Default: `10`
  - Range: 1–600 (step 1)
- **`count`** (`number`, _optional_)
  - Default: `2`
  - Options: `1`, `2`, `3`, `4`
- **`format`** (`string`, _optional_): Format
  - Default: `"wav"`
  - Options: `wav`, `mp3`, `aac`, `flac`
- **`bitrateKbps`** (`number`, _optional_): Audio Bitrate (kbps)
  - Range: 32–320 (step 1)
- **`seed`** (`number`, _optional_): Seed
  - Range: 0–2147483647 (step 1)

### 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": [
    "videoUrl"
  ],
  "properties": {
    "videoUrl": {
      "type": "string",
      "format": "uri",
      "description": "Source Video"
    },
    "prompt": {
      "type": "string",
      "maxLength": 2000,
      "description": "Prompt"
    },
    "negativePrompt": {
      "type": "string",
      "maxLength": 1000,
      "description": "Negative Prompt"
    },
    "preserveSpeech": {
      "type": "boolean",
      "default": true,
      "description": "Preserve Speech"
    },
    "duration": {
      "type": "number",
      "minimum": 1,
      "maximum": 600,
      "multipleOf": 1,
      "default": 10
    },
    "count": {
      "type": "number",
      "enum": [
        1,
        2,
        3,
        4
      ],
      "default": 2
    },
    "format": {
      "type": "string",
      "enum": [
        "wav",
        "mp3",
        "aac",
        "flac"
      ],
      "default": "wav",
      "description": "Format"
    },
    "bitrateKbps": {
      "type": "number",
      "minimum": 32,
      "maximum": 320,
      "multipleOf": 1,
      "description": "Audio Bitrate (kbps)"
    },
    "seed": {
      "type": "number",
      "minimum": 0,
      "maximum": 2147483647,
      "multipleOf": 1,
      "description": "Seed"
    }
  },
  "additionalProperties": false
}
```

### Required parameters example

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

```json
{
  "params": {
    "model": "mirelo-sfx-2.0-video-to-audio",
    "params": {
      "videoUrl": "https://cdn.example.com/input.mp4",
      "prompt": "A serene mountain lake at golden hour, ultra detailed",
      "duration": 10
    }
  }
}
```

### 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": "mirelo-sfx-2.0-video-to-audio"
    }
  }
}
```

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

```json
{
  "items": [
    {
      "url": "https://cdn.picsart.com/…/result"
    }
  ],
  "model": "mirelo-sfx-2.0-video-to-audio"
}
```

### 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('mirelo-sfx-2.0-video-to-audio', {
  videoUrl: "https://cdn.example.com/input.mp4",
  prompt: "A serene mountain lake at golden hour, ultra detailed",
  duration: 10
});

console.log(result.url); // audio 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": "mirelo-sfx-2.0-video-to-audio",
    "params": {
      "videoUrl": "https://cdn.example.com/input.mp4",
      "prompt": "A serene mountain lake at golden hour, ultra detailed",
      "duration": 10
    }
  }
}'
```

#### 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": "mirelo-sfx-2.0-video-to-audio",
    "params": {
      "videoUrl": "https://cdn.example.com/input.mp4",
      "prompt": "A serene mountain lake at golden hour, ultra detailed",
      "duration": 10
    }
  }
}'
# → { "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 mirelo-sfx-2.0-video-to-audio  # this model's parameters
gen-ai pricing mirelo-sfx-2.0-video-to-audio  # quote before spending credits
gen-ai generate -m mirelo-sfx-2.0-video-to-audio \
  -p "A serene mountain lake at golden hour" \
  -d 10
```

## Compatibility API (vendor parameters)

Alongside the unified API, the `mirelo-ai/sfx2.0/video-to-audio` workflow takes Mirelo'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/mirelo-ai/sfx2.0/video-to-audio/execute` (sync) · `POST …/submit` + `GET …/{taskId}/result` (async)
- **SDK**: `ai.apis.run('mirelo-ai/sfx2.0/video-to-audio', params, { mode })` — params forwarded verbatim

### Vendor parameters

| Parameter | Type | Required | Default | Details |
| --- | --- | --- | --- | --- |
| `return_speech` | `boolean` | no | `false` | Also return the input's separated speech as its own audio file, in the response's speech. With preserve_speech false the soundtracks are sound effects only and the speech is separated while they generate. With preserve_speech true it is the speech separated from the input that the soundtracks were generated around, not the speech in them: the model renders that speech anew, so the file does not cancel or double it cleanly when layered onto a soundtrack. The file is mono, in upload_audio_format, and as long as the soundtracks. It is not billed. |
| `video_url` | `string` | yes | — | Video to add sound to: an http(s) URL, or a base64 data URI up to 8 MB. · e.g. `https://di3otfzjg1gxa.cloudfront.net/chase.mp4` |
| `num_samples` | `integer` | no | `2` | Number of variations to generate. Billed per sample. · 1–4 |
| `upload_audio_bitrate_kbps` | `integer` | no | — | Bitrate in kbps for an mp3 or aac upload. mp3 is written at exactly this constant rate, one of 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320. aac takes 32 to 256 as a target the encoder may undershoot on mono or sparse audio. Unset keeps the default: mp3 at LAME V0 VBR, aac at a 256 kbps target. Refused with a lossless upload_audio_format. · 32–320 |
| `duration` | `number` | no | `10` | Seconds of sound to generate, from 1 s to 600 s, clamped to the video's length. Over 10 s generates in 10 s windows. A video shorter than 1 s answers 400. · 1–600 |
| `text_prompt` | `string` | no | — | Optional text guiding the soundtrack. Name sounds the picture does not show, such as off-screen sounds or an ambience bed, to have them worked into it. · max 2000 chars · e.g. `Distant police sirens, tires screeching on asphalt` |
| `negative_prompt` | `string` | no | — | Sounds to keep out of the result, as a short comma-separated list. · max 1000 chars · e.g. `music, crowd noise` |
| `preserve_speech` | `boolean` | no | `true` | Keep the speech in the input's audio and generate the rest of the soundtrack around it. False generates sound effects only and suppresses speech. |
| `upload_audio_format` | `string` | no | `wav` | Audio format of each file · Options: `wav`, `mp3`, `aac`, `flac` |
| `seed` | `integer` | no | — | Seed for generation. -1 or None for random. · -1–18446744073709552000 |
| `options` | `object` | no | — | Platform-specific options for safety checks and Picsart Drive integration. |
| └ `safety_checks` | `object` | no | — | Safety check configuration. |
| └   `enabled` | `boolean` | no | `true` | Enable or disable text safety checks. Defaults to true. |
| └ `drive` | `object` | no | — | Picsart Drive storage options. When provided, the result will be saved to the user's Drive. |
| └   `name` | `string` | yes | — | Filename to save the result as in Picsart Drive. |
| └   `attributes` | `object` | no | — | Additional file metadata attributes. |
| └   `folder` | `object` | no | — | Destination folder in Picsart Drive. |

### Example request body

```json
{
  "params": {
    "video_url": "https://di3otfzjg1gxa.cloudfront.net/chase.mp4",
    "text_prompt": "Distant police sirens, tires screeching on asphalt"
  }
}
```

### 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 'mirelo-ai/sfx2.0/video-to-audio' workflow directly — params are sent as-is.
const { result, usage } = await ai.apis.run('mirelo-ai/sfx2.0/video-to-audio', {
  video_url: "https://di3otfzjg1gxa.cloudfront.net/chase.mp4",
  text_prompt: "Distant police sirens, tires screeching on asphalt"
}, {
  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/mirelo-ai/sfx2.0/video-to-audio/execute' \
  -H 'Authorization: Bearer $PICSART_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "params": {
    "video_url": "https://di3otfzjg1gxa.cloudfront.net/chase.mp4",
    "text_prompt": "Distant police sirens, tires screeching on asphalt"
  }
}'
```

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

```bash
# 1. Submit the job
curl -X POST 'https://api.picsart.com/workflows/mirelo-ai/sfx2.0/video-to-audio/submit' \
  -H 'Authorization: Bearer $PICSART_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "params": {
    "video_url": "https://di3otfzjg1gxa.cloudfront.net/chase.mp4",
    "text_prompt": "Distant police sirens, tires screeching on asphalt"
  }
}'
# → { "status": "success", "response": { "id": "wf_abc123" } }

# 2. Poll until response.status is COMPLETED
curl 'https://api.picsart.com/workflows/mirelo-ai/sfx2.0/video-to-audio/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": {
    "id": "wf_abc123",
    "status": "COMPLETED",
    "result": {
      "model": "sfx-2.0",
      "audio": [
        {
          "content_type": "audio/wav",
          "file_name": "generated_audio_1.wav",
          "url": "https://di3otfzjg1gxa.cloudfront.net/chase_output_1.wav"
        }
      ],
      "speech": {
        "windows_failed": 0,
        "outcome": "speech",
        "windows": 0,
        "audio": {
          "content_type": "image/png",
          "file_size": 4404019,
          "file_name": "z9RV14K95DvU.png",
          "url": "https://cdn.picsart.com/…/result.mp3"
        },
        "windows_with_speech": 0
      }
    }
  }
}
```

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

```json
{
  "result": {
    "model": "sfx-2.0",
    "audio": [
      {
        "content_type": "audio/wav",
        "file_name": "generated_audio_1.wav",
        "url": "https://di3otfzjg1gxa.cloudfront.net/chase_output_1.wav"
      }
    ],
    "speech": {
      "windows_failed": 0,
      "outcome": "speech",
      "windows": 0,
      "audio": {
        "content_type": "image/png",
        "file_size": 4404019,
        "file_name": "z9RV14K95DvU.png",
        "url": "https://cdn.picsart.com/…/result.mp3"
      },
      "windows_with_speech": 0
    }
  }
}
```

## Additional resources

- Model page: https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio
- Try it: https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/playground
- SDK: https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/sdk
- REST API (unified): https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/api
- Compatibility API (vendor parameters): https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/advanced
- Pricing: https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/pricing
- This document: https://picsart.com/api-platform/models/mirelo-sfx-2.0-video-to-audio/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
