# Video Options

> Configure render-level video output with fps, quality, trim, subtitles, and multi-page combine transitions.

- **URL**: https://orshot.com/docs/video-generation/video-options

---

The `videoOptions` object controls render-level behavior when `response.format` is set to `"mp4"`, `"webm"`, or `"gif"`.

## All Options```json
{
  "videoOptions": {
    "fps": 30,
    "quality": 80,
    "trimStart": 0,
    "trimEnd": 20,
    "duration": 8,
    "muted": true,

    "subtitleSource": "https://example.com/subtitles.srt",
    "subtitleFontSize": "30px",
    "subtitleFontWeight": "700",
    "subtitleColor": "#ffffff",
    "subtitleBackground": "rgba(0,0,0,0.5)",
    "subtitleFontFamily": "Inter, sans-serif",
    "subtitlePosition": "bottom",
    "subtitleOffset": "50px",
    "subtitlePaddingX": "16px",
    "subtitlePaddingY": "8px",
    "subtitleBorderRadius": "6px",

    "combinePages": true,
    "pageTransition": "fade",
    "pageTransitionDuration": 0.5
  }
}
```## Performance and Quality

### FPS

- `videoOptions.fps`
- Type: `number`
- Range: `1` to `30`
- Controls output frame rate. When not specified, FPS is set automatically based on video length (shorter videos get higher FPS, up to 30). GIF defaults to 15 FPS.

### Quality

- `videoOptions.quality`
- Type: `number`
- Range: `1` to `100`
- Higher values produce better visual quality with larger file size.

## Trimming and Duration

### Trim Range

- `videoOptions.trimStart`
- `videoOptions.trimEnd`
- Type: `number` (seconds)

When both are provided, output duration is calculated as `trimEnd - trimStart`.

### Duration Fallback

- `videoOptions.duration`
- Type: `number` (seconds)
- Used as a fallback duration when a trim range is not provided.

## Audio

### Muted

- `videoOptions.muted`
- Type: `boolean`
- `true`: force mute all output audio (video elements and page audio)
- `false`: include audio from video elements and page-level audio

### Page-Level Audio

Each page can have multiple audio tracks (e.g., background music + voiceover) configured in the Studio editor. Audio tracks are automatically mixed into the video output alongside any video element audio.

Each audio track supports:
- **Volume control** — adjust the mix level relative to other tracks
- **Fade in / fade out** — smooth audio transitions
- **Trim** — use a specific portion of the audio file
- **Offset** — delay when the audio starts playing within the page
- **Loop** — repeat the audio to fill the full page duration

### Audio Source

- `videoOptions.audioSource`
- Supported forms:
  - `string`: a single audio URL applied to the first audio track on each rendered page
  - `array`: per-page (and optionally per-track) source mapping for targeted overrides

Per-page format:```json
{
  "videoOptions": {
    "audioSource": [
      { "page": 1, "url": "https://example.com/music.mp3" },
      { "page": 1, "track": 1, "url": "https://example.com/voiceover.mp3" },
      { "pageId": "a1b2c3d4-5e6f-7890-abcd-ef1234567890", "url": "https://example.com/chapter-2-music.mp3" }
    ]
  }
}
```| Field | Type | Description |
| ----- | ---- | ----------- |
| `page` | Number | Page number to target (1-based) |
| `pageId` | String | Page UUID to target — stable when pages are reordered. Use `page` or `pageId`, not both |
| `url` | String | URL of the audio file |
| `track` | Number | (Optional) Track index to override. Defaults to `0` (first track) |

When `audioSource` is provided as a string, it overrides the first audio track URL on each rendered page. When provided as an array, each entry targets a specific page (by `page` number or `pageId`) and track. If the target track index doesn't exist, a new track is created. Passing a single `string` on a multi-page render applies the same audio to every page.

## Subtitles

### Subtitle Source

- `videoOptions.subtitleSource`
- Supported forms:
  - `string`: single source URL for single-page renders
  - `array`: per-page source mapping for multi-page renders

Per-page format:```json
{
  "videoOptions": {
    "subtitleSource": [
      { "page": 1, "url": "https://example.com/intro.mp3" },
      { "page": 2, "url": "https://example.com/chapter-2.srt" }
    ]
  }
}
```### Subtitle Styling

| Option                  | Type     | Default               | Description                                           |
| :---------------------- | :------- | :-------------------- | :---------------------------------------------------- |
| `subtitleFontSize`      | `string` | `"30px"`              | CSS font size                                         |
| `subtitleFontWeight`    | `string` | `"700"`               | Font weight (`"400"`, `"500"`, `"600"`, `"700"`, `"800"`) |
| `subtitleColor`         | `string` | `"white"`             | Text color                                            |
| `subtitleBackground`    | `string` | `"rgba(0,0,0,0.6)"`  | Background color of the subtitle box                  |
| `subtitleFontFamily`    | `string` | `"Arial, sans-serif"` | Font family (Google Fonts supported)                  |
| `subtitlePosition`      | `string` | `"bottom"`            | Position: `"bottom"` or `"top"`                       |
| `subtitleOffset`        | `string` | `"50px"`              | Distance from the positioned edge                     |
| `subtitlePaddingX`      | `string` | `"16px"`              | Horizontal padding                                    |
| `subtitlePaddingY`      | `string` | `"8px"`               | Vertical padding                                      |
| `subtitleBorderRadius`  | `string` | `"6px"`               | Corner radius of the subtitle box                     |
| `subtitleShadowX`       | `number` | `0`                   | Text shadow X offset (px)                             |
| `subtitleShadowY`       | `number` | `0`                   | Text shadow Y offset (px)                             |
| `subtitleShadowBlur`    | `number` | `0`                   | Text shadow blur radius (px)                          |
| `subtitleShadowColor`   | `string` | `"rgba(0,0,0,0.8)"`  | Text shadow color                                     |

## Multi-Page Combine Options

### Combine Pages

- `videoOptions.combinePages`
- Type: `boolean`
- Combines multi-page video renders into one final video.

### Page Transition

- `videoOptions.pageTransition`
- Type: `string`
- Supported values:
  - `fade`
  - `fadeblack`
  - `fadewhite`
  - `dissolve`
  - `wipeleft`
  - `wiperight`
  - `wipeup`
  - `wipedown`
  - `slideleft`
  - `slideright`
  - `slideup`
  - `slidedown`
  - `circleopen`
  - `circleclose`
  - `pixelize`
- Omit or use `"none"` for hard cuts.

### Page Transition Duration

- `videoOptions.pageTransitionDuration`
- Type: `number`
- Range: `0.1` to `2` (seconds)

## Complete Request Example```javascript
await fetch("https://api.orshot.com/v1/studio/render", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <YOUR_API_KEY>",
  },
  body: JSON.stringify({
    templateId: "<YOUR_TEMPLATE_ID>",
    modifications: {
      "page1@title": "Intro",
      "page2@title": "Features",
      "page3@title": "CTA",
    },
    response: {
      format: "webm",
      type: "url",
      includePages: [1, 2, 3],
    },
    videoOptions: {
      fps: 30,
      quality: 80,
      muted: true,
      combinePages: true,
      pageTransition: "fade",
      pageTransitionDuration: 0.5,
      subtitleSource: [
        { page: 1, url: "https://example.com/intro.mp3" },
        { page: 2, url: "https://example.com/chapter2.mp3" },
      ],
      subtitleFontSize: "30px",
      subtitleColor: "#ffffff",
      subtitleBackground: "rgba(0,0,0,0.5)",
    },
  }),
});
```