# Media File Inspector – ffprobe, LUFS & Spec Check (`aleksejsg/media-delivery-inspector`) Actor

Check video/audio files against festival, broadcast (EBU R128), streaming or podcast delivery specs: codec, resolution, frame rate, interlacing, audio channels, integrated loudness (LUFS) and true peak. ffprobe + ffmpeg in the cloud, no install.

- **URL**: https://apify.com/aleksejsg/media-delivery-inspector.md
- **Developed by:** [Aleksej Sg](https://apify.com/aleksejsg) (community)
- **Categories:** Videos, Developer tools, For creators
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Media File Inspector – ffprobe, LUFS Loudness & Delivery Spec Checker

Check a **video or audio file against a delivery spec in one click**: codec, container, resolution, frame rate,
interlacing, pixel aspect, audio channels and sample rate, plus **EBU R128 integrated loudness (LUFS), loudness range
and true peak**. It is ffprobe + ffmpeg loudness metering in the cloud: no install, no command line, works from the API, Make, n8n or Zapier.

Built by a working film editor and subtitler who checks festival screeners and masters every week.

### Who it is for

- **Filmmakers and editors** submitting to festivals (FilmFreeway screeners, ProRes masters)
- **Post-production and dubbing studios** doing batch QC before delivery
- **Podcasters and YouTubers** checking loudness targets (-14/-16 LUFS, -23 LUFS EBU R128, -24 LKFS)
- **Developers** who need `ffprobe` JSON / media metadata from a URL without running ffmpeg servers

### Presets

| Preset | Checks |
|---|---|
| `festival-screener` | MOV/MP4/MKV, H.264/ProRes/HEVC, ≥720p, 23.976/24/25/29.97 fps, -27..-20 LUFS, true peak ≤ -1 dBTP |
| `festival-prores-master` | MOV ProRes, ≥1080p, 23.976/24/25 fps |
| `ebu-r128-broadcast` | -23 LUFS ±1, true peak ≤ -1 dBTP, 25/50 fps |
| `web-streaming` | MP4/MOV H.264/HEVC, -16..-13 LUFS (YouTube, Spotify video, Instagram) |
| `podcast` | -16 LUFS ±1, true peak ≤ -1 dBTP |
| `none` | metadata only |

Presets summarise public guidelines; always check your festival's or broadcaster's own spec.

### Input

Direct file URLs (S3 / signed links, Dropbox `?dl=1`, Google Drive direct download, your own server). Not YouTube pages:
this Actor inspects files you own, it does not download from video platforms.

```json
{"mediaUrls": ["https://example.com/my-short-film.mov"], "preset": "festival-screener", "measureLoudness": true}
```

### Output (one row per file)

`passed`, `errors`, `warnings`, `issues[]` (code + message), `container`, `duration_s`, `bitrate_kbps`,
`video{codec, profile, width, height, fps, pix_fmt, field_order, sar, dar, timecode}`,
`audio[]{codec, channels, layout, sample_rate, language}`, `subtitle_tracks[]`, `loudness{integrated_lufs, lra_lu, true_peak_dbtp}`.

### Pricing (pay per event)

- $0.01 per file inspected (metadata + spec check)
- $0.02 per loudness measurement
  A 10-file festival batch with loudness costs $0.30 plus Apify platform usage.

### FAQ

**Is my file stored?** It is streamed to a temporary file, measured and deleted at the end of the run.
**LUFS vs LKFS?** Same scale; -24 LKFS (ATSC A/85) ≈ -24 LUFS.
**Max size?** 2 GB by default (`maxFileSizeMb`). Use `loudnessMaxSeconds` for a quick check of long files.

Keywords: ffprobe online, mediainfo API, video metadata extractor, LUFS meter, loudness checker, EBU R128, true peak,
festival delivery QC, ProRes check, frame rate checker, audio loudness normalization check, video QC tool.

### Example output row (shortened)

```json
{"url": "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4", "passed": false, "errors": 1, "warnings": 0,
 "container": "mov", "duration_s": 734.1, "video": {"codec": "h264", "width": 1920, "height": 800, "fps": 24.0},
 "loudness": {"integrated_lufs": -18.9, "lra_lu": 9.1, "true_peak_dbtp": -0.4},
 "issues": [{"code": "true_peak", "message": "True peak -0.4 dBTP > -1 dBTP"}]}
```

(See the test run for actual values.)

### 🇮🇹 In italiano

**Controllo file video/audio per la consegna** a festival, broadcast (EBU R128), streaming o podcast: codec,
risoluzione, frame rate, interlacciamento, canali audio, loudness integrata (LUFS) e true peak. ffprobe + ffmpeg nel
cloud, senza installare nulla. Prezzo: **0,01 $ per file ispezionato + 0,02 $ per misura di loudness**.

# Actor input Schema

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

Direct links to video or audio files (MP4, MOV, MKV, MXF, WAV, MP3...). Signed S3/Drive-direct/Dropbox ?dl=1 links work. Not YouTube pages.

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

Delivery spec to check against: festival-screener, festival-prores-master, ebu-r128-broadcast (-23 LUFS), web-streaming (-14 LUFS), podcast (-16 LUFS), or none for metadata only.

## `measureLoudness` (type: `boolean`):

Measure EBU R128 integrated loudness (LUFS), loudness range (LU) and true peak (dBTP). Adds one 'loudness-measured' event per file and takes about real-time/20.

## `loudnessMaxSeconds` (type: `integer`):

Measure loudness only on the first N seconds for a quick, cheaper check of long files. Leave empty to measure the whole file.

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

Safety cap on how many files are processed (and billed) in one run.

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

Files larger than this are skipped with an error (not billed). Raise it for big masters; download time grows with size.

## Actor input object example

```json
{
  "mediaUrls": [
    "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4"
  ],
  "preset": "festival-screener",
  "measureLoudness": true,
  "loudnessMaxSeconds": 60,
  "maxFiles": 20,
  "maxFileSizeMb": 2000
}
```

# Actor output Schema

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

One row per media file: container, video/audio stream specs, loudness (LUFS, true peak) and pass/fail against the chosen delivery preset.

# 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://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4"
    ],
    "loudnessMaxSeconds": 60
};

// Run the Actor and wait for it to finish
const run = await client.actor("aleksejsg/media-delivery-inspector").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://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4"],
    "loudnessMaxSeconds": 60,
}

# Run the Actor and wait for it to finish
run = client.actor("aleksejsg/media-delivery-inspector").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://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/360/Big_Buck_Bunny_360_10s_1MB.mp4"
  ],
  "loudnessMaxSeconds": 60
}' |
apify call aleksejsg/media-delivery-inspector --silent --output-dataset

```

## MCP server setup

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

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/0JAICcfgscpHxJRs5/builds/eewfqydl2QjXcS11e/openapi.json
