# Generate video

> Start a video render on an explicit model, with optional frame inputs, and collect the file.

`POST /video/generate` creates a video task. `model` and `prompt` are
required. One request renders one video, and there is no `auto` or `count`.

**SDK**

```ts
import Mynth from "@mynthio/sdk";

const mynth = new Mynth();

const task = await mynth.video.generate({
  model: "bytedance/seedance-2.0-mini",
  prompt: "A lighthouse beam sweeping over waves",
  duration: 5,
  resolution: "720p",
});

console.log(task.urls[0]);
```

**REST**

```bash
curl https://api.mynth.io/video/generate \
  -H "Authorization: Bearer $MYNTH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"bytedance/seedance-2.0-mini","prompt":"A lighthouse beam sweeping over waves","duration":5,"resolution":"720p"}'
```

The REST call returns a `taskId` and `estimatedCost` at once. The SDK waits up
to an hour. A render takes minutes, so in a request handler, create the task
with `generateAsync()` and finish in a [webhook](https://mynth.io/docs/concepts/webhooks.md)
instead of waiting. The CLI has no video command.

## Fields

| Field             | Notes                                                                                                   |
| ----------------- | ------------------------------------------------------------------------------------------------------- |
| `model`           | Required. An id from [video models](https://mynth.io/docs/models/video.md)                                                 |
| `prompt`          | Required. 1 to 8192 characters                                                                          |
| `negative_prompt` | Optional. Up to 8192 characters                                                                         |
| `resolution`      | `480p`, `720p`, `1080p`, or `4k`. Defaults to the model's default                                       |
| `duration`        | Seconds. Defaults to the model's default. Each model accepts its own range                              |
| `audio`           | Generated audio. Defaults to the model's default, which is on for every current model                   |
| `inputs`          | Frame images. See [frame inputs](#frame-inputs)                                                         |
| `webhook`         | Per-request URLs, same shape as on images. See [webhooks](https://mynth.io/docs/concepts/webhooks.md#per-request-webhooks) |
| `metadata`        | A JSON object up to 2048 bytes                                                                          |
| `access`          | `{ "pat": { "enabled": false } }` skips the browser token                                               |

Video does not take `destination`, `size`, `count`, `magic_prompt`, or
`output`. `destination` is dropped without an error, so a video request that
names one still writes nothing to your storage.

Every value is checked against the model when the task is created. A
resolution, duration, audio setting, or input the model does not serve answers
`400 VALIDATION_ERROR`, and nothing is queued.

## Frame inputs

Send `inputs` to animate from an image. Each input is a URL string or an
object with a role:

```json
{
  "model": "bytedance/seedance-2.0-mini",
  "prompt": "The camera pulls back from the lighthouse",
  "inputs": [
    {
      "type": "image",
      "as": "first_frame",
      "source": { "type": "url", "url": "https://cdn.example.com/start.png" }
    },
    {
      "type": "image",
      "as": "last_frame",
      "source": { "type": "url", "url": "https://cdn.example.com/end.png" }
    }
  ]
}
```

Every current model needs exactly one `first_frame` for image-to-video.
Seedance and Gemini Omni Flash also take an optional `last_frame`. P-Video and
Grok Imagine Video take the first frame only. [Video models](https://mynth.io/docs/models/video.md)
has the table, and `modes` on the catalog entry is the live contract.

## What comes back

```json
{
  "model": "bytedance/seedance-2.0-mini",
  "videos": [
    {
      "status": "success",
      "id": "vid_3HkP9wQz7LmR2tXc8VbN5dFy0JsA4gUe",
      "url": "https://cdn.mynth.io/videos/vid_3HkP9wQz7LmR2tXc8VbN5dFy0JsA4gUe.mp4",
      "mynth_url": "https://cdn.mynth.io/videos/vid_3HkP9wQz7LmR2tXc8VbN5dFy0JsA4gUe.mp4",
      "cost": "0.40500000",
      "duration": 5,
      "resolution": "720p",
      "audio": true
    }
  ]
}
```

Check `status` on the video. A refusal or a provider failure fails the item
with an `error.code` while the task still completes. The file is served for 7
days. See [tasks](https://mynth.io/docs/concepts/tasks.md#file-lifetimes).

## Price

Video is `perSecond[resolution] × duration`, and the estimate is exact because
the model is explicit. Price a body with `POST /video/generate/estimate`, or
`mynth.video.estimate()` in the SDK. [Pricing](https://mynth.io/docs/pricing.md#video-price) has
the formula.

## Next steps

- [Video models](https://mynth.io/docs/models/video.md): resolutions, durations, and frame inputs per model.
- [Webhooks](https://mynth.io/docs/concepts/webhooks.md): collect a long render without holding a connection.
- [Poll for results](https://mynth.io/docs/guides/poll-for-results.md): the status and result calls.
