# Media Toolkit — Video Converter, Compressor, MP4 to MP3 & GIF (`saliga/media-toolkit`) Actor

Convert, compress, trim and resize video and audio files in bulk with FFmpeg: MP4, WebM, MP3, M4A, WAV, GIF and thumbnails from direct links, Google Drive or Dropbox. No upload limits of online converters.

- **URL**: https://apify.com/saliga/media-toolkit.md
- **Developed by:** [Salih Küçükkayış](https://apify.com/saliga) (community)
- **Categories:** Videos, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 file processeds

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

Convert, compress, trim and resize **video and audio files in bulk** with FFmpeg: MP4, WebM, MOV, MKV, **MP4 to MP3**, M4A, WAV, OGG, FLAC, Opus, animated **GIFs** and **thumbnails**. Give it direct file links or Google Drive and Dropbox share links; get the converted files back as download links. No upload limits, no watermarks, no sign-ups on converter sites.

**$3 per 1,000 files, plus $3 per 1,000 minutes of audio output or $20 per 1,000 minutes of video or GIF output** (encoding video takes far more computing than audio). Thumbnails count only as a file. Failed files are free. No platform usage fees.

### Quick start

Press **Start** with the example input. It turns a 30-second 1080p sample video into an MP3:

```json
{
  "fileUrls": ["https://samplelib.com/mp4/sample-30s.mp4"],
  "outputFormat": "mp3"
}
```

You get one row per file (a real run):

```json
{
  "url": "https://samplelib.com/mp4/sample-30s.mp4",
  "outputUrl": "https://api.apify.com/v2/key-value-stores/…/records/000-sample-30s.mp3",
  "outputFormat": "mp3",
  "outputBytes": 488322,
  "inputBytes": 21657943,
  "sizeChangePct": -97.7,
  "outputSeconds": 30.44,
  "input": { "container": "mov,mp4,m4a,3gp,3g2,mj2", "durationSec": 30.44, "width": 1920, "height": 1080, "videoCodec": "h264", "fps": 30, "audioCodec": "aac", "channels": 2 },
  "output": { "container": "mp3", "durationSec": 30.48, "audioCodec": "mp3", "sampleRate": 44100, "channels": 2 },
  "billedMinutes": 1,
  "error": null
}
```

### What you can do

| Goal | Settings |
|---|---|
| **Video to MP3** (or M4A, WAV, OGG, FLAC, Opus) | `outputFormat: "mp3"` |
| **Compress a video** | `outputFormat: "mp4"`, `quality: "small"`, or `targetSizeMb: 25` |
| **Convert** MOV/MKV/AVI to MP4 or WebM | `outputFormat: "mp4"` or `"webm"` |
| **Trim** a clip | `start: "0:30"`, `end: "1:15"` |
| **Resize** to 720p width or for social media | `width: 1280` (keeps the aspect ratio, never upscales) |
| **GIF** from a video | `outputFormat: "gif"`, `start`, `gifSeconds: 5`, `width: 480` |
| **Thumbnails** | `outputFormat: "jpg"`, `thumbnailCount: 6` (evenly spaced) |
| **Remove the sound** | `removeAudio: true` |

Settings apply to every file in the run, so one run can turn 200 MOV files into compressed 720p MP4s.

### Input

| Field | Default | Meaning |
|---|---|---|
| `fileUrls` | | Direct links, Google Drive or Dropbox share links. |
| `outputFormat` | `mp4` | mp4, webm, mov, mkv, mp3, m4a, wav, ogg, flac, opus, gif, jpg, png, webp. |
| `start`, `end` | | Trim (seconds, `1:30`, `00:01:30.5`). |
| `quality` | `medium` | `high`, `medium` or `small` (more compression). |
| `targetSizeMb` | | Compress to about this size instead. |
| `width`, `fps` | | Resize and frame rate. |
| `removeAudio` | `false` | Video without sound. |
| `audioBitrateKbps` | | Audio bitrate. |
| `thumbnailCount` | `1` | Images per file for jpg, png, webp. |
| `gifSeconds` | `10` | Longest GIF (up to 60 s). |
| `maxFileSizeMb`, `maxDurationMinutes` | `1000`, `180` | Larger or longer files are skipped (free). |

### Output

One dataset row per input file:

| Field | Meaning |
|---|---|
| `url` | The input link |
| `outputUrl` or `outputFiles` | Download link(s) of the result (several for thumbnails) |
| `outputFormat`, `outputBytes`, `inputBytes`, `sizeChangePct` | Result and how much smaller or larger it is |
| `outputSeconds`, `billedMinutes` | Length of the result and minutes charged |
| `input`, `output` | Container, duration, resolution, codecs, frame rate, audio channels |
| `error` | Why the file failed (failed files are free) |

The files are in the run's key-value store as well.

### What it costs

| Run | Price |
|---|---|
| 100 videos of about 3 minutes to MP3 | $1.20 |
| 50 videos of about 5 minutes compressed to MP4 | $5.15 |
| 200 five-second GIFs | $4.60 |
| Thumbnails of 1,000 videos | $3.00 |

Pricing: $0.003 per file, $0.003 per started minute of audio output, $0.02 per started minute of video or GIF output. Platform usage is included.

### Good to know

- **Your files only.** Pages of YouTube, TikTok, Instagram and other platforms are refused; use direct links to files you may process. Google Drive and Dropbox links must be shared as "Anyone with the link".
- Video is encoded with H.264 (MP4, MOV, MKV) or VP9 (WebM), audio with AAC, MP3, Opus or Vorbis. MP4 files are ready for the web (fast start).
- `targetSizeMb` sets the bitrate from the duration, so the result is close to, not exactly, that size.
- Private and internal network addresses are refused, and FFmpeg only reads the downloaded file (playlists and other files that point to links are not supported).
- If the run is moved to another server, files already done are not processed or charged again.

### FAQ

**Can I convert a YouTube video?** No. This Actor processes files you have, by direct link.

**How big can files be?** Up to 4 GB each (`maxFileSizeMb`); the default limit is 1 GB.

**Am I charged for files that fail?** No.

**Can I use it from Make, Zapier, n8n or an AI agent?** Yes, like any Apify Actor: through Apify's integrations, the Apify API or the Apify MCP server.

### Next steps with your results

- Transcribe the converted MP3s or videos with [Audio to Text](https://apify.com/saliga/audio-to-text) (paste the output links).
- Split videos into scenes with keyframes and a transcript per scene with [Video to Scenes](https://apify.com/saliga/video-to-scenes).
- Download many files first, or put the results in one ZIP, with [Bulk File & Image Downloader](https://apify.com/saliga/bulk-file-downloader).

### More from this developer

- [Audio to Text](https://apify.com/saliga/audio-to-text): audio, video and podcast feeds to timestamped text and SRT/VTT subtitles with Whisper, $8 per 1,000 audio minutes.
- [Video to Scenes](https://apify.com/saliga/video-to-scenes): scene cuts, one keyframe per scene, a contact sheet and the transcript of each scene, $2 per 1,000 frames.
- [Bulk File & Image Downloader](https://apify.com/saliga/bulk-file-downloader): download files from many URLs, Drive or Dropbox into one ZIP.
- [Image to Text OCR](https://apify.com/saliga/image-to-text-ocr): text from images and scanned PDFs in 40+ languages, $1.50 per 1,000 images.

Code examples (curl, Python, Node.js, n8n) for this and the other Actors: [github.com/msalihk/apify-actor-examples](https://github.com/msalihk/apify-actor-examples).

Questions or a missing feature: open an issue on the Actor page.

# Actor input Schema

## `fileUrls` (type: `array`):

Direct links to video or audio files, or Google Drive / Dropbox share links (shared as "Anyone with the link"). Pages of YouTube, TikTok and other platforms are not supported.

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

What to make. Video: MP4 (H.264), WebM (VP9), MOV, MKV. Audio only: MP3, M4A (AAC), WAV, OGG, FLAC, Opus. Animated GIF. Still images: JPG, PNG, WebP (thumbnails).

## `start` (type: `string`):

Optional: cut from this time (seconds, 1:30 or 00:01:30.5).

## `end` (type: `string`):

Optional: cut until this time.

## `quality` (type: `string`):

Compression level for video and audio.

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

Optional: compress each output to about this size (sets the bitrate from the duration). Overrides quality.

## `width` (type: `integer`):

Optional: resize to this width, keeping the aspect ratio (never upscales). For GIFs the default is 480.

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

Optional: frames per second for video and GIF (GIF default 12).

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

Video outputs without the sound track.

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

Optional: audio bitrate for MP3, M4A, OGG, Opus and video sound.

## `thumbnailCount` (type: `integer`):

For JPG/PNG/WebP: how many frames, evenly spaced over the file (or the trimmed part).

## `gifSeconds` (type: `number`):

Longest GIF to make, from the start time.

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

Files larger than this are skipped (free).

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

Longer files are skipped (free).

## Actor input object example

```json
{
  "fileUrls": [
    "https://samplelib.com/mp4/sample-30s.mp4"
  ],
  "outputFormat": "mp3",
  "quality": "medium",
  "removeAudio": false,
  "thumbnailCount": 1,
  "gifSeconds": 10,
  "maxFileSizeMb": 1000,
  "maxDurationMinutes": 180
}
```

# Actor output Schema

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

One row per input file: the output link, sizes, durations and codecs.

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

All converted files in the run's key-value store.

# 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 = {
    "fileUrls": [
        "https://samplelib.com/mp4/sample-30s.mp4"
    ],
    "outputFormat": "mp3"
};

// Run the Actor and wait for it to finish
const run = await client.actor("saliga/media-toolkit").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 = {
    "fileUrls": ["https://samplelib.com/mp4/sample-30s.mp4"],
    "outputFormat": "mp3",
}

# Run the Actor and wait for it to finish
run = client.actor("saliga/media-toolkit").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 '{
  "fileUrls": [
    "https://samplelib.com/mp4/sample-30s.mp4"
  ],
  "outputFormat": "mp3"
}' |
apify call saliga/media-toolkit --silent --output-dataset

```

## MCP server setup

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

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/7AYYHvcczXoMaOx5C/builds/Y1a0kRXdKbrdfFZKZ/openapi.json
