# Media Converter — Convert, Compress & Trim Video and Audio (`nexgensignal/media-converter`) Actor

Convert video and audio files by link with FFmpeg: MP4, WebM, MKV, MOV, GIF, MP3, M4A, WAV, OGG, FLAC. Compress to a target size, trim, resize, watermark, extract or remove audio. Saved with download links. Billed per minute. Part of NexGen Signal — data tools and official-source data products

- **URL**: https://apify.com/nexgensignal/media-converter.md
- **Developed by:** [NexGen Signal](https://apify.com/nexgensignal) (community)
- **Categories:** Videos, Automation, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $33.50 / 1,000 media minutes

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## 🎬 Media Converter — Convert, Compress & Trim Video and Audio

Give direct links to **audio or video files** and get each one **converted with FFmpeg** and saved with a download link: MP4, WebM, MKV, MOV, animated GIF, MP3, M4A, WAV, OGG or FLAC.

In the same step you can **compress** (three quality levels, or a **target file size** in MB hit with two-pass encoding), **trim** to a start and end time, **resize** to a maximum width or height, **change the frame rate**, add a **text or image watermark**, **extract the sound** from a video (choose an audio format), or **remove it**. Each row gives the new file's size, length, picture size and codecs next to the original's, and how much smaller it got.

The unit of billing is one started minute of output: a 20-second GIF is 1 minute, a 40-minute podcast is 40. Files that cannot be converted are not billed.

### Who buys this and for what job

- **Marketers and creators** compressing videos and making GIFs for the web.
- **Podcasters** turning recordings into MP3 or M4A at the right bitrate.
- **AI and data teams** pulling audio out of video before transcription.
- **Developers** adding a conversion step to an Apify workflow without running FFmpeg themselves.

Buyers usually search for this as **"video converter"**, **"compress video"**, **"video to mp3"** or **"ffmpeg online"**.

### 📊 Sample Output

![Table of converted files: input, output format, duration, size, size change and minutes billed.](https://api.apify.com/v2/key-value-stores/IXCaMKjxSmUTLHhmq/records/media-converter.png)

| input | output_format | output_duration_seconds | output_bytes | size_change_percent | minutes_billed |
|---|---|---|---|---|---|
| Apollo 11 launch film (MP4) | mp4 | 84.2 | 765146 | -95.1 | 2 |
| Apollo 11 launch film (MP4) | gif | 6 | 2873456 | -81.5 | 1 |
| SLS resource reel (MP4) | webm | 30 | 118087 | -98.7 | 1 |
| 590325main_ringtone_kennedy_WeChoose.mp3 | flac | 20.088 | 1479768 | 355.4 | 1 |
| 590331main_ringtone_smallStep.mp3 | flac | 12.983 | 742749 | 251.2 | 1 |
| NATIONALAERONAUTICSANDSPACEADMINISTRATIO | m4a | 2400 | 29484275 | -83 | 40 |

Rows from live run `kRgjI9drZGTPoFb8P` on Apify (five proof runs on NASA films, clips and a podcast episode). Notice the 40-minute M4A: it is cut from a 72-minute episode with endSeconds, and only the 40 minutes kept are billed.

### ✅ What you get

Every field of each record:

- `record_id`, `input_url`, `output_format` — the file and what it became.
- `file_key`, `file_url` — the converted file in the run's key-value store.
- `output_bytes`, `input_bytes`, `size_change_percent` — sizes before and after.
- `output_duration_seconds`, `minutes_billed` — length of the result and the started minutes billed.
- `output_width`, `output_height`, `output_video_codec`, `output_audio_codec` — the result's picture size and codecs.
- `input_duration_seconds`, `input_format`, `input_width`, `input_height`, `input_video_codec`, `input_audio_codec` — the original.
- `trim_start_seconds`, `trim_end_seconds` — the cut.
- `target_size_mb`, `video_kbps`, `watermark` — the size target and the bitrate used for it; which watermark was applied.
- `processing_seconds`, `converted_at` — FFmpeg's time, and when (UTC).

### ⚙️ Sample inputs

**Compress a video (the Store example)**

```json
{
  "mediaUrls": ["https://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4"],
  "outputFormat": "mp4",
  "videoQuality": "small",
  "maxFiles": 10
}
```

84 seconds of film: 15.5 MB down to 0.77 MB, 2 minutes billed.

**A GIF from six seconds of video**

```json
{
  "mediaUrls": ["https://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4"],
  "outputFormat": "gif",
  "startSeconds": 40,
  "endSeconds": 46,
  "maxWidth": 320,
  "maxFiles": 5
}
```

320 px wide, 10 frames per second.

**Extract the audio as MP3**

```json
{
  "mediaUrls": ["https://example.com/talk.mp4"],
  "outputFormat": "mp3",
  "audioBitrateKbps": 128,
  "maxFiles": 10
}
```

Audio formats keep only the sound.

**Under 25 MB with a watermark**

```json
{
  "mediaUrls": ["https://example.com/talk.mp4"],
  "outputFormat": "mp4",
  "targetSizeMb": 25,
  "watermarkText": "© Your Name",
  "watermarkPosition": "bottom-right",
  "maxFiles": 10
}
```

Two-pass encode to the size, text drawn in the corner.

Input fields:

| Field | Meaning |
|---|---|
| `mediaUrls` | direct audio or video file links (up to 500). Not YouTube or social media pages. |
| `outputFormat` | mp4, webm, mkv, mov, gif, mp3, m4a, wav, ogg, flac. |
| `videoQuality` | high, balanced or small (H.264 CRF 20/24/30; VP9 CRF 31/36/42). |
| `targetSizeMb` | video formats: two-pass encode to land at or under this size (0 = use videoQuality). |
| `watermarkText`, `watermarkImageUrl`, `watermarkPosition`, `watermarkOpacity` | a text and/or image (PNG keeps transparency, scaled to a fifth of the width) watermark in a corner or the centre; with both, the image takes the position and the text the opposite side. |
| `startSeconds`, `endSeconds` | trim. |
| `maxWidth`, `maxHeight`, `fps` | resize and frame rate (GIF defaults to 480 px and 10 fps). |
| `audioBitrateKbps`, `removeAudio` | sound bitrate (default 128) or no sound. |
| `maxInputMb`, `maxMinutesPerFile` | skip files over these limits (defaults 1,000 MB, 60 minutes). |
| `maxFiles` | stop after this many files (default 100). Billing is per started minute of output. |

### 🧾 JSON sample record

```json
{
  "record_id": "0061299946f55d3061963e1a",
  "input_url": "https://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4",
  "output_format": "mp4",
  "file_key": "converted-a9a6a5a99d1dd46d.mp4",
  "file_url": "https://api.apify.com/v2/key-value-stores/lw7ybRQ4xt6hRVuNe/records/converted-a9a6a5a99d1dd46d.mp4",
  "output_bytes": 765146,
  "input_bytes": 15526635,
  "size_change_percent": -95.1,
  "output_duration_seconds": 84.2,
  "minutes_billed": 2,
  "output_width": 480,
  "output_height": 480,
  "output_video_codec": "h264",
  "output_audio_codec": null,
  "input_duration_seconds": 84.2,
  "input_format": "mov,mp4,m4a,3gp,3g2,mj2",
  "input_width": 480,
  "input_height": 480,
  "input_video_codec": "h264",
  "input_audio_codec": null,
  "trim_start_seconds": null,
  "trim_end_seconds": null,
  "target_size_mb": null,
  "video_kbps": null,
  "watermark": null,
  "processing_seconds": 5.2,
  "converted_at": "2026-10-18T00:10:51Z"
}
```

### 🔧 How it works

Each file is downloaded, read with FFprobe, and converted with FFmpeg: H.264 (veryfast preset) with AAC sound for MP4, MKV and MOV, VP9 with Opus for WebM, a two-pass palette for GIF, and LAME, AAC, Vorbis, FLAC or PCM for audio. With targetSizeMb the video bitrate is worked out from the length (less the audio) and the file is encoded in two passes, which lands at or a little under the target; text watermarks use the DejaVu Sans Bold font at about 1/22 of the frame height. MP4 and MOV are written with the index at the front so they start playing before they finish downloading. Metadata is not copied to the result.

Before a file is converted, its minutes are checked against your maximum charge: a file that would go over is skipped (not cut short) and smaller files can still follow.

Every run reads each host's robots.txt first: a path it disallows is skipped, listed in the run receipt and never charged. Only public internet addresses are fetched (no private, loopback or cloud-metadata addresses, checked again on every redirect). No logins, no CAPTCHA solving, no proxies.

Saved files go to the run's own key-value store. If your Apify account keeps storages private, add your API token to the link (`?token=…`) or open the store from the run in Apify Console.

The minutes for each file are charged when its row is delivered. The run receipt (`RUN_RECEIPT`) lists every link with its outcome and minutes, and the minutes billed and charged.

### 💰 Pricing example

Per minute delivered, no start fee, no monthly charge:

| Apify plan | Price per minute |
|---|---|
| Free | $0.05 |
| Bronze | $0.045 |
| Silver | $0.04 |
| Gold, Platinum, Diamond | $0.0335 |

- The Store example, an 84-second video: 2 minutes = $0.10 on the Free plan, $0.067 on Gold.
- A 40-minute podcast to M4A: $2.00 on Free, $1.34 on Gold.
- 10 hours of video: $30.00 on Free, $20.10 on Gold.

**Coverage and size.** Proof runs on 17 Oct 2026: the first 40 minutes of a 173 MB NASA podcast MP3 converted to M4A in about 2.5 minutes (83% smaller); an 84-second video compressed to MP4 in about 5 seconds (95% smaller); 30 seconds of a reel to a 1 MB target with text and image watermarks in two passes (0.67 MB); 30 seconds of a reel to silent WebM, a 6-second GIF and two clips to FLAC in seconds each. Runs use 4 GB of memory (one CPU core) by default; more memory gives more cores and faster video conversion.

### ⚖️ Legal & ToS

Files belong to their owners. You choose the links. Make sure you have the right to download and use the content you point it at; the actor fetches only what you give it (and, where you turn it on, what those pages link to).

Every run reads each host's robots.txt first: a path it disallows is skipped, listed in the run receipt and never charged. Only public internet addresses are fetched (no private, loopback or cloud-metadata addresses, checked again on every redirect). No logins, no CAPTCHA solving, no proxies.

### ❓ FAQ

**Can I give a YouTube link?**
No. Give a direct link to the media file.

**How is a minute counted?**
Started minutes of the result: 61 seconds is 2 minutes. Trimming lowers the bill.

**Is my file sent to another service?**
No. FFmpeg runs inside the actor.

### 🆘 Troubleshooting

- **no video stream (audio only)** — Choose an audio format such as mp3 for audio files.
- **not converted: your maximum charge does not cover its N minute(s)** — Raise your maximum charge or trim the file.
- **SOURCE UNAVAILABLE** — None of your links could be reached after retries. Nothing was charged.

### 🔗 Related Actors

- [Bilibili Video Scraper](https://apify.com/nexgensignal/bilibili-video-data-api) — video data by keyword or creator
- [PR Newswire Scraper](https://apify.com/nexgensignal/press-release-monitor-api) — press releases by company or topic
- [Website Tech Stack Detector](https://apify.com/nexgensignal/website-tech-stack-api) — what a site is built with

🏢 **About NexGen Signal** — data tools and official-source data products. Browse the catalog: [apify.com/nexgensignal](https://apify.com/nexgensignal)

### ⭐ Found this useful?

If this actor saved you time, a rating on its Apify Store page helps other buyers find it.

Part of NexGen Signal — data tools and official-source data products.

# Actor input Schema

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

Direct links to media files (not YouTube or social media pages). Up to 500 per run.

## `outputFormat` (type: `string`):

Audio formats extract the sound track from a video.

## `videoQuality` (type: `string`):

Use 'small' to compress videos. Ignored for audio and GIF.

## `startSeconds` (type: `number`):

Trim: keep from this time on.

## `endSeconds` (type: `number`):

Trim: keep until this time. 0 = to the end.

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

Shrink wider videos to this width, keeping the shape. 0 = keep (GIF defaults to 480).

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

Shrink taller videos to this height, keeping the shape. 0 = keep.

## `fps` (type: `number`):

Frames per second of the result. 0 = keep (GIF defaults to 10).

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

Video formats only: encode in two passes to land at or under this size (e.g. 25 for an e-mail or chat upload). 0 = use videoQuality instead.

## `watermarkText` (type: `string`):

Text drawn on the video (up to 120 characters). Empty = none.

## `watermarkImageUrl` (type: `string`):

Link to a PNG (transparency kept) or other image, drawn at about a fifth of the video's width. Empty = none.

## `watermarkPosition` (type: `string`):

Where the watermark sits.

## `watermarkOpacity` (type: `number`):

1 = solid, 0.3 = faint.

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

For MP3, M4A, OGG and the sound in MP4/WebM/MKV/MOV.

## `removeAudio` (type: `boolean`):

Make a silent video.

## `maxInputMb` (type: `integer`):

Skip files bigger than this.

## `maxMinutesPerFile` (type: `integer`):

Skip files whose result would be longer than this (after trimming).

## `maxFiles` (type: `integer`):

Stop after this many files are converted.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4"
  ],
  "outputFormat": "mp4",
  "videoQuality": "small",
  "startSeconds": 0,
  "endSeconds": 0,
  "maxWidth": 0,
  "maxHeight": 0,
  "fps": 0,
  "targetSizeMb": 0,
  "watermarkText": "",
  "watermarkImageUrl": "",
  "watermarkPosition": "bottom-right",
  "watermarkOpacity": 0.6,
  "audioBitrateKbps": 128,
  "removeAudio": false,
  "maxInputMb": 1000,
  "maxMinutesPerFile": 60,
  "maxFiles": 10
}
```

# Actor output Schema

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

The delivered (and billed) records.

## `receipt` (type: `string`):

Per-link outcome, robots result, delivered and charged counts.

# 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://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4"
    ],
    "outputFormat": "mp4",
    "videoQuality": "small",
    "maxFiles": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgensignal/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://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4"],
    "outputFormat": "mp4",
    "videoQuality": "small",
    "maxFiles": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("nexgensignal/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://images-assets.nasa.gov/video/KSC_69-71212-sRGB/KSC_69-71212-sRGB~small.mp4"
  ],
  "outputFormat": "mp4",
  "videoQuality": "small",
  "maxFiles": 10
}' |
apify call nexgensignal/media-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexgensignal/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/fm9NdbHpSwz5uNSgB/builds/lObCQmdLHA7gnhS7e/openapi.json
