# Video Converter & Compressor – MP4, MP3, WebM, GIF (FFmpeg) (`gazidev/media-converter`) Actor

Video converter, video compressor and audio converter for media file URLs: MP4/WebM/MOV, compress to a target size or 1080p/720p/480p, MP4 to MP3, WAV/FLAC/M4A/OGG/Opus, video to GIF, trim, mute, normalize loudness. Public download links. From $0.03 per video minute.

- **URL**: https://apify.com/gazidev/media-converter.md
- **Developed by:** [Cemal Atakli](https://apify.com/gazidev) (community)
- **Categories:** Videos, Automation, For creators
- **Stats:** 12 total users, 10 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 video minute (sd)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

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

## Video Converter & Compressor – MP4, MP3, WebM, GIF (FFmpeg)

Convert, compress and trim **video and audio files from URLs** in the cloud with FFmpeg. Paste direct links to your media files and get back **public download links** plus clean metadata for every file:

- **Compress video** – smaller MP4 (H.264/AAC) or WebM, by quality level (small / balanced / high) or to an **exact target size** in MB (e.g. 8 MB for Discord, 16 MB for WhatsApp), downscale to 1080p / 720p / 480p, change the frame rate.
- **Convert video** – MP4 (H.264 + AAC, plays everywhere), WebM (VP9 + Opus) or MOV.
- **Extract audio** – **MP4 to MP3**, M4A, WAV, FLAC, OGG or Opus, with your bitrate.
- **Convert audio** – WAV to MP3, FLAC to M4A, MP3 to Opus… any combination.
- **Video to GIF** – high-quality GIFs with a per-clip color palette, your fps, width, start time and length.
- **Trim** any operation with `startTime` / `endTime`, **mute**, and **normalize loudness** (EBU R128, −16 LUFS).

Inputs: MP4, MOV, WebM, MKV, AVI, M4V, MPEG-TS, MP3, WAV, M4A, AAC, FLAC, OGG, Opus and **HLS `.m3u8`** streams – anything FFmpeg reads.

> **Not a YouTube / TikTok / Instagram downloader.** Links to pages of YouTube, TikTok, Instagram, Facebook, X, Vimeo, Twitch, SoundCloud, Spotify and similar platforms are refused with a clear error (free). Use direct links to files you own or are allowed to process: your CDN, S3 / R2 / GCS bucket, Dropbox or Drive direct links, stock footage, podcast hosting, form uploads.

### What can I use it for?

- **Shrink user uploads** before storing them or sending them by email, Slack, Discord or WhatsApp (target size mode).
- **MP4 to MP3** for podcasts, transcription pipelines (Whisper, Deepgram) and audio previews.
- **Web-ready video:** convert MOV / MKV / AVI uploads to MP4 H.264 with fast start, or to WebM.
- **GIF previews** and thumbnails-in-motion for product pages, docs, newsletters and social posts.
- **Batch-normalize loudness** of podcast episodes or voice-overs.
- **Automations:** call it from Make, Zapier, n8n or your backend after a file lands in a bucket, or chain it after another Actor that outputs media URLs.

### Input

| Field | Description |
|---|---|
| `mediaUrls`, `bulkText`, `datasetId` | Direct media file links (list, pasted text/CSV, or another dataset) |
| `operation` | `compress-video` (default), `convert-video`, `extract-audio`, `convert-audio`, `video-to-gif` |
| `videoFormat` | `mp4` (default), `webm`, `mov` |
| `compressionLevel` | `small` (CRF 30), `balanced` (CRF 26, default), `high` (CRF 22) |
| `targetSizeMb` | Exact output size for `compress-video` (two-pass encoding) |
| `maxResolution` | `original`, `2160`, `1440`, `1080`, `720` (default for compress), `480`, `360` – never upscales; portrait-aware |
| `fps`, `mute`, `normalizeAudio` | Frame rate (0 = keep), drop audio, loudness normalization |
| `audioFormat`, `audioBitrateKbps` | `mp3`, `m4a`, `wav`, `flac`, `ogg`, `opus`; 32–320 kbps (default 192) |
| `gifFps`, `gifWidth`, `gifMaxSeconds` | 10 fps, 480 px, 10 s by default |
| `startTime`, `endTime` | Trim, e.g. `75`, `01:15`, `00:01:15.5` |
| `maxFileSizeMb`, `maxDurationMinutes` | Safety limits: 500 MB and 60 minutes per file by default (skipped files are free) |

Compress a video to 8 MB at 720p:

```json
{
  "mediaUrls": ["https://download.samplelib.com/mp4/sample-10s.mp4"],
  "operation": "compress-video",
  "targetSizeMb": 8,
  "maxResolution": "720"
}
```

Extract MP3 from a video, only minutes 2–6:

```json
{
  "mediaUrls": ["https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"],
  "operation": "extract-audio",
  "audioFormat": "mp3",
  "audioBitrateKbps": 192,
  "startTime": "00:02:00",
  "endTime": "00:06:00"
}
```

### Output

One dataset row per file (Output tab: **Converted files** table with download links). The file itself is in the run's key-value store; `fileUrl` is a public link.

```json
{
  "sourceUrl": "https://download.samplelib.com/mp4/sample-10s.mp4",
  "operation": "compress-video",
  "status": "ok",
  "input": {"duration": 10.216, "width": 1920, "height": 1080, "fps": 29.97, "videoCodec": "h264", "audioCodec": "aac",
            "container": "mov,mp4,m4a,3gp,3g2,mj2", "bitrateKbps": 4296, "sizeBytes": 5485935},
  "output": {"format": "mp4", "duration": 10.216, "width": 1280, "height": 720, "videoCodec": "h264", "audioCodec": "aac",
             "bitrateKbps": 1784, "sizeBytes": 2278391, "sizeReductionPct": 58.5},
  "fileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/000-sample-10s.mp4",
  "fileKey": "000-sample-10s.mp4",
  "billedEvents": {"hd-video-minute": 1},
  "processingSec": 3.8,
  "processedAt": "2026-10-11T11:56:53+00:00"
}
```

Failed items have `status: "error"`, an `errorCode` (`UNSUPPORTED_PLATFORM`, `INVALID_URL`, `HTTP_404`, `HTTP_403`, `NOT_MEDIA`, `FILE_TOO_LARGE`, `TOO_LONG`, `NO_AUDIO_STREAM`, `NO_VIDEO_STREAM`, `MAX_CHARGE_REACHED`, …) and a readable `error` – and are **never charged**. A `SUMMARY` record has run totals.

### Pricing

Pay only for what you get: **per started minute of output media**, priced by output resolution. Failed, skipped and refused files are free.

| What | Price |
|---|---|
| Video minute, SD (480p / 360p) | $0.008 |
| Video minute, HD (720p) | $0.025 |
| Video minute, Full HD (1080p) | $0.05 |
| Video minute, 4K / 1440p | $0.20 |
| Audio minute (MP3, M4A, WAV, FLAC, OGG, Opus) | $0.003 |
| Loudness normalization | +$0.015 per output minute |
| GIF | $0.015 per 10 seconds |
| Actor start | $0.00005 |

Examples: a 10-minute podcast WAV → MP3 = **$0.03**; a 3-minute 1080p phone video compressed to 720p = **$0.075**; a 10-second GIF = **$0.015**. Trim first to pay only for the part you need. Set a maximum total charge on the run and the Actor stops cleanly before exceeding it.

Other media converters on the Apify Store (30-day users at the time of writing):

| Actor | Users (30 d) | Price model |
|---|---|---|
| hgservices/video-downloader-converter | 25 | $0.01 per result |
| whitewalk/ffmpeg-cloud-mcp | 24 | – |
| rixin/video-compressor | 5 | – |
| codingfrontend/video-converter | 4 | $0.005 per result |
| akash9078/audio-file-converter | 0 | – |

Per-result pricing is cheaper for very short clips; per-minute pricing is predictable for long files and covers target-size compression, GIF, audio extraction, loudness normalization, trimming and HLS in one Actor.

### FAQ

**Can I convert a YouTube or TikTok video?** No. Platform pages are refused on purpose (their terms forbid downloading). Use a direct link to a file you own or may process.

**How big can files be?** Up to `maxFileSizeMb` (500 MB default, max 5,000). For files over ~1 GB, run with 8 GB+ memory. Length is capped by `maxDurationMinutes` (60 default) so a wrong link can't create a large bill.

**How accurate is the target size?** Two-pass H.264 usually lands within ±5% (20 MB requested → 19.9 MB in our test). Very short or very static clips may come out smaller.

**Which resolution am I billed for?** The output's short side: a 1080p video compressed to 720p is billed as HD. Vertical (portrait) videos use the same rule, so a 1080×1920 phone video is Full HD.

**Is the quality good?** MP4 uses x264 `veryfast` with CRF 22/26/30, AAC audio and `+faststart` for instant web playback. WebM uses fast real-time VP9 (larger than MP4 at the same quality, but plays natively in browsers). GIFs use a per-clip palette with dithering.

**How long are files kept?** In the run's default key-value store, subject to your Apify data retention. Download or copy them if you need them longer.

**Private files?** Use pre-signed S3/GCS/R2 URLs or any link that works without a login. Hosts that block datacenter IPs work with the proxy option.

### Use with AI agents / Apify MCP

The Actor works as a tool in the [Apify MCP server](https://mcp.apify.com) (Claude, Cursor, VS Code, ChatGPT and other MCP clients) and through the Apify API. An agent can say *"compress this video to 10 MB"*, *"give me the audio of this file as MP3"* or *"make a 5-second GIF starting at 0:42"* and get back a public `fileUrl`. Typical chain: media URL → this Actor (`extract-audio`, mp3/m4a) → a transcription Actor → summary.

```bash
curl -X POST "https://api.apify.com/v2/acts/gazidev~media-converter/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mediaUrls":["https://download.samplelib.com/mp4/sample-10s.mp4"],"operation":"extract-audio","audioFormat":"mp3"}'
```

# Actor input Schema

## `mediaUrls` (type: `array`):

Direct links to video or audio FILES: MP4, MOV, WebM, MKV, AVI, MP3, WAV, M4A, FLAC, OGG, or HLS `.m3u8` playlists (your CDN, S3/R2/GCS bucket, Dropbox direct link…). Pages of YouTube, TikTok, Instagram, Vimeo, SoundCloud etc. are refused: this is a converter, not a downloader.

## `bulkText` (type: `string`):

One URL per line or a CSV with a `url` column.

## `datasetId` (type: `string`):

Chain after another Actor that outputs media file URLs.

## `datasetField` (type: `string`):

Field name in that dataset.

## `operation` (type: `string`):

What to do with every file. Trim (`startTime`/`endTime`), `maxResolution`, `fps`, `mute` and `normalizeAudio` work with every operation where they make sense.

## `videoFormat` (type: `string`):

For `compress-video` and `convert-video`.

## `compressionLevel` (type: `string`):

Quality preset for video encoding. `convert-video` uses `high` unless you choose otherwise. Ignored when `targetSizeMb` is set.

## `targetSizeMb` (type: `number`):

Optional, `compress-video` only: hit this size (two-pass bitrate encoding), e.g. 8 for Discord or 16 for WhatsApp. The result is usually within ±5%.

## `maxResolution` (type: `string`):

Downscale so the short side is at most this (works for landscape and portrait). Never upscales. Default 720p for `compress-video`; `convert-video` keeps the original unless you choose. Billing depends on the output resolution.

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

0 = keep the source frame rate. E.g. 30 or 24 to reduce size.

## `mute` (type: `boolean`):

Drop the audio track from video output.

## `normalizeAudio` (type: `boolean`):

Even out loudness with ffmpeg `loudnorm` (podcast/social standard). Adds 3 audio-minutes ($0.015) per output minute.

## `audioFormat` (type: `string`):

For `extract-audio` and `convert-audio`.

## `audioBitrateKbps` (type: `integer`):

For MP3, M4A, OGG and Opus (WAV/FLAC are lossless). 128 = podcasts/voice, 192 = good music, 320 = maximum MP3.

## `gifFps` (type: `integer`):

10–15 looks smooth; lower = smaller file.

## `gifWidth` (type: `integer`):

Height follows the aspect ratio. Uses a per-clip color palette for good quality.

## `gifMaxSeconds` (type: `number`):

The GIF starts at `startTime` and lasts until `endTime` or this many seconds, whichever is shorter.

## `startTime` (type: `string`):

Optional, any operation: seconds (`12.5`) or `HH:MM:SS` / `MM:SS`.

## `endTime` (type: `string`):

Optional, any operation, e.g. `00:01:30`.

## `maxFileSizeMb` (type: `integer`):

Larger files are skipped with an error row (not charged). Above ~1,000 MB give the run more memory.

## `maxDurationMinutes` (type: `integer`):

Cost cap: longer media are skipped (not charged) - trim them or raise the limit.

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

Encoding is CPU-bound; more than 2 only helps with more memory (CPU).

## `proxyConfiguration` (type: `object`):

Only for hosts that block datacenter IPs (HTTP 403).

## Actor input object example

```json
{
  "mediaUrls": [
    "https://download.samplelib.com/mp4/sample-10s.mp4"
  ],
  "datasetField": "url",
  "operation": "compress-video",
  "videoFormat": "mp4",
  "compressionLevel": "balanced",
  "maxResolution": "720",
  "fps": 0,
  "mute": false,
  "normalizeAudio": false,
  "audioFormat": "mp3",
  "audioBitrateKbps": 192,
  "gifFps": 10,
  "gifWidth": 480,
  "gifMaxSeconds": 10,
  "maxFileSizeMb": 500,
  "maxDurationMinutes": 60,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `all` (type: `string`):

No description

## `files` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "mediaUrls": [
        "https://download.samplelib.com/mp4/sample-10s.mp4"
    ],
    "operation": "compress-video"
};

// Run the Actor and wait for it to finish
const run = await client.actor("gazidev/media-converter").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 = {
    "mediaUrls": ["https://download.samplelib.com/mp4/sample-10s.mp4"],
    "operation": "compress-video",
}

# Run the Actor and wait for it to finish
run = client.actor("gazidev/media-converter").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 '{
  "mediaUrls": [
    "https://download.samplelib.com/mp4/sample-10s.mp4"
  ],
  "operation": "compress-video"
}' |
apify call gazidev/media-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gazidev/media-converter"
        }
    }
}
```

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/XK2ZhD5JVcaFSjZYo/builds/jmoGQ7YWoBZZnpww4/openapi.json
