# Video Render Engine - Remotion & HTML/CSS to MP4 (`andrew_babo/hyper-video-render-engine`) Actor

Render Remotion / React / HTML / CSS / SVG / Canvas compositions to MP4, WebM, MOV or GIF in seconds. Parallel frame sharding across cores and containers, seamless stitching, voiceover and ducked music mixed in. 900 frames of 1080x1920 in 13-28 s. Webhook and standby mode.

- **URL**: https://apify.com/andrew\_babo/hyper-video-render-engine.md
- **Developed by:** [Andrew Babo](https://apify.com/andrew_babo) (community)
- **Categories:** Videos, Developer tools, Automation
- **Stats:** 63 total users, 12 monthly users, 94.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Hyper Video Render Engine — Remotion & HTML/CSS to MP4 at high speed

Turn a **Remotion** project (React, HTML, CSS, SVG, Canvas, WebGL) into a finished **MP4 / WebM / MOV / GIF** in seconds, on demand, through an API — without keeping a render farm alive.

The engine splits the composition into frame shards, renders them **in parallel across many Chromium instances**, and stitches the pieces with Remotion's own seamless concat: no re-encode, no duplicated or dropped frames at the seams, no drift between picture and sound. Voiceover and background music are mixed in one final FFmpeg pass, so the browser never has to deal with audio.

***

### Why it is fast

| Stage | What most render setups do | What this engine does |
| --- | --- | --- |
| Workspace | Write frames to the container disk | Everything lives on the **RAM disk** (`/dev/shm`) — no disk I/O at all |
| Parallelism | One browser, more tabs | **One browser per shard**, so the work actually uses every CPU core |
| Chunk format | MP4 pieces that need a new header | **MPEG-TS pieces** that concatenate with a stream copy in ~50 ms |
| Audio | Rendered inside the browser | Muxed at the end with FFmpeg — **under a second**, always in sync |
| Cold start | Download Chromium and the bundle on every run | Chromium is **baked into the image**; bundles are cached by content hash |
| Warm calls | New container every time | **Standby mode** keeps browsers and unpacked bundles warm between requests |

On Apify you get **one CPU core per 4 GB of memory**, so memory is the speed dial:

| Memory | Cores | Parallel renderers | Use it for |
| --- | --- | --- | --- |
| 8 GB | 2 | 2 | cheapest, short clips |
| 16 GB (default) | 4 | 4 | balanced, or the orchestrator of a distributed run |
| 32 GB | 8 | 8 | fastest single container |
| `mode: "distributed"` | orchestrator + N workers | 16–64 | long videos and heavy templates |

***

### Measured performance

Real runs on Apify, 1080x1920 at 30 fps, h264 CRF 18, `chromiumGl: "angle"` — no cherry-picking, these are the numbers the Actor reports in its own output row.

| Video | Setup | Render | Total | Throughput |
| --- | --- | --- | --- | --- |
| 30 s (900 frames), light template | 32 GB, one container | 12.8 s | **13.4 s** | 67 fps |
| 30 s (900 frames), heavy template¹ | 32 GB, one container | 35.2 s | 51.9 s | 17 fps |
| 30 s (900 frames), heavy template¹ | 16 GB + 6 x 8 GB workers | 26.6 s | **28.3 s** | 32 fps |
| 30 s, heavy + voiceover + ducked music | 16 GB + 6 x 8 GB workers | 39.6 s | 44.7 s | 20 fps |
| 2 min (3600 frames), light template | 32 GB, one container | 59.1 s | 60.1 s | 60 fps |
| 2 min (3600 frames), light template | 16 GB + 6 x 8 GB workers | 39.9 s | **40.7 s** | 89 fps |
| 10 s (300 frames), transparent VP9² | 16 GB, one container | 29.4 s | **37.2 s** | 10 fps |
| 10 s (300 frames), transparent VP9 + music² | 16 GB, one container | 28.8 s | 38.5 s | 10 fps |

¹ The heavy template is deliberately brutal: full-screen `backdrop-filter` blur, an animated conic gradient, a 120-particle canvas and animated SVG dashes on every single frame. Ordinary marketing and social templates behave like the light one.

² Transparency costs frame rate everywhere: lossless PNG frames and an alpha-capable intermediate are unavoidable. The point of the number is what it replaces — the same clip encoded the standard way spent **6.7 minutes** in libvpx alone. See [Transparent output](#transparent-output).

Every output above was verified with `ffprobe`: **exactly 900 / 3600 frames, 30.000 s, audio track the same length as the picture** — no dropped, duplicated or drifting frames at the shard seams. The transparent runs were decoded frame by frame: **94% of every frame is fully transparent, alpha intact at the shard seams**.

Cost is the memory-time Apify bills: roughly **$0.10–0.13 per 30 s render** at the 64 GB tier, under **$0.01** for a light 30 s clip in a single container.

***

### Quick start

Run it with **no input at all** to render the built-in demo composition and see the output format.

#### 1. Build your Remotion bundle

```bash
npx remotion bundle          # produces the "build" folder (index.html + JS + your public/ assets)
cd build && zip -r ../bundle.zip .
```

Upload `bundle.zip` anywhere with a direct download link (S3, R2, GitHub release, Apify key-value store).

#### 2. Run the Actor

```json
{
  "bundleUrl": "https://example.com/bundle.zip",
  "compositionId": "MainVideo",
  "inputProps": { "title": "Hello world", "brandColor": "#ff6a00" },
  "audioUrl": "https://example.com/voiceover.mp3",
  "bgmUrl": "https://example.com/music.mp3",
  "bgmVolume": 0.15,
  "videoConfig": {
    "width": 1080,
    "height": 1920,
    "fps": 30,
    "durationInFrames": 900,
    "format": "mp4",
    "crf": 18
  },
  "sharding": { "mode": "auto" },
  "webhookUrl": "https://example.com/api/render-webhook"
}
```

#### 3. Collect the result

The finished file lands in the run's key-value store under `OUTPUT` and the dataset gets one report row:

```json
{
  "status": "SUCCEEDED",
  "videoUrl": "https://api.apify.com/v2/key-value-stores/<STORE_ID>/records/OUTPUT.mp4",
  "compositionId": "MainVideo",
  "width": 1080,
  "height": 1920,
  "fps": 30,
  "totalFrames": 900,
  "durationSeconds": 30,
  "renderTimeMs": 28329,
  "effectiveSpeed": "31.8 fps",
  "shards": 16,
  "localShards": 4,
  "workerRuns": 6,
  "shardingMode": "distributed",
  "fileSizeBytes": 24313344,
  "computeUnits": 0.428,
  "costUsd": 0.107,
  "warnings": [],
  "errorCode": null
}
```

If a `webhookUrl` is set, that exact JSON is POSTed to it the moment the video is ready.

***

### Three ways to supply the bundle

| Field | Use it when |
| --- | --- |
| `bundleUrl` | You have a `.zip` / `.tar.gz` of the bundle on any HTTP host. Downloaded once, then cached by content hash. |
| `serveUrl` | The bundle is already hosted (S3 website, Cloudflare R2, `npx remotion deploy`). Nothing is downloaded. |
| `bundleKeyValueStoreKey` | Another Actor produced the bundle and left it in a key-value store. |

Leave all three empty and the built-in demo composition is rendered — useful for a smoke test.

***

### Input reference

#### Composition

| Field | Default | Meaning |
| --- | --- | --- |
| `compositionId` | first composition found | Which composition to render |
| `inputProps` | `{}` | Props passed to your React component |
| `envVariables` | `{}` | Values available as `process.env` inside the composition |

#### `videoConfig`

| Field | Default | Meaning |
| --- | --- | --- |
| `width`, `height` | from the composition | Output resolution |
| `fps` | from the composition | Frame rate |
| `durationInFrames` | from the composition | Length in frames |
| `frameRange` | full video | `[from, to]` to render a slice only |
| `format` | `mp4` | `mp4`, `webm`, `mov`, `mkv`, `gif` |
| `codec` | from the format | `h264`, `h265`, `vp8`, `vp9`, `av1`, `prores`, `gif` |
| `crf` | codec default | Quality, lower is better (18 is visually lossless for H.264) |
| `preset` | `faster` | x264 speed/size trade-off |
| `pixelFormat` | `yuv420p` | `yuva420p` + codec `vp8`, `vp9` or `prores` gives a transparent background. PNG frames and the ProRes 4444 profile are switched on automatically; H.264/H.265 cannot carry alpha, so the request falls back to opaque |
| `proResProfile` | `hq` (`4444` when transparent) | `4444-xq`, `4444`, `hq`, `standard`, `light`, `proxy` |
| `videoBitrate`, `audioBitrate` | — / `192k` | Fixed bitrates instead of CRF |
| `audioCodec` | container default | `aac`, `mp3`, `opus`, `pcm-16` |
| `scale` | `1` | Render at a multiple of the composition size |
| `muted` | `false` | Drop the composition's own audio |
| `imageFormat`, `jpegQuality` | `jpeg`, `90` | Intermediate frame format |

##### Transparent output

```json
{ "compositionId": "Overlay", "videoConfig": { "format": "webm", "codec": "vp9", "pixelFormat": "yuva420p" } }
```

Transparent WebM takes a detour that keeps it fast. Handed straight to libvpx at
its stock speed setting, an alpha channel encodes at well under one frame per
second — a four second 1080x1920 clip took **6.7 minutes** in testing. So the
shards are rendered as ProRes 4444 instead, converted to VP8/VP9 in parallel
with libvpx tuned for speed, and stitched with a stream copy: the same clip now
finishes in **seconds**. ProRes 4444 (`format: "mov"`) keeps alpha natively and
needs no conversion.

Two things to know: transparent jobs always render in one container (the
intermediate frames are too heavy to ship between machines), and most players
and `ffprobe` report an alpha WebM as `yuv420p` — decode it with `ffmpeg -c:v
libvpx-vp9` or drop it on a web page to see the transparency.

#### `sharding`

| Field | Default | Meaning |
| --- | --- | --- |
| `workers` | one per CPU core | Parallel renderers in local mode; number of extra containers in distributed mode |
| `concurrencyPerWorker` | `1` | Tabs inside each renderer (raise only for very light compositions) |
| `mode` | `auto` | `local` = one container, `distributed` = many containers, `auto` = switch at the threshold |
| `distributedThresholdFrames` | `4000` | When `auto` fans out to several containers |
| `workerMemoryMbytes` | `8192` | Memory (and therefore cores) per worker container — 8 GB buys 2 cores |
| `masterRenders` | `true` | The orchestrator renders its own share instead of idling while the workers work |

#### Audio

| Field | Default | Meaning |
| --- | --- | --- |
| `audioUrl` | — | Voiceover or main audio track |
| `audioVolume` | `1` | Level of that track |
| `bgmUrl` | — | Background music |
| `bgmVolume` | `0.15` | Level of the music bed |
| `bgmDucking` | `true` | Music dips automatically while the voice speaks |
| `bgmLoop` | `true` | Short music beds repeat to the end of the video |

Both files are muxed onto the finished video with `-c:v copy`, so the picture is never re-encoded and the audio cannot drift.

#### Delivery and advanced

| Field | Default | Meaning |
| --- | --- | --- |
| `outputKey` | `OUTPUT` | Name of the record in the key-value store |
| `webhookUrl`, `webhookHeaders` | — | Where to POST the report when the render finishes |
| `remotionLicenseKey` | — | Your Remotion company licence key, if you need one |
| `chromiumGl` | `angle` | Graphics backend. `angle` measured 8x faster than `swangle` here; if a machine refuses it the render falls back automatically and says so in `warnings` |
| `shardTimeoutSecs` | `600` | A silent shard is abandoned and retried on a fresh browser |
| `failOnRenderError` | `false` | Turn on if your pipeline watches run status instead of the output row |
| `verbose` | `false` | Full Remotion renderer log |

***

### Standby mode — near-zero cold start

Enable **Standby** on the Actor and the container stays alive with warm Chromium instances and cached bundles. Then render over plain HTTP:

```bash
curl -X POST "https://<your-actor>.apify.actor?token=<APIFY_TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{"bundleUrl":"https://example.com/bundle.zip","compositionId":"MainVideo","inputProps":{"title":"Hi"}}'
```

The response is the same report JSON. A `GET` on the same URL returns a readiness check. Warm requests skip the bundle download, the browser launch and the composition resolution — typically a third of the total time on short videos.

***

### Distributed mode — for long videos

With `"sharding": { "mode": "distributed" }` (or automatically past `distributedThresholdFrames`), the run becomes an orchestrator: it starts worker runs of the same Actor, each rendering its own frame range with its own CPUs, hands the finished chunks back through its own key-value store, and the orchestrator stitches everything. A worker that crashes or times out is retried once on its own, so one bad shard never fails the whole job.

The orchestrator does not sit idle: it claims one shard per core it owns and renders alongside the workers, so a 16 GB orchestrator is four extra renderers rather than a supervisor.

Two things to know before turning it on:

- **A worker container costs about 9 seconds to boot.** Below roughly 900 frames of a light template, a single 32 GB container finishes before the workers have even started.
- **Cost scales with total memory-time**, so a fan-out is worth it when the render is long or heavy enough that wall-clock time matters more than a couple of cents.

The whole render is reported as one number: `computeUnits` and `costUsd` in the output row already include every worker run, and `workerRuns` / `localShards` show how the work was split.

***

### What renders correctly

- Modern CSS: `backdrop-filter`, conic and radial gradients, CSS variables, filters, `mix-blend-mode`
- Web fonts — Chromium waits for `document.fonts.ready`, so there is no flash of unstyled text on the first frames
- SVG (including `strokeDashoffset` path animation), Canvas 2D and WebGL
- Remotion `spring()` / `interpolate()` physics, identical across shard boundaries
- Images and videos embedded in the bundle, plus any remote asset your composition fetches
- Liberation, DejaVu, Noto (including CJK) and colour emoji fonts are installed in the image

***

### Error codes

| `errorCode` | What happened | What to do |
| --- | --- | --- |
| `NO_BUNDLE` | No source given | Set `bundleUrl`, `serveUrl` or `bundleKeyValueStoreKey` |
| `BUNDLE_DOWNLOAD_FAILED` | The archive could not be fetched | Check that the link is public and direct |
| `BUNDLE_FORMAT` / `BUNDLE_INVALID` | Not a Remotion bundle archive | Zip the folder that contains `index.html` |
| `BUNDLE_TOO_LARGE` | Bigger than `maxBundleSizeMb` | Raise the limit or trim the assets |
| `COMPOSITION_NOT_FOUND` | No composition with that ID | Check the ID in your Root file |
| `SHARD_FAILED` | A frame range failed three times | Usually a runtime error in the composition; run with `verbose: true` |
| `COMBINE_FAILED` | Stitching produced an empty file | Report it — include the run ID |
| `AUDIO_DOWNLOAD_FAILED` / `AUDIO_MUX_FAILED` | Audio could not be fetched or mixed | Check the audio links |
| `WORKER_FAILED` | A distributed worker run did not succeed | Look at the worker run log, or use `mode: "local"` |

A failed render still finishes as **SUCCEEDED** with an explanatory row, so scheduled pipelines stay readable. Set `failOnRenderError: true` to flip that.

***

### Licensing note

Remotion itself is free for individuals, non-profits and companies with up to three people. Larger companies need a Remotion company licence — put your key in `remotionLicenseKey`. This Actor does not include a Remotion licence.

***

### 🤖 AI Agent / MCP Skill

**Role & Trigger** — Use this Actor whenever the task is "render / produce / export a video" from a React, HTML or Remotion template, or to re-render the same template with different text, colours or data. Do not use it to edit an existing video file, to scrape videos, or to generate footage with AI.

**Parameter Rules**

1. A source is required unless the user wants the demo: `bundleUrl` (zip link), `serveUrl` (hosted bundle) or `bundleKeyValueStoreKey`. Never invent a bundle URL — ask for it.
2. `compositionId` must match a composition in that bundle. If you do not know it, omit it: the first composition is rendered and its ID is reported back.
3. Put all dynamic content in `inputProps`. Never patch text by rebuilding the bundle.
4. Vertical social video: `{"width":1080,"height":1920,"fps":30}`. Landscape: `{"width":1920,"height":1080,"fps":30}`. Transparency needs `format: "webm"` with `pixelFormat: "yuva420p"`.
5. Leave `sharding` alone unless the user asks for speed. For speed, raise the run's memory first (each 4 GB adds a core); only use `mode: "distributed"` above ~2 minutes of video.
6. For batch jobs from one template, enable Standby and POST each job — the bundle is unpacked once and reused.

**Output Interpretation**

- `status: "SUCCEEDED"` → the video is at `videoUrl`; report `durationSeconds`, `renderTimeMs` and `effectiveSpeed` if asked about performance.
- `status: "FAILED"` → read `errorCode` and `error` and fix the input; do not retry the same input unchanged.
- `warnings` is never fatal: it lists things that were ignored (for example audio on a container that cannot carry it).
- Every run writes exactly one report row plus a `RUN_SUMMARY` record with the full timing breakdown (`bundleMs`, `renderMs`, `combineMs`, `audioMs`, `uploadMs`).

# Actor input Schema

## `bundleUrl` (type: `string`):

Direct link to a built Remotion bundle archive (the folder produced by `npx remotion bundle`, zipped). Leave every source field empty to render the built-in demo composition.

## `serveUrl` (type: `string`):

URL of an already-hosted bundle (for example on S3, Cloudflare R2 or Remotion's `deploySite`). Nothing is downloaded — the browser loads it directly.

## `bundleKeyValueStoreKey` (type: `string`):

Key of a .zip record inside an Apify key-value store. Handy when another Actor produced the bundle.

## `bundleKeyValueStoreId` (type: `string`):

Store that holds the bundle record. Defaults to this run's own key-value store.

## `compositionId` (type: `string`):

The composition to render, as registered in your Root file. Leave empty to render the first composition in the bundle.

## `inputProps` (type: `object`):

JSON passed to your composition as props — dynamic text, colours, image URLs, chart data, anything.

## `envVariables` (type: `object`):

Values exposed to the composition through `process.env` while rendering.

## `startFrame` (type: `integer`):

Segment mode: first frame to render (inclusive). Render each scene as its own run with the same videoConfig, then join the files with ffmpeg -f concat -c copy — every output has zero-based PTS, a 90 kHz timescale and starts on a keyframe.

## `endFrame` (type: `integer`):

Last frame to render (inclusive). Leave empty to render until the end of the composition.

## `videoConfig` (type: `object`):

Overrides for size, frame rate, length and encoding. Anything you leave out is taken from the composition itself.

Fields: width, height, fps, durationInFrames, frameRange \[from, to], format (mp4 / webm / mov / mkv / gif), codec (h264, h265, vp8, vp9, av1, prores, gif), crf, preset, pixelFormat, proResProfile (4444-xq / 4444 / hq / standard / light / proxy), videoBitrate, audioCodec, audioBitrate, scale, everyNthFrame, muted, imageFormat, jpegQuality.

Transparency: set pixelFormat to yuva420p together with codec vp8, vp9 or prores. PNG frames and the ProRes 4444 profile are switched on for you, and transparent WebM is encoded through a fast parallel libvpx pass instead of the stock one that runs at under one frame per second. Transparent jobs always render in one container. Alpha is dropped with h264/h265 because those formats cannot carry it.

## `sharding` (type: `object`):

How the work is split.

Fields: workers (parallel renderers — in local mode one per CPU core, in distributed mode the number of extra containers), concurrencyPerWorker (tabs per renderer, 1 is fastest), mode (auto / local / distributed), distributedThresholdFrames (when auto reaches for extra containers), workerMemoryMbytes (memory per worker container, 8192 = 2 cores each), masterRenders (this container renders its own share alongside the workers, default true).

Measured on Apify: a 900-frame 1080x1920 render of a heavy template takes 52 s in one 32 GB container and 31 s across 7 x 8 GB workers. A light template does the same 900 frames in 13 s in a single container.

## `audioUrl` (type: `string`):

Audio file mixed into the finished video. Mixing happens outside the browser, so it costs under a second and never drifts out of sync.

## `audioVolume` (type: `string`):

1 keeps the original level, 0.5 halves it, 2 doubles it.

## `bgmUrl` (type: `string`):

Music bed. It is looped or trimmed to the length of the video automatically.

## `bgmVolume` (type: `string`):

Level of the music bed relative to the original file.

## `bgmDucking` (type: `boolean`):

Automatically lowers the music whenever the voiceover speaks.

## `bgmLoop` (type: `boolean`):

Repeats short music beds until the video ends.

## `outputKey` (type: `string`):

Key of the video record in the key-value store. The right extension is added for you.

## `webhookUrl` (type: `string`):

The full render report is POSTed here as JSON the moment the video is ready.

## `webhookHeaders` (type: `object`):

Extra headers for the webhook call, for example an Authorization token.

## `remotionLicenseKey` (type: `string`):

Remotion is free for individuals and companies with up to three people; larger companies need a company licence. Paste your key here if you have one.

## `chromiumGl` (type: `string`):

How Chromium draws the page. angle is measured about 8x faster than swangle on Apify hardware and is used by default; if a machine cannot start it, the render falls back to swangle automatically and says so in warnings.

## `maxBundleSizeMb` (type: `integer`):

Safety limit for the downloaded bundle archive. Downloads larger than this are stopped instead of filling the container.

## `shardTimeoutSecs` (type: `integer`):

A shard that goes quiet for longer than this is abandoned and retried on a fresh browser.

## `failOnRenderError` (type: `boolean`):

Off by default: a failed render still writes an explanatory row and finishes as succeeded, which keeps automated pipelines readable. Turn it on if your orchestrator watches run status instead of output.

## `verbose` (type: `boolean`):

Prints Remotion's full renderer log — useful when a composition misbehaves.

## Actor input object example

```json
{
  "inputProps": {},
  "envVariables": {},
  "videoConfig": {
    "width": 1080,
    "height": 1920,
    "fps": 30,
    "format": "mp4",
    "crf": 18,
    "preset": "faster",
    "pixelFormat": "yuv420p"
  },
  "sharding": {
    "mode": "auto",
    "concurrencyPerWorker": 1
  },
  "audioVolume": "1",
  "bgmVolume": "0.15",
  "bgmDucking": true,
  "bgmLoop": true,
  "outputKey": "OUTPUT",
  "webhookHeaders": {},
  "chromiumGl": "angle",
  "maxBundleSizeMb": 1024,
  "shardTimeoutSecs": 600,
  "failOnRenderError": false,
  "verbose": false
}
```

# Actor output Schema

## `video` (type: `string`):

The finished video file, ready to download or stream.

## `dataset` (type: `string`):

One row per render: video URL, resolution, frame count, timings, speed and cost.

## `keyValueStore` (type: `string`):

The video plus the RUN\_SUMMARY record with the full timing breakdown.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "bundleUrl": "",
    "serveUrl": "",
    "bundleKeyValueStoreKey": "",
    "bundleKeyValueStoreId": "",
    "compositionId": "",
    "inputProps": {},
    "envVariables": {},
    "videoConfig": {
        "width": 1080,
        "height": 1920,
        "fps": 30,
        "format": "mp4",
        "crf": 18,
        "preset": "faster",
        "pixelFormat": "yuv420p"
    },
    "sharding": {
        "mode": "auto",
        "concurrencyPerWorker": 1
    },
    "audioUrl": "",
    "audioVolume": "1",
    "bgmUrl": "",
    "bgmVolume": "0.15",
    "outputKey": "OUTPUT",
    "webhookUrl": "",
    "webhookHeaders": {},
    "remotionLicenseKey": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("andrew_babo/hyper-video-render-engine").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "bundleUrl": "",
    "serveUrl": "",
    "bundleKeyValueStoreKey": "",
    "bundleKeyValueStoreId": "",
    "compositionId": "",
    "inputProps": {},
    "envVariables": {},
    "videoConfig": {
        "width": 1080,
        "height": 1920,
        "fps": 30,
        "format": "mp4",
        "crf": 18,
        "preset": "faster",
        "pixelFormat": "yuv420p",
    },
    "sharding": {
        "mode": "auto",
        "concurrencyPerWorker": 1,
    },
    "audioUrl": "",
    "audioVolume": "1",
    "bgmUrl": "",
    "bgmVolume": "0.15",
    "outputKey": "OUTPUT",
    "webhookUrl": "",
    "webhookHeaders": {},
    "remotionLicenseKey": "",
}

# Run the Actor and wait for it to finish
run = client.actor("andrew_babo/hyper-video-render-engine").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "bundleUrl": "",
  "serveUrl": "",
  "bundleKeyValueStoreKey": "",
  "bundleKeyValueStoreId": "",
  "compositionId": "",
  "inputProps": {},
  "envVariables": {},
  "videoConfig": {
    "width": 1080,
    "height": 1920,
    "fps": 30,
    "format": "mp4",
    "crf": 18,
    "preset": "faster",
    "pixelFormat": "yuv420p"
  },
  "sharding": {
    "mode": "auto",
    "concurrencyPerWorker": 1
  },
  "audioUrl": "",
  "audioVolume": "1",
  "bgmUrl": "",
  "bgmVolume": "0.15",
  "outputKey": "OUTPUT",
  "webhookUrl": "",
  "webhookHeaders": {},
  "remotionLicenseKey": ""
}' |
apify call andrew_babo/hyper-video-render-engine --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,andrew_babo/hyper-video-render-engine"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Y7hwICsVJbwbfDfAW/builds/d4Nlt0xoYBKr4c2J5/openapi.json
