Video Frame Extractor & Media Probe for AI Agents avatar

Video Frame Extractor & Media Probe for AI Agents

Pricing

from $1.00 / 1,000 frame extracteds

Go to Apify Store
Video Frame Extractor & Media Probe for AI Agents

Video Frame Extractor & Media Probe for AI Agents

Give AI agents eyes for video: send direct video or audio file links, get ffprobe metadata (duration, codecs, resolution, fps, rotation, 9:16 check), frames at set times, every N seconds or at scene cuts, a contact sheet for vision models, EBU R128 loudness and MP3 audio.

Pricing

from $1.00 / 1,000 frame extracteds

Rating

0.0

(0)

Developer

FFS Marketing

FFS Marketing

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Security

Limited permissions

Share

Give your AI agent eyes and ears for video. Send a direct link to a video or audio file; get back its metadata (duration, codecs, resolution, frame rate, rotation, aspect ratio), frames at the times you choose, every N seconds or at scene changes, one contact sheet image sized for vision models, EBU R128 loudness, and the audio as an MP3 link. One call, JSON out.

Works as a tool for AI agents. Add it to Claude, ChatGPT, Cursor or any MCP client through Apify's MCP server (https://mcp.apify.com/?tools=fluidfaith/media-probe), or call it with one API request. Agents cannot watch video and cloud agents have no ffmpeg: this Actor is that missing step.

Costs $0.002 per file, $0.001 per frame, $0.005 per contact sheet, $0.002 per loudness measurement and $0.003 per minute of MP3 audio. Failed links and errors are free, and your maximum charge per run is never exceeded.

What an agent can do with it

  • See a clip: ask for 6 to 12 evenly spaced frames plus a contact sheet, and pass the sheet to a vision model in one image.
  • Check a deliverable before posting: is this reel 9:16, under 90 seconds, with audio, near -14 LUFS? checks.isVertical916, durationSeconds, checks.hasAudio and loudness.integratedLufs answer it.
  • Find the shots: scene mode returns the time of every cut plus one frame per shot.
  • Transcribe: extractAudio returns a small mono MP3 link ready for a speech-to-text model.

Why use it

Probe, frames, contact sheet and loudness in one call

Most frame grabbers return frames only. This Actor also reads the full ffprobe metadata, runs simple delivery checks and measures loudness, so an agent gets everything it needs about a file in one row.

Long files are not decoded end to end

Frames are taken with a seek before decoding, so asking for 5 frames of a 2-hour file decodes only a few seconds around each time. (Scene detection has to look at the whole video, so it decodes it at 5 frames per second.)

Sized for vision models

Frames default to 768 px wide and are never upscaled. The contact sheet is a grid with time labels that is at most 1568 px on its long side, the size vision models read without shrinking it.

It reads files you can link to directly (your storage bucket, CDN, Apify key-value store, a podcast feed enclosure, a client upload). It does not download from YouTube, TikTok, Instagram, Facebook, X, Vimeo or other social and streaming sites; those links get a clear error and are not charged.

Use it from an agent

Any MCP client

Add https://mcp.apify.com/?tools=fluidfaith/media-probe as a remote MCP server (OAuth or your Apify token). The agent sees one tool with the input fields below.

One API request

curl -X POST "https://api.apify.com/v2/acts/fluidfaith~media-probe/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls": ["https://example.com/reel.mp4"], "framesMode": "count", "frameCount": 9, "contactSheet": true, "loudness": true}'

Pricing

Pay per event. You only pay for what is returned.

EventPriceCharged when
File probed$0.002the file's metadata is returned
Frame extracted$0.001each frame image returned
Contact sheet$0.005each contact sheet returned
Loudness measured$0.002loudness numbers are returned
Audio minute extracted$0.003each started minute of MP3 returned

Examples:

JobCost
Metadata only (framesMode: "none")$0.002
Metadata + 6 frames (the default)$0.008
A reel check: metadata + 9 frames + contact sheet + loudness$0.018
A 12-minute podcast as MP3 for transcription + loudness$0.040
20 files, metadata + 6 frames each$0.16

Nothing is charged for blocked or social links, failed downloads, files that are not media, or files that pass a time limit. Set a maximum charge on the run and the Actor stops exactly there: what does not fit is skipped, listed in warnings and not charged, and stoppedAtSpendingCap is true in the run summary.

Input

FieldDefaultWhat it does
urlsrequired unless files givenDirect http(s) links to video or audio files (up to 20).
files[]Up to 5 small files as { "name": "clip.mp4", "base64": "..." }, 6 MB each.
framesModecountnone, count (evenly spaced), every (every N seconds), times (your list), scene (at cuts).
frameCount6Frames for count mode (1 to 100).
everyNSeconds10Seconds between frames for every mode.
frameTimes[]Times for times mode: seconds (12.5) or "mm:ss" / "hh:mm:ss".
sceneThreshold0.3Scene mode sensitivity, 0.05 (more cuts) to 0.95 (only hard cuts).
maxFramesPerFile100Hard limit on frames per file.
frameWidth768Frame width in px (64 to 3840), never upscaled.
frameFormatjpgjpg, webp or png.
contactSheetfalseAlso return a grid image of the frames with time labels.
loudnessfalseEBU R128 integrated loudness, loudness range and true peak.
extractAudiofalseReturn the first audio track as MP3.
audioQualityspeechspeech (mono 64 kbps) or music (stereo 192 kbps).
audioMaxMinutes30Audio is cut after this many minutes (up to 180).
maxFileSizeMb500Larger files are refused before download (hard limit 2048).
maxDurationSeconds0Use only the first N seconds for frames, scenes, loudness and audio (0 = whole file).
maxConcurrency2Files at the same time (1 to 4).

Example:

{
"urls": ["https://example.com/reel.mp4"],
"framesMode": "scene",
"contactSheet": true,
"loudness": true
}

Output

One dataset row per file:

{
"source": "https://example.com/reel.mp4",
"fileName": "reel.mp4",
"status": "OK",
"error": null,
"durationSeconds": 28.4,
"container": "mp4",
"containerLongName": "QuickTime / MOV",
"sizeBytes": 9123456,
"bitRate": 2570000,
"creationTime": "2026-11-02T15:04:11.000000Z",
"streams": { "video": 1, "audio": 1, "subtitle": 0, "coverArt": 0 },
"video": {
"codec": "h264", "profile": "High", "width": 1920, "height": 1080,
"displayWidth": 1080, "displayHeight": 1920, "rotation": 90,
"fps": 29.97, "aspectRatio": "9:16", "pixelFormat": "yuv420p", "bitRate": 2400000, "frameCount": 851
},
"audio": { "codec": "aac", "profile": "LC", "sampleRate": 48000, "channels": 2, "channelLayout": "stereo", "bitRate": 128000 },
"checks": { "hasVideo": true, "hasAudio": true, "isVertical": true, "isVertical916": true, "isHorizontal169": false },
"loudness": { "integratedLufs": -14.2, "loudnessRangeLu": 6.1, "truePeakDbtp": -1.3, "thresholdLufs": -24.3, "silent": false },
"frames": [
{ "index": 1, "timeSeconds": 0.0, "url": "https://api.apify.com/v2/key-value-stores/<id>/records/01-reel-mp4-1a2b3c-frame-001.jpg?signature=<signature>", "key": "01-reel-mp4-1a2b3c-frame-001.jpg", "width": 768, "height": 1366 }
],
"sceneChanges": [3.2, 7.8, 12.0, 19.4],
"contactSheetUrl": "https://api.apify.com/v2/key-value-stores/<id>/records/01-reel-mp4-1a2b3c-contact-sheet.jpg?signature=<signature>",
"contactSheet": { "columns": 3, "rows": 2, "tiles": 5, "width": 1192, "height": 1550, "timeLabels": true },
"audioUrl": null,
"audioDurationSeconds": null,
"charged": { "probes": 1, "frames": 5, "contactSheets": 1, "loudness": 1, "audioMinutes": 0, "usd": 0.014 },
"warnings": []
}
  • status: OK, PARTIAL (metadata returned but something asked for was skipped: spending limit or a frame that could not be read; see warnings) or ERROR (nothing returned, nothing charged; see error).
  • rotation is the clockwise rotation a player applies; displayWidth and displayHeight are what viewers see, and the checks use them.
  • aspectRatio is the nearest common label within 2% (16:9, 9:16, 4:3, 1:1, 4:5, 21:9 and so on), else the exact ratio.
  • Frame, contact sheet and MP3 links point to the run's key-value store and follow your Apify storage retention.

The run summary (key-value store record OUTPUT) holds counts, the total charged, stoppedAtSpendingCap and the status of every file.

Limits

  • Up to 20 links per run, 100 frames per file, 2048 MB per file (500 MB by default).
  • Time limits: download 5 minutes, each ffmpeg step 2 minutes (scene detection, loudness and audio 7 minutes), each file 10 minutes. A file that passes a limit is an ERROR row and is not charged.
  • Formats: whatever ffmpeg reads in mp4, mov, m4a, webm, mkv, avi, flv, ts, mpeg, wmv/asf, mxf, mp3, wav, ogg, opus, flac, aac, aiff and similar containers. Streaming playlists (HLS .m3u8, DASH) are refused: give a direct link to one file.

Privacy and safety

  • Files are downloaded into the run's temporary folder and deleted when the file is done. Only the frames, contact sheet and MP3 you asked for are stored, in the run's own storage.
  • Only public http(s) links are fetched. Localhost, private networks, cloud metadata addresses and internal host names are refused, also when a redirect or a DNS answer points there.
  • ffmpeg only ever reads the downloaded local file: it cannot open network addresses or other files on disk.
  • Metadata tags that can hold personal data (GPS location, device owner) are not returned; only creationTime is.

FAQ

Those sites' terms forbid downloading outside their apps, they change often, and Actors that depend on them fail a lot. This Actor is for files you have a direct link to and the right to process: your own uploads, client deliverables, your storage bucket or CDN. If you have the rights to a social video, download it with the platform's own tools and pass the file link.

Share links open a web page. Use the direct download form (Dropbox: change dl=0 to dl=1; Google Drive: a direct download link for public files) or put the file in any storage that gives a direct URL.

How do I check a reel before posting?

{"urls": ["<file>"], "framesMode": "count", "frameCount": 9, "contactSheet": true, "loudness": true}. Read checks.isVertical916, durationSeconds, checks.hasAudio and loudness.integratedLufs (most social platforms normalize near -14 LUFS), and look at the contact sheet.

Is a frame at an exact time exact?

Yes. The seek goes to the keyframe before your time and decodes forward to it, so the frame is the one at (or right after) the time you asked for.

What happens at my spending limit?

Metadata comes first, then frames, the contact sheet, loudness and audio, as far as your maximum charge allows. Anything skipped is listed in warnings, the row is PARTIAL, and nothing past your maximum is ever charged.

Other Actors by Fluid Faith

Load them together as MCP tools: https://mcp.apify.com/?tools=fluidfaith/mobile-qa-gate,fluidfaith/lighthouse-gate,fluidfaith/pdf-to-markdown-tables,fluidfaith/media-probe

Credits

Built on FFmpeg (ffprobe and ffmpeg, run as separate programs). Made by Fluid Faith Solutions.