# Generate videos

> Learn how to design a short animated video template and render it as an MP4 with the API.

Canonical: https://bannerify.co/docs/essentials/generate-videos

You can design a short video in the editor and render it as an MP4 with your own text, images, and audio. This is useful for reels, stories, product teasers, and social ads, where the motion stays the same and the content changes for each render.

> Video templates are in beta. The editor, the API, and the SDK methods can still change.

## How a video template works

A video template is a template with a timeline. Each top-level layer has a start and an end on the timeline, and up to one animation of each kind:

| Kind | What it does | Presets |
| --- | --- | --- |
| Enter | Brings the layer in at its start | Fade in, Slide in, Slide in up, Slide in down, Scale in, Pop, Rotate in, Flip in X, Flip in Y, Text reveal, Typewriter |
| Exit | Takes the layer out at its end | Fade out, Slide out, Slide out up, Slide out down, Scale out, Rotate out, Flip out X, Flip out Y |
| Ambient | Runs for the whole time the layer shows | Ken Burns, Pulse, Breathe, Float, Drift, Wiggle, Shake, Slow rotate |
| Behavior | Runs once, at a time you choose | Press, Count up |

Text reveal, Typewriter, and Count up are for text layers. Ken Burns is for images and video layers.

On a text layer, an Enter or Exit preset can animate each word or each letter in turn, in place of the whole layer. Set **Animate by** to **Word** or **Letter**, then set **Stagger**: the share of the animation between the start of the first word or letter and the start of the last one. At 0%, all of them move together.

A video can also have audio tracks (music, a voice over, sound effects), and video layers that play a clip with its sound.

Each preset has an easing: Linear, Ease in, Ease out, Ease in and out, the back curves (Ease in back, Ease out back, Ease in and out back) that go a little past the end, Hold, and the springs Gentle, Quick, Bouncy, and Slow.

## Design a video

1. Click **New template**, then **Blank video**. The editor opens a 1080 by 1920 canvas with a 5-second timeline at 30 fps.
2. Add layers as in an image template: text, images, shapes, and frames. To add a clip, use **Objects → Video**, or drop a video file on the canvas.
3. Drag the bars on the timeline to set when each layer starts and ends. Hold Shift to snap an edge to the playhead.
4. Select a layer and open the **Motion** tab of the right panel. Set its timing, then pick an Enter, Exit, Ambient, or Behavior preset and its easing. Point at a preset to see it on the layer before you pick it. **Start after** makes a layer start when another layer ends.
5. With no layer selected, the **Motion** tab sets the duration (up to 60 seconds) and the frame rate (24, 25, 30, or 60 fps). You can also type the duration on the timeline, or drag the end of the video on its ruler.
6. Press play to watch the video. **Play once**, **Loop**, and **Ping-pong** set what the preview does at the end.

### Add audio

Drop audio files on the canvas or on the timeline, or click **Add audio** in the **Motion** tab. Each file becomes an audio track that starts at the playhead, or where you drop it on the timeline, and lasts as long as the file.

- Drag a track to move it in time, or drag its edges to trim it. The start edge trims the file too, so each sound stays at its time.
- Click the speaker of a track to mute it.
- Select a track and press **Alt+K** (Option+K on a Mac) to split it at the playhead. Press **Delete** to remove it.
- The right panel of a selected track sets its name, its file, its volume, a fade in and a fade out, where the file starts, and the loop.

A video layer plays the sound of its clip. Its **Volume** and **Sound** settings are in the **Playback** section of the layer.

### Work on the timeline

- Type a time in the current time or the duration of the timeline, as `0:01.50` or as seconds.
- Zoom the timeline with its slider, or with Ctrl or Cmd and the mouse wheel. On a trackpad, pinch.
- Drag the top edge of the timeline to make it taller.
- Click the arrow next to a layer to show a bar for each of its animations. Drag the end of an Enter bar or the start of an Exit bar to change its duration. Drag a Behavior bar to move it, or its edges to change it. An Ambient bar lasts the whole layer.

Video and audio files upload to your workspace assets, up to 50 MB each.

## Render a video

Send a `POST` request to `/v1/templates/renderVideo` with the template id and your modifications:

```bash
curl --request POST \
  --url https://api.bannerify.co/v1/templates/renderVideo \
  --header 'Content-Type: application/json' \
  --data '{
    "apiKey": "YOUR_API_KEY",
    "templateId": "tpl_xxx",
    "modifications": [
      { "name": "headline", "text": "Summer sale" },
      { "name": "photo", "src": "https://example.com/image.png" },
      { "name": "music", "src": "https://example.com/song.mp3" }
    ]
  }'
```

The answer comes when the MP4 is ready. `id` identifies the video:

```json
{
  "id": "vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11",
  "url": "https://images.bannerify.co/files/0b3c1c1e-5d6f-4c52-9e0a-8f6a4c0f2a11.mp4"
}
```

A modification works as in an image template. In addition:

- A modification with the name of a video layer and a `src` changes the clip of that layer.
- A modification with the name of an audio track and a `src` changes the file of that track. The track keeps its time, volume, and fades. In this example, the template has an audio track named `music`.

## Follow the progress

A render takes longer than an image, and a video can wait in line for a renderer. Add `?stream=true` to get server-sent events while it renders:

```bash
curl --no-buffer --request POST \
  --url 'https://api.bannerify.co/v1/templates/renderVideo?stream=true' \
  --header 'Content-Type: application/json' \
  --data '{ "apiKey": "YOUR_API_KEY", "templateId": "tpl_xxx" }'
```

| Event | Fields | When |
| --- | --- | --- |
| `created` | `id` | The video has an id. This is the first event. |
| `queued` | `ahead` | The video waits for a renderer. `ahead` is the number of videos before it. |
| `progress` | `frame`, `totalFrames`, `progress` | The frames render. `progress` goes from 0 to 1. |
| `done` | `url` | The MP4 is saved. This is the last event. |
| `error` | `error` | The render failed. This is the last event. `error` has `code`, `message`, and `requestId`. |

## Start a video without waiting

Add `?wait=false` to get the id of the video at once. This is useful when your server cannot keep a connection open for the whole render:

```bash
curl --request POST \
  --url 'https://api.bannerify.co/v1/templates/renderVideo?wait=false' \
  --header 'Content-Type: application/json' \
  --data '{ "apiKey": "YOUR_API_KEY", "templateId": "tpl_xxx" }'
```

The answer has status `202`:

```json
{ "id": "vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11", "status": "queued" }
```

Then read the video with its id, as in the next section.

## Read a video again

A video renders to its end also when the connection drops. Use its `id` from the `created` event to read it again:

```bash
curl 'https://api.bannerify.co/v1/videos/vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11?apiKey=YOUR_API_KEY'
```

```json
{
  "id": "vid_0b3c1c1e5d6f4c529e0a8f6a4c0f2a11",
  "status": "done",
  "url": "https://images.bannerify.co/files/0b3c1c1e-5d6f-4c52-9e0a-8f6a4c0f2a11.mp4"
}
```

| Status | Meaning |
| --- | --- |
| `queued` | The video waits for a renderer. |
| `rendering` | The frames render. |
| `done` | The MP4 is saved. `url` is its URL. |
| `failed` | The render failed. `error` tells why. |

Add `&stream=true` to get the events again, from the latest one. Do not send the `renderVideo` request again: it renders, and counts, a second video.

The SDKs read these events for you, and read the video again when the connection drops. See the [JavaScript](https://bannerify.co/docs/sdk/js/apis/render-video), [PHP](https://bannerify.co/docs/sdk/php/apis/render-video), [Go](https://bannerify.co/docs/sdk/go/apis/render-video), and [Python](https://bannerify.co/docs/sdk/python/apis/render-video) guides.

## Usage

Each second of video counts as one generation, rounded up, and as two generations at 60 fps. A 5-second video counts 5 generations, a 7.5-second video counts 8, and a 5-second video at 60 fps counts 10. A video counts when its MP4 is saved, also when the connection dropped before the end. A render that fails counts nothing.

## Limits

| Limit | Value |
| --- | --- |
| Output | MP4 (H.264 video, AAC audio) |
| Duration | Up to 60 seconds |
| Frame rate | 24, 25, 30, or 60 fps |
| Uploaded video or audio file | Up to 50 MB |

## Learn more

- [Render video API reference](https://bannerify.co/docs/api-reference/endpoint/render-video)
- [Retrieve video API reference](https://bannerify.co/docs/api-reference/endpoint/get-video)
- [Modifications](https://bannerify.co/docs/essentials/modifications)
- [Template editor](https://bannerify.co/docs/essentials/template-editor)

## Related

- [Previous: Generate PDFs](https://bannerify.co/docs/essentials/generate-pdfs)
- [Next: Generate images from a spreadsheet](https://bannerify.co/docs/essentials/bulk-generation)
- [Documentation index](https://bannerify.co/docs/llms.txt)
