# WebM to MP4 Converter (`junipr/webm-to-mp4`) Actor

Convert WebM video files to MP4 format using FFmpeg. Fast, reliable transcoding with support for batch URLs and custom output settings.

- **URL**: https://apify.com/junipr/webm-to-mp4.md
- **Developed by:** [junipr](https://apify.com/junipr) (community)
- **Categories:** Developer tools, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $39.00 / 1,000 video converteds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## WebM to MP4 Converter

Convert WebM video files to MP4 format using FFmpeg. Accepts WebM URLs or Apify Key-Value Store keys, transcodes using H.264 (or H.265) video codec with AAC audio, and outputs MP4 files with direct download links. Supports configurable resolution, bitrate, quality presets, frame rate, and audio settings. Handles capped batches of up to 3 videos per run with explicit file-size and duration limits.

WebM is increasingly common — browsers use it natively via the MediaRecorder API, it's the default for screen recordings in Chrome and Firefox, and many scraping pipelines encounter it. The problem is that most downstream tools, social platforms, and video players prefer MP4. This actor closes that gap with zero configuration required.

### Why Use This Actor

**There is no other dedicated WebM-to-MP4 conversion actor on the Apify Store.** Users currently rely on desktop tools that require installation (HandBrake, FFmpeg CLI), online converters with file size limits, or build their own FFmpeg Docker pipelines. This actor handles the capped pipeline — download, transcode, upload to KV Store, return download URL — with a single API call.

#### Cost Comparison

| Service | Price per 1,000 conversions | File size limit | Batch processing |
|---------|---------------------------|-----------------|-----------------|
| **This actor** | **$39.00** | 50MB default, 100MB max | Up to 3/run |
| CloudConvert | ~$8.00 | 1GB (free: 25MB) | 25/job |
| Zamzar | ~$15.00 | 50MB (free) | 5 at a time |
| Convertio | ~$10.00 | 100MB (free) | 10 at a time |

No account or API key required beyond Apify — the actor uses the Apify Key-Value Store for output automatically. FFmpeg runs locally inside the actor, so your video data never passes through a third-party conversion service.

Output files are web-optimized by default: the MP4 moov atom is placed at the beginning of the file (`faststart` mode), which allows browsers to begin playback before the entire file has loaded.

### How to Use

#### Zero-Config (Quick Start)

The actor works with no configuration. Default settings produce a web-compatible H.264 MP4 with AAC audio:

```json
{
  "videos": [
    { "url": "https://example.com/recording.webm" }
  ]
}
````

After the run completes, the dataset contains a record with `outputUrl` — a direct download link for the converted MP4 from the Apify Key-Value Store.

#### Convert from KV Store

If you have a WebM file already stored in the actor's Key-Value Store (e.g., uploaded via the Apify API), reference it by key:

```json
{
  "videos": [
    { "kvStoreKey": "my-recording.webm" }
  ]
}
```

#### Quality Configuration

```json
{
  "videos": [{ "url": "https://example.com/recording.webm" }],
  "videoCodec": "h264",
  "preset": "slow",
  "crf": 18,
  "maxWidth": 1920,
  "audioBitrate": "192k",
  "fastStart": true
}
```

#### Calling via Apify API

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

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('junipr/webm-to-mp4').call({
  videos: [{ url: 'https://example.com/lecture.webm' }],
  videoCodec: 'h264',
  preset: 'balanced',
  crf: 23,
});

const dataset = await client.dataset(run.defaultDatasetId).listItems();
const result = dataset.items[0];
console.log('Download URL:', result.outputUrl);
```

#### Downloading Converted Files

Each dataset item contains an `outputUrl` with a direct download link:

```bash
curl -L "https://api.apify.com/v2/key-value-stores/{storeId}/records/converted_myvideo.mp4" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -o myvideo.mp4
```

### Input Configuration

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `videos` | array | (sample URL) | List of `{ url }` or `{ kvStoreKey }` objects. Max 3. |
| `videoCodec` | string | `"h264"` | Video codec: `h264` or `h265` |
| `preset` | string | `"balanced"` | Speed/quality tradeoff: `ultrafast`, `fast`, `balanced`, `slow`, `veryslow` |
| `crf` | integer | `23` | Quality: 0 (lossless) to 51 (worst). 18–28 is typical range. |
| `maxBitrate` | string | null | Cap bitrate: `"2M"`, `"5M"`. Null = CRF-only. |
| `resolution` | string | null | Force resolution: `"1920x1080"`, `"1280x720"` |
| `maxWidth` | integer | null | Scale down if wider than this (preserves aspect ratio) |
| `maxHeight` | integer | null | Scale down if taller than this (preserves aspect ratio) |
| `fps` | integer | null | Output frame rate (1–120). Null = same as input. |
| `audioCodec` | string | `"aac"` | Audio: `aac`, `mp3`, or `none` (strip audio) |
| `audioBitrate` | string | `"128k"` | Audio bitrate: `64k`, `128k`, `192k`, `320k` |
| `audioSampleRate` | integer | null | Sample rate in Hz. Null = same as input. |
| `volume` | number | `1.0` | Volume multiplier: 0.5 = half, 2.0 = double |
| `outputPrefix` | string | `"converted_"` | Prefix for output KV Store keys |
| `fastStart` | boolean | `true` | Move moov atom to start for web streaming |
| `maxConcurrency` | integer | `1` | Concurrent conversions (1–3) |
| `downloadTimeout` | integer | `60000` | Per-video download timeout in ms |
| `conversionTimeout` | integer | `300000` | Per-video FFmpeg timeout in ms |
| `maxFileSizeMb` | number | `50` | Maximum source file size per video, capped at 100MB |
| `maxDurationSeconds` | number | `300` | Maximum source duration per video, capped at 600 seconds |

#### Common Configurations

**Quick convert** (defaults — best compatibility):

```json
{ "videos": [{ "url": "..." }] }
```

**Web optimized** (streaming-ready, 720p max):

```json
{ "videos": [{ "url": "..." }], "videoCodec": "h264", "crf": 23, "maxHeight": 720, "fastStart": true }
```

**High quality** (archive, large files):

```json
{ "videos": [{ "url": "..." }], "videoCodec": "h264", "crf": 18, "preset": "slow" }
```

**Maximum compression** (smallest files, slowest):

```json
{ "videos": [{ "url": "..." }], "videoCodec": "h265", "crf": 28, "preset": "veryslow" }
```

### Output Format

Each converted video produces one dataset item:

```json
{
  "sourceUrl": "https://example.com/recording.webm",
  "sourceKvKey": null,
  "outputKvKey": "converted_recording.mp4",
  "outputUrl": "https://api.apify.com/v2/key-value-stores/{storeId}/records/converted_recording.mp4",
  "inputFormat": "webm",
  "inputCodec": "vp9",
  "inputDurationSeconds": 42.5,
  "inputWidth": 1920,
  "inputHeight": 1080,
  "inputSizeBytes": 15728640,
  "outputDurationSeconds": 42.5,
  "outputWidth": 1920,
  "outputHeight": 1080,
  "outputSizeBytes": 8388608,
  "outputVideoCodec": "h264",
  "outputAudioCodec": "aac",
  "outputFps": 30,
  "compressionRatio": 0.53,
  "conversionTimeMs": 12340,
  "convertedAt": "2026-03-11T10:30:00.000Z",
  "errors": []
}
```

A `compressionRatio` below 1.0 means the output is smaller than the input. Values above 1.0 can occur with lossless CRF settings or very short clips where codec overhead dominates.

The Key-Value Store also contains an `OUTPUT` record with a run summary including totals, averages, and the codec configuration used.

### Tips and Advanced Usage

#### Choosing Between H.264 and H.265

Use **H.264** (default) for: web playback, social media uploads, sharing, anything that needs to play in browsers or on mobile devices. It is supported on 99%+ of devices.

Use **H.265** for: archiving, internal storage, and delivery to controlled playback environments (iOS apps with hardware H.265 support, smart TVs). H.265 files are typically 30–50% smaller at equivalent quality, but most web browsers do not support H.265 natively.

#### Understanding CRF

CRF (Constant Rate Factor) controls quality, not file size directly. A CRF of 18 produces very high quality files that are noticeably larger than CRF 23. For most use cases:

- **CRF 18–20**: High quality (visually lossless)
- **CRF 23**: Default, good balance of quality and size
- **CRF 26–28**: Acceptable quality, significantly smaller files
- **CRF 0**: True lossless — output may be larger than input; not recommended for web

#### Optimal Settings by Use Case

| Use Case | Codec | CRF | Preset | Notes |
|----------|-------|-----|--------|-------|
| Web streaming | h264 | 23 | balanced | Add fastStart: true (default) |
| Social media | h264 | 20 | fast | Check platform max resolution |
| Mobile app | h264 | 23 | balanced | maxWidth: 1280 for bandwidth |
| Archive | h265 | 22 | slow | Smaller long-term storage |
| Fast processing | h264 | 25 | ultrafast | Trade quality for speed |

#### Batch Processing

To convert a large video library, split into runs of 3 videos. Use `maxConcurrency: 2` only on short, small videos. For longer videos, keep `maxConcurrency: 1` to avoid memory pressure.

### Pricing

This actor uses Pay-Per-Event (PPE) pricing: **$39.00 per 1,000 videos converted** ($0.039 per video).

Pricing includes all platform compute costs — no hidden fees.

PPE charges are attempted only after input validation, download, size checks, duration checks, and media probing pass. Invalid URLs, SSRF-blocked URLs, missing KV keys, oversized files, over-duration files, and invalid media are not charged or pushed to the default dataset. If the Apify PPE budget is exhausted, the actor stops before conversion and writes a diagnostic record to the key-value store instead of the default dataset.

| Scenario | Videos | Estimated Cost |
|----------|--------|---------------|
| Single conversion | 1 | $0.039 |
| Browser recording batch | 20 | $0.39 |
| Screen recording library | 200 | $3.90 |
| Video dataset | 2,000 | $39.00 |
| Large-scale conversion | 10,000 | $195.00 |

### FAQ

#### What is the maximum file size I can convert?

The default max source size is 50MB per video and the hard cap is 100MB per video. The default duration cap is 300 seconds and the hard cap is 600 seconds. Split larger files before running the actor.

#### Can I convert other formats besides WebM?

Yes. FFmpeg detects the actual input format regardless of file extension. MP4, AVI, MKV, MOV, FLV, and other common formats will convert successfully. The actor logs the detected input format in the dataset item.

#### What is the difference between H.264 and H.265?

H.264 (AVC) is the current standard: universally compatible, supported on virtually all browsers, devices, and platforms. H.265 (HEVC) is the next generation: produces 30–50% smaller files at equivalent quality, but requires hardware decoding support on the playback device and is not natively supported by most web browsers. Choose H.264 unless you have specific reasons to use H.265.

#### What CRF value should I use?

For most web use cases, the default CRF 23 is a good starting point. If you need higher quality (for example, a source video with a lot of fine detail), try CRF 18–20. If file size is the priority, try CRF 26–28. Avoid CRF 0 (lossless) unless you specifically need lossless output — the file sizes are enormous.

#### Does conversion reduce video quality?

All lossy encoding introduces some quality reduction. At CRF 23 with H.264, the quality loss is imperceptible for most content. At CRF 18, the output is visually lossless for most viewers. Converting from WebM VP8/VP9 to H.264 with a reasonable CRF setting produces excellent results.

#### Can I convert audio-only WebM files?

Yes. If the WebM file contains only an audio stream (e.g., Opus audio from a browser recording with no video), the actor will convert it to an MP4 audio container. The output dimensions will be 0x0 and the video codec fields will be empty.

#### How long does conversion take?

Conversion time depends on video length, resolution, and preset. For a 30-second 1080p clip with the default "balanced" preset, expect 5–15 seconds. A 5-minute 1080p clip typically takes 30–90 seconds. The "ultrafast" preset can reduce conversion time by 3–5x at the cost of larger output files.

#### Are subtitles preserved during conversion?

No. WebM subtitle streams and chapter markers are not preserved during conversion to MP4. If subtitle preservation is required, extract subtitles separately before conversion.

***

Related actors: [Video Download Link Crawler](https://apify.com/junipr/video-download-crawler)

# Actor input Schema

## `videos` (type: `array`):

List of WebM videos to convert. Each item must have either a 'url' (HTTP/HTTPS link to a WebM file) or a 'kvStoreKey' (key in the actor's Key-Value Store). Min: 1, Max: 3.

## `videoCodec` (type: `string`):

Video codec to use for encoding. H.264 offers the best compatibility (all browsers, devices, platforms). H.265 produces smaller files but has limited browser support — best for archiving or mobile apps.

## `preset` (type: `string`):

Encoding speed vs quality/size tradeoff. 'ultrafast' is fastest but produces larger files. 'veryslow' produces the smallest files but takes much longer. 'balanced' (default) is the best choice for most use cases.

## `crf` (type: `integer`):

Constant Rate Factor controls quality. Lower = better quality, larger file. 0 = lossless (very large), 18 = high quality, 23 = default, 28 = lower quality, 51 = worst quality.

## `maxBitrate` (type: `string`):

Maximum video bitrate (e.g., '2M', '5M', '10M'). Leave empty for CRF-only quality control (recommended). Use this to cap file size for streaming scenarios.

## `resolution` (type: `string`):

Force output to a specific resolution (e.g., '1920x1080', '1280x720', '854x480'). Leave empty to keep the original resolution. Aspect ratio is preserved with padding if needed.

## `maxWidth` (type: `integer`):

Scale video down if wider than this value (pixels). Aspect ratio is preserved. Ignored if 'resolution' is set.

## `maxHeight` (type: `integer`):

Scale video down if taller than this value (pixels). Aspect ratio is preserved. Ignored if 'resolution' is set.

## `fps` (type: `integer`):

Output frames per second. Leave empty to keep the original frame rate. Common values: 24, 30, 60.

## `audioCodec` (type: `string`):

Audio codec: 'aac' (default, universal compatibility), 'mp3' (widely supported), 'none' (strip audio from output).

## `audioBitrate` (type: `string`):

Audio bitrate. Common values: '64k' (low), '128k' (default, good quality), '192k' (high), '320k' (maximum).

## `audioSampleRate` (type: `integer`):

Audio sample rate in Hz. Leave empty to keep the original sample rate. Common values: 44100, 48000.

## `volume` (type: `number`):

Audio volume adjustment. 1.0 = original volume (default). 0.5 = half volume. 2.0 = double volume. Range: 0.0 to 5.0.

## `outputPrefix` (type: `string`):

Prefix added to output filenames in the Key-Value Store. For example, 'converted\_' produces 'converted\_myvideo.mp4'.

## `fastStart` (type: `boolean`):

Move the MP4 moov atom to the beginning of the file. Enables streaming playback — the browser can start playing before the entire file is downloaded. Highly recommended for web use.

## `maxConcurrency` (type: `integer`):

Maximum number of videos to convert simultaneously. Video encoding is CPU-intensive — keep this at 1-2 unless you have excess memory and CPU available. Range: 1-3.

## `downloadTimeout` (type: `integer`):

Timeout for downloading each source video in milliseconds. Default: 60000 (1 minute). Range: 10000-300000.

## `conversionTimeout` (type: `integer`):

Timeout for FFmpeg conversion per video in milliseconds. Default: 300000 (5 minutes). Range: 30000-600000.

## `maxFileSizeMb` (type: `number`):

Maximum source video size per file. Default 50 MB, hard cap 100 MB.

## `maxDurationSeconds` (type: `number`):

Maximum source video duration per file. Default 300 seconds, hard cap 600 seconds.

## Actor input object example

```json
{
  "videos": [
    {
      "url": "https://www.w3schools.com/html/mov_bbb.webm"
    }
  ],
  "videoCodec": "h264",
  "preset": "balanced",
  "crf": 23,
  "maxBitrate": "",
  "resolution": "",
  "audioCodec": "aac",
  "audioBitrate": "128k",
  "volume": 1,
  "outputPrefix": "converted_",
  "fastStart": true,
  "maxConcurrency": 1,
  "downloadTimeout": 60000,
  "conversionTimeout": 300000,
  "maxFileSizeMb": 50,
  "maxDurationSeconds": 300
}
```

# Actor output Schema

## `OUTPUT` (type: `string`):

Summary of the conversion run: totals, success/failure counts, average conversion time, and codec settings used.

## `results` (type: `string`):

Per-video conversion records including input/output metadata, file sizes, compression ratio, and download URLs for converted MP4 files.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("junipr/webm-to-mp4").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("junipr/webm-to-mp4").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call junipr/webm-to-mp4 --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=junipr/webm-to-mp4",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "WebM to MP4 Converter",
        "description": "Convert WebM video files to MP4 format using FFmpeg. Fast, reliable transcoding with support for batch URLs and custom output settings.",
        "version": "1.0",
        "x-build-id": "1Agx5bUevXuhIDGmW"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/junipr~webm-to-mp4/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-junipr-webm-to-mp4",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/junipr~webm-to-mp4/runs": {
            "post": {
                "operationId": "runs-sync-junipr-webm-to-mp4",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/junipr~webm-to-mp4/run-sync": {
            "post": {
                "operationId": "run-sync-junipr-webm-to-mp4",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "videos": {
                        "title": "Videos to Convert",
                        "minItems": 1,
                        "maxItems": 3,
                        "type": "array",
                        "description": "List of WebM videos to convert. Each item must have either a 'url' (HTTP/HTTPS link to a WebM file) or a 'kvStoreKey' (key in the actor's Key-Value Store). Min: 1, Max: 3.",
                        "items": {
                            "type": "object"
                        },
                        "default": [
                            {
                                "url": "https://www.w3schools.com/html/mov_bbb.webm"
                            }
                        ]
                    },
                    "videoCodec": {
                        "title": "Video Codec",
                        "enum": [
                            "h264",
                            "h265"
                        ],
                        "type": "string",
                        "description": "Video codec to use for encoding. H.264 offers the best compatibility (all browsers, devices, platforms). H.265 produces smaller files but has limited browser support — best for archiving or mobile apps.",
                        "default": "h264"
                    },
                    "preset": {
                        "title": "Encoding Preset",
                        "enum": [
                            "ultrafast",
                            "fast",
                            "balanced",
                            "slow",
                            "veryslow"
                        ],
                        "type": "string",
                        "description": "Encoding speed vs quality/size tradeoff. 'ultrafast' is fastest but produces larger files. 'veryslow' produces the smallest files but takes much longer. 'balanced' (default) is the best choice for most use cases.",
                        "default": "balanced"
                    },
                    "crf": {
                        "title": "Quality (CRF)",
                        "minimum": 0,
                        "maximum": 51,
                        "type": "integer",
                        "description": "Constant Rate Factor controls quality. Lower = better quality, larger file. 0 = lossless (very large), 18 = high quality, 23 = default, 28 = lower quality, 51 = worst quality.",
                        "default": 23
                    },
                    "maxBitrate": {
                        "title": "Max Video Bitrate",
                        "type": "string",
                        "description": "Maximum video bitrate (e.g., '2M', '5M', '10M'). Leave empty for CRF-only quality control (recommended). Use this to cap file size for streaming scenarios.",
                        "default": ""
                    },
                    "resolution": {
                        "title": "Output Resolution",
                        "type": "string",
                        "description": "Force output to a specific resolution (e.g., '1920x1080', '1280x720', '854x480'). Leave empty to keep the original resolution. Aspect ratio is preserved with padding if needed.",
                        "default": ""
                    },
                    "maxWidth": {
                        "title": "Max Width",
                        "type": "integer",
                        "description": "Scale video down if wider than this value (pixels). Aspect ratio is preserved. Ignored if 'resolution' is set."
                    },
                    "maxHeight": {
                        "title": "Max Height",
                        "type": "integer",
                        "description": "Scale video down if taller than this value (pixels). Aspect ratio is preserved. Ignored if 'resolution' is set."
                    },
                    "fps": {
                        "title": "Output Frame Rate",
                        "minimum": 1,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Output frames per second. Leave empty to keep the original frame rate. Common values: 24, 30, 60."
                    },
                    "audioCodec": {
                        "title": "Audio Codec",
                        "enum": [
                            "aac",
                            "mp3",
                            "none"
                        ],
                        "type": "string",
                        "description": "Audio codec: 'aac' (default, universal compatibility), 'mp3' (widely supported), 'none' (strip audio from output).",
                        "default": "aac"
                    },
                    "audioBitrate": {
                        "title": "Audio Bitrate",
                        "type": "string",
                        "description": "Audio bitrate. Common values: '64k' (low), '128k' (default, good quality), '192k' (high), '320k' (maximum).",
                        "default": "128k"
                    },
                    "audioSampleRate": {
                        "title": "Audio Sample Rate",
                        "type": "integer",
                        "description": "Audio sample rate in Hz. Leave empty to keep the original sample rate. Common values: 44100, 48000."
                    },
                    "volume": {
                        "title": "Volume Multiplier",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Audio volume adjustment. 1.0 = original volume (default). 0.5 = half volume. 2.0 = double volume. Range: 0.0 to 5.0.",
                        "default": 1
                    },
                    "outputPrefix": {
                        "title": "Output File Prefix",
                        "type": "string",
                        "description": "Prefix added to output filenames in the Key-Value Store. For example, 'converted_' produces 'converted_myvideo.mp4'.",
                        "default": "converted_"
                    },
                    "fastStart": {
                        "title": "Fast Start (Web Optimized)",
                        "type": "boolean",
                        "description": "Move the MP4 moov atom to the beginning of the file. Enables streaming playback — the browser can start playing before the entire file is downloaded. Highly recommended for web use.",
                        "default": true
                    },
                    "maxConcurrency": {
                        "title": "Max Concurrent Conversions",
                        "minimum": 1,
                        "maximum": 3,
                        "type": "integer",
                        "description": "Maximum number of videos to convert simultaneously. Video encoding is CPU-intensive — keep this at 1-2 unless you have excess memory and CPU available. Range: 1-3.",
                        "default": 1
                    },
                    "downloadTimeout": {
                        "title": "Download Timeout (ms)",
                        "minimum": 10000,
                        "maximum": 300000,
                        "type": "integer",
                        "description": "Timeout for downloading each source video in milliseconds. Default: 60000 (1 minute). Range: 10000-300000.",
                        "default": 60000
                    },
                    "conversionTimeout": {
                        "title": "Conversion Timeout (ms)",
                        "minimum": 30000,
                        "maximum": 600000,
                        "type": "integer",
                        "description": "Timeout for FFmpeg conversion per video in milliseconds. Default: 300000 (5 minutes). Range: 30000-600000.",
                        "default": 300000
                    },
                    "maxFileSizeMb": {
                        "title": "Max Source File Size (MB)",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "number",
                        "description": "Maximum source video size per file. Default 50 MB, hard cap 100 MB.",
                        "default": 50
                    },
                    "maxDurationSeconds": {
                        "title": "Max Source Duration (seconds)",
                        "minimum": 1,
                        "maximum": 600,
                        "type": "number",
                        "description": "Maximum source video duration per file. Default 300 seconds, hard cap 600 seconds.",
                        "default": 300
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
