> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.bannerify.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Play dynamic videos

> Learn how to show a video template with your own content as soon as someone opens it, with no render step on your server.

A dynamic video is a video template that plays with your modifications the moment someone opens it. You do not render the video first and store it. Bannerify starts the render when the video is opened, and playback begins while the rest of the video renders. This is useful for personalized videos in emails, landing pages, and apps, where each viewer sees their own name, photo, or offer.

## Prerequisites

* A video template. See [Generate videos](https://documentation.bannerify.co/docs/essentials/generate-videos).
* The Scale or Enterprise plan.
* An API key, kept on your server. See [Authentication](https://documentation.bannerify.co/docs/api-reference/authentication).

## Create a video link

A video link is a [signed URL](https://documentation.bannerify.co/docs/essentials/signed-urls) of a video template. The SDKs sign it on your server and make no network request.

**JavaScript**

```ts theme={null}
const url = await bannerify.generateVideoSignedUrl("tpl_xxx", {
  modifications: [{ name: "headline", text: "Hello, Ada" }],
})
```

**Python**

```python theme={null}
url = client.generate_video_signed_url(
    "tpl_xxx",
    modifications=[{"name": "headline", "text": "Hello, Ada"}],
)
```

**PHP**

```php theme={null}
$url = $client->generateVideoSignedUrl('tpl_xxx', [
    'modifications' => [['name' => 'headline', 'text' => 'Hello, Ada']],
]);
```

**Go**

```go theme={null}
url, err := client.GenerateVideoSignedURL("tpl_xxx", &bannerify.VideoSignedURLOptions{
    Modifications: []bannerify.Modification{{Name: "headline", Text: ptr("Hello, Ada")}},
})
```

You can also sign it yourself, as [Build a signed URL yourself](https://documentation.bannerify.co/docs/essentials/signed-urls#build-a-signed-url-yourself) shows. A signed URL of a video template with no `format`, or with `format=m3u8`, is its video link.

## Play the video link

The video link answers an HLS playlist (`application/vnd.apple.mpegurl`). Safari plays it in a `<video>` tag:

```html theme={null}
<video src="https://api.bannerify.co/v1/templates/signedurl?..." controls playsinline></video>
```

In other browsers, play it with [hls.js](https://github.com/video-dev/hls.js):

```html theme={null}
<video id="video" controls playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
  const url = "https://api.bannerify.co/v1/templates/signedurl?..."
  const video = document.getElementById("video")
  if (video.canPlayType("application/vnd.apple.mpegurl")) {
    video.src = url
  } else {
    const hls = new Hls()
    hls.loadSource(url)
    hls.attachMedia(video)
  }
</script>
```

The first seconds of the video are ready first, so playback starts soon after the link opens. If the viewer skips ahead to a part that is still rendering, the player waits for it, as it does on a slow connection.

## Play it with the embed player

The embed player plays the video template in the viewer's browser, so nothing renders on Bannerify's side: it starts at once, at full quality, at any length. Take the query of the video link and put it after `https://embed.bannerify.co/play`:

```html theme={null}
<iframe
  src="https://embed.bannerify.co/play?apiKeyHashed=...&modifications=...&templateId=tpl_xxx&sign=..."
  width="540"
  height="675"
></iframe>
```

The player fits the video to the frame and has play, pause and seek controls. Add `#loop` to the end of the URL to play it in a loop. Any site can show the player, as any site can show the video link.

## What renders again

Bannerify keeps each rendered part of a video. When you change a modification, only the parts of the video that show the changed layers render again. The other parts play from storage at once. For example, if a price shows from second 5 to second 10, a new price renders those 5 seconds only.

A video link that was opened before, with the same template and the same modifications, plays from storage with no render.

## Get an MP4 file

Set `format` to `mp4` to get the video as one MP4 file, for videos of up to 15 seconds. The link redirects to the MP4 when its whole render is done, so use it where a player or a platform needs one complete file.

**JavaScript**

```ts theme={null}
const url = await bannerify.generateVideoSignedUrl("tpl_xxx", { format: "mp4" })
```

**Python**

```python theme={null}
url = client.generate_video_signed_url("tpl_xxx", format="mp4")
```

**PHP**

```php theme={null}
$url = $client->generateVideoSignedUrl('tpl_xxx', ['format' => 'mp4']);
```

**Go**

```go theme={null}
url, err := client.GenerateVideoSignedURL("tpl_xxx", &bannerify.VideoSignedURLOptions{Format: "mp4"})
```

For longer videos, render the MP4 with [renderVideo](https://documentation.bannerify.co/docs/essentials/generate-videos).

A signed URL of a video template with `format` set to `png`, `jpeg`, or `webp` answers a still image of the template.

## Limits and usage

| | Video link | Embed player | MP4 |
| - | - | - | - |
| Plan | Scale and Enterprise | Scale and Enterprise | Scale and Enterprise |
| Length | Any | Any | Up to 15 seconds |
| Starts playing | Soon after the link opens | At once | When the render is done |

A video counts one generation for each second, and two for each second at 60 fps. A video link counts when it opens with a new set of modifications, and the embed player when it loads one. An MP4 counts once its render is done. Bannerify keeps a rendered video for up to 30 days. Opening the same template with the same modifications in that time plays the stored video and counts no new generation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.