MediaMetaX avatar

MediaMetaX

Pricing

from $5.00 / 1,000 results

Go to Apify Store
MediaMetaX

MediaMetaX

MediaMetaX is an Apify Actor designed to extract video and audio metadata quickly, accurately, and comprehensively using FFmpeg/FFprobe. It’s perfect for content creators, podcasters, video editors, media engineers, digital agencies, and developers who need technical media information.

Pricing

from $5.00 / 1,000 results

Rating

0.0

(0)

Developer

fanio zilla

fanio zilla

Maintained by Community

Actor stats

0

Bookmarked

11

Total users

4

Monthly active users

a month ago

Last modified

Security

Limited permissions

Share

Video and audio metadata extraction with FFmpeg/FFprobe.

Download one video or audio file, read its technical metadata with FFprobe, optionally grab a thumbnail frame with FFmpeg, and publish one record to the dataset.

Built for content catalogs, podcast and video libraries, asset pipelines, and developers who need reliable media specs without running FFmpeg themselves.

What it does

Given a direct URL to a media file, the Actor downloads it to a temporary workspace, probes it, and publishes a single JSON record per run:

  • Duration in seconds
  • Bitrate in kbps
  • Codec — the video codec, falling back to the audio codec
  • Resolution and frame rate — video files only, omitted for audio-only
  • Audio channel count — omitted when the file has no audio stream
  • File size in bytes and container format
  • Optional thumbnail — a JPEG frame grabbed at 1 second, stored in a key-value store, referenced by public URL

The file is streamed to disk and deleted when the run ends, successful or not.

Cost

Pay-per-event pricing. The platform charges two events:

EventPriceWhen it fires
Actor Start$0.00005Once per run, based on allocated memory (1 event per GB, minimum 1)
Dataset Record$0.005Once per successfully published record

Two things worth knowing before you bill against this:

  • A failed run still costs for Actor Start. The start charge is based on memory allocation, so a URL that 404s, times out, or is unreadable is billed for the start charge only. No extraction event is charged for failed runs.
  • A dropped thumbnail is still billed as an extraction. If the thumbnail grab fails, the Actor publishes the record without thumbnailUrl and charges the extraction event. The metadata record was delivered; the thumbnail is cosmetic. Check for thumbnailUrl rather than assuming success means you got one.

Standard platform fees for dataset and key-value store usage apply on top.

Input

FieldTypeRequiredDefaultDescription
mediaUrlstringYes—Direct HTTP/HTTPS URL to a video or audio file
extractThumbnailbooleanNofalseGrab a JPEG frame at the 1-second mark and attach its public URL to the record
downloadTimeoutSecsintegerNo120Budget for one download attempt, shared by any redirects it follows

mediaUrl must be a parseable http/https URL that answers with a non-empty body — directly, or after up to 5 redirects. Direct file URLs work best — pages that link to media, or URLs requiring a session or a referrer header, generally do not.

Input example

{
"mediaUrl": "https://mdn.github.io/shared-assets/videos/flower.mp4",
"extractThumbnail": true
}

Output

Every run publishes exactly one record to the dataset. Which of the two shapes you get is decided by success.

Success record

{
"success": true,
"sourceUrl": "https://mdn.github.io/shared-assets/videos/flower.mp4",
"duration": 5.055,
"bitrate": 1785,
"codec": "h264",
"resolution": "960x540",
"fps": 29.97002997002997,
"fileSize": 1128375,
"format": "mov,mp4,m4a,3gp,3g2,mj2",
"audioChannels": 2,
"thumbnailUrl": "https://api.apify.com/v2/key-value-stores/.../thumbnail.jpg"
}
FieldTypeAlways presentDescription
successbooleanYestrue on this shape
sourceUrlstringYesThe mediaUrl that was probed
durationnumberYesSeconds. 0 when the container reports no duration
bitratenumberYesKilobits per second, rounded down. 0 when unknown
codecstringYesVideo codec, else audio codec, else "unknown"
fileSizenumberYesBytes. 0 when unknown
formatstringYesContainer format, e.g. mp4. "unknown" when absent
resolutionstringNoWIDTHxHEIGHT, video streams only
fpsnumberNoVideo streams only; omitted when the container reports a zero frame-rate denominator
audioChannelsnumberNoOmitted when the file carries no audio stream
thumbnailUrlstringNoPresent only when extractThumbnail was requested and the frame was captured

Fields marked "No" are genuinely absent from the record, not null — filter on key presence rather than truthiness if that distinction matters to your pipeline.

Failure record

{
"success": false,
"sourceUrl": "https://example.com/missing.mp4",
"error": "Failed to download file: HTTP 404"
}

A failure record carries only success, sourceUrl, and error. It is published only once mediaUrl is known — a run rejected during input validation has nothing to record against, so it publishes nothing and exits non-zero.

Failure behavior

The Actor routes each kind of failure differently, and the route is decided in one place rather than at each throw site.

What failedRecord publishedExitBilled
Input validationNoneNon-zeroActor Start only
Downloadsuccess: falseNon-zeroActor Start only
Probe / unreadable mediasuccess: falseNon-zeroActor Start only
Thumbnailsuccess: true, without thumbnailUrlSuccessActor Start + extraction
Unexpected internal errorsuccess: falseNon-zeroActor Start only

A failed thumbnail is the only soft failure. The thumbnail is cosmetic, so the run degrades instead of dying: the record still publishes, the run still exits successfully, and the run is still billed as an extraction. Check for thumbnailUrl rather than assuming a successful run produced one.

A thumbnail that is captured but then fails to store is not softened — that is a platform failure, not a thumbnail failure, and the run fails.

Note: Actor Start is charged by the platform based on allocated memory and is separate from your code's extraction charge. This run never manually charges the start event.

Usage

Console

Fill in Media File URL, optionally tick Extract Thumbnail, and start the run. Results appear in the dataset tab; the thumbnail, if captured, appears under the run's key-value store.

API

curl -X POST \
"https://api.apify.com/v2/acts/YOUR-USERNAME~video-audio-metadata-extractor/runs?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mediaUrl": "https://mdn.github.io/shared-assets/videos/flower.mp4",
"extractThumbnail": true
}'

CLI

apify run \
-c '{"mediaUrl":"https://mdn.github.io/shared-assets/videos/flower.mp4","extractThumbnail":true}' \
-w

JavaScript SDK

import { Apify } from 'apify';
const client = new Apify({ token: 'YOUR_TOKEN' });
const run = await client.actor('YOUR-USERNAME/video-audio-metadata-extractor').call({
mediaUrl: 'https://mdn.github.io/shared-assets/videos/flower.mp4',
extractThumbnail: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);

Supported formats

The Actor does not gate on file extension or container. Anything the bundled FFprobe build can read is accepted, which in practice means:

  • Video — MP4, MOV, MKV, WebM, AVI, FLV, WMV, MPEG, 3GP
  • Audio — MP3, AAC, WAV, FLAC, OGG, M4A, WMA
  • Codecs — H.264, H.265/HEVC, VP8, VP9, AV1, AAC, MP3, FLAC, Opus, Vorbis

A file FFprobe cannot parse produces a probe-classified failure rather than a wrong answer.

Limits and notes

  • One file per run. There is no batch input; schedule or loop the Actor over a list.
  • downloadTimeoutSecs per download attempt (120 by default), up to 3 attempts. Redirects are followed within an attempt, up to 5, and share that attempt's budget.
  • http and https only. Any other scheme fails immediately.
  • No file size limit. The download streams straight to disk, so memory use does not scale with file size. The practical ceiling is your run's disk and the timeout.
  • Node.js 22, FFmpeg and FFprobe bundled in the image.
  • Temporary files are always cleaned up, including on failure.

Development

apify run # run locally
npm test # hermetic suite, no network or FFmpeg needed
npm run build # compile to dist/

Platform-level test specification

The hermetic suite cannot verify charging against the platform's registered pay-per-event events — that requires the real platform pricing table. A Jasmine-style spec at .actor/spec.js drives the deployed Actor on the Apify platform to verify:

  • Exact charge sequences on success and failure paths
  • Deployed build matches the repository
  • Completion within the Store's five-minute test budget
  • Non-empty dataset on successful runs

Run on demand after deployment:

$apify call actorify/actor-testing -f .actor/spec-input.json --json

This is not part of the PR workflow (it costs money and needs a deployed build). Run it on demand or set up a scheduled workflow if automated verification is desired.

Architecture

  • ./docs/adr/0001-failure-routing-lives-in-one-route-table.md
  • ./docs/adr/0002-charging-at-the-success-seam.md
  • ./docs/adr/0003-ports-and-fakes-testing.md
  • ./docs/adr/0004-no-downloader-seam.md

Resources