> ## 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.

# Render videos in PHP

> Render a video template as an MP4 and follow its progress with the PHP SDK.

A video template renders as an MP4. Each second of the video counts as one generation. [Generate videos](/docs/essentials/generate-videos) explains how to design one.

Both methods take a template id and an options array.

<ParamField body="templateId" type="string" required>
  The id of a video template, for example `tpl_xxx`.
</ParamField>

<ParamField body="modifications" type="array">
  The values to put into the template's layers. A video layer takes a `src`, and the modification named `music` changes the music. [Modifications](/docs/essentials/modifications) lists the fields each layer accepts.
</ParamField>

## Render and wait for the URL

`renderAndWaitVideo` returns `['result' => $url]` or `['error' => [...]]`.

```php theme={null}
$result = $client->renderAndWaitVideo('tpl_xxx', [
    'modifications' => [
        ['name' => 'headline', 'text' => 'Summer sale'],
        ['name' => 'music', 'src' => 'https://example.com/song.mp3'],
    ],
]);

if (isset($result['error'])) {
    throw new RuntimeException($result['error']['message']);
}

echo $result['result'];
```

## Follow the progress

`renderVideo` returns a `Generator` of event arrays. The last event is `done` or `error`.

```php theme={null}
foreach ($client->renderVideo('tpl_xxx', ['modifications' => [['name' => 'headline', 'text' => 'Summer sale']]]) as $event) {
    match ($event['type']) {
        'queued' => printf("%d videos before this one\n", $event['ahead']),
        'progress' => printf("%d%%\n", $event['progress'] * 100),
        'done' => print($event['url'] . "\n"),
        'error' => print($event['error']['message'] . "\n"),
    };
}
```

| Event | Fields |
| - | - |
| `queued` | `ahead`: the number of videos before this one |
| `progress` | `frame`, `totalFrames`, and `progress` from 0 to 1 |
| `done` | `url`: the URL of the MP4 |
| `error` | `error`: `code`, `message`, and `requestId` |

A refused request, such as an invalid API key or a used-up quota, gives one `error` event. The client timeout applies only to the connection, because a video can wait in line for minutes.


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