# Muse Video

Muse Video is the video model from Meta Superintelligence Labs. One request makes a clip of about 10 seconds at 720p with sound, from a prompt or from a prompt plus up to 9 reference images, in one of seven aspect ratios. Send the request, keep the returned task ID, and read the finished video from the task. Reference images go in as URLs.

## Model IDs

| Model ID     | Inputs           | Resolution | Length                       |
| ------------ | ---------------- | ---------- | ---------------------------- |
| `muse-video` | text, 0–9 images | `720p`     | about 10 seconds, with sound |

See the [model page](https://seedrouter.ai/models/muse-video#pricing) for current prices.

## Quick example

```bash
curl https://api.seedrouter.ai/v1/videos/generations \
  -H "Authorization: Bearer $SEEDROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "muse-video",
    "prompt": "Waves rolling onto a sandy beach at sunset, slow camera pan, natural ocean sound. No text.",
    "aspect_ratio": "16:9"
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.seedrouter.ai/v1/videos/generations",
    headers={"Authorization": f"Bearer {os.environ['SEEDROUTER_API_KEY']}"},
    json={
        "model": "muse-video",
        "prompt": "Waves rolling onto a sandy beach at sunset, slow camera pan, natural ocean sound. No text.",
        "aspect_ratio": "16:9",
    },
    timeout=60,
)
response.raise_for_status()
task_id = response.json()["id"]
```

```javascript
const response = await fetch('https://api.seedrouter.ai/v1/videos/generations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SEEDROUTER_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'muse-video',
    prompt: 'Waves rolling onto a sandy beach at sunset, slow camera pan, natural ocean sound. No text.',
    aspect_ratio: '16:9',
  }),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { id: taskId } = await response.json();
```

```go
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strings"
    "time"
)

func main() {
    body := strings.NewReader(`{
      "model": "muse-video",
      "prompt": "Waves rolling onto a sandy beach at sunset, slow camera pan, natural ocean sound. No text.",
      "aspect_ratio": "16:9"
    }`)
    req, err := http.NewRequest("POST", "https://api.seedrouter.ai/v1/videos/generations", body)
    if err != nil { panic(err) }
    req.Header.Set("Authorization", "Bearer " + os.Getenv("SEEDROUTER_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 60 * time.Second}
    res, err := client.Do(req)
    if err != nil { panic(err) }
    defer res.Body.Close()
    if res.StatusCode != http.StatusOK { panic(res.Status) }
    var task struct { ID string `json:"id"` }
    if err := json.NewDecoder(res.Body).Decode(&task); err != nil { panic(err) }
    fmt.Println(task.ID)
}
```

## Endpoint

```text
POST https://api.seedrouter.ai/v1/videos/generations
```

| Header        | Value                 |
| ------------- | --------------------- |
| Authorization | `Bearer YOUR_API_KEY` |
| Content-Type  | `application/json`    |

The response is a task (`{"id": "task_...", "status": "processing"}`), not the finished video. Poll `GET /v1/tasks/{task_id}` for the result. Keep API keys in server-side code.

## Parameters

| Field          | Type              | Default  | Notes                                                                                                                                               |
| -------------- | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`        | string            | required | `muse-video`                                                                                                                                        |
| `prompt`       | string            | required | Must not be empty after trimming. Required with references too.                                                                                     |
| `image_urls`   | URL list          | none     | 0–9 public image URLs, 11 MB in total. Without them the request is text to video.                                                                   |
| `aspect_ratio` | enum              | auto     | `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2` or `2:3`. Leave it out for auto: references set the shape; text only gives `16:9`. Do not send `"auto"`. |
| `size`         | enum              | none     | Compatibility alias of `aspect_ratio`: one of the ratios above, or `auto`. When both are valid, `aspect_ratio` wins.                                |
| `duration`     | integer or string | `10`     | Only `10`, `"10"` or `"10s"`. The clip runs about 10 seconds.                                                                                       |
| `resolution`   | enum              | `720p`   | Only `720p`.                                                                                                                                        |
| `audio`        | boolean           | `true`   | Only `true`; every clip has sound. `false` is refused.                                                                                              |
| `n`            | integer           | `1`      | Only `1`. Each request returns one clip.                                                                                                            |

Fields outside this list are dropped before the request is forwarded; they never cause an error and never change the output. There are no first or last frame, reference video, reference audio, extend, seed or negative prompt settings. `callback_url` is not available; poll the task instead.

## Reference images

Pass up to 9 images in `image_urls` and describe the motion in `prompt`. Muse Video uses them as references: the clip stays close to them, but the first frame is not a pixel copy. With `aspect_ratio` left out, the clip follows their shape.

```json
{
  "model": "muse-video",
  "prompt": "The fox slowly lifts its head, wind moving through its fur, the camera pushing in gently, soft forest ambience.",
  "image_urls": ["https://example.com/fox.png"]
}
```

## Media inputs

Each reference is a public HTTP(S) URL. Base64 data URIs are not accepted: upload the file to your own storage and pass its URL. Use PNG, JPEG or WebP images; the original files must total 11 MB or less across all references. A set over that limit fails after acceptance and is not charged.

## Pricing dimensions

Check the [model pricing section](https://seedrouter.ai/models/muse-video#pricing) for current rates. Muse Video has one price per clip:

```text
cost = price per clip × 1
```

The price is not multiplied by seconds. Text-only and reference requests, and every aspect ratio, cost the same. The amount reserved when the task is accepted is the amount charged. View final charges in your account usage history. Failed tasks are not charged.

## Output schema

Submission returns the task:

```json
{"id": "task_...", "model": "muse-video", "status": "processing", "created_at": 1789689600}
```

### Get the task

```text
GET https://api.seedrouter.ai/v1/tasks/{task_id}
```

Poll every 10–20 seconds until `status` is `completed` or `failed`. A network timeout while polling does not mean generation failed: keep the task ID and resume checking it. Do not create another task to check progress.

### Completed task

```json
{
  "id": "task_...",
  "model": "muse-video",
  "status": "completed",
  "created_at": 1789689600,
  "finished_at": 1789689790,
  "output": {
    "video_url": "https://static.seedrouter.ai/media/tasks/task_example/0.mp4"
  }
}
```

In our tests the clips came back as 10.0-second MP4 (H.264) files with an AAC audio track: 1280 × 720 for `16:9`, 720 × 1280 for `9:16`, and 1248 × 704 for a reference with a 16:9 shape, about 100–200 seconds after submission.

## Errors

Requests rejected before a task is created return an HTTP error with an `error` object and are not charged. A task that fails after acceptance returns HTTP 200 when queried, with `status: "failed"` and an `error` object.

See the [shared error catalog](https://seedrouter.ai/docs/api/errors) for codes, HTTP statuses, and retry guidance.

```json
{
  "id": "task_...",
  "model": "muse-video",
  "status": "failed",
  "error": {
    "code": 60001,
    "message": "The request was rejected by the content policy. Please revise the prompt or input images."
  }
}
```

If submission itself times out, check your tasks before submitting again: the first request may have been accepted.

## Tips

* Describe subject, action, camera move and light, and name the sounds you want; the audio is generated together with the picture.
* Make a still with [Muse Image](https://seedrouter.ai/docs/muse-image), then pass its URL here to set it in motion.
* For vertical video, send `aspect_ratio: "9:16"`, or a portrait reference.
* Add `no text` to keep invented captions out.

## Related

* [Muse Video Playground and pricing](https://seedrouter.ai/models/muse-video)
* [Muse Image API reference](https://seedrouter.ai/docs/muse-image)
* [Download OpenAPI](https://seedrouter.ai/docs/muse-video.openapi.json)
* [Copyable Markdown](https://seedrouter.ai/docs/muse-video.md)
