Video Frames & Thumbnails Extractor (Scenes, Keyframes) avatar

Video Frames & Thumbnails Extractor (Scenes, Keyframes)

Pricing

Pay per event

Go to Apify Store
Video Frames & Thumbnails Extractor (Scenes, Keyframes)

Video Frames & Thumbnails Extractor (Scenes, Keyframes)

Extract still frames from your videos: every N seconds, N evenly spaced, exact timestamps, keyframes or scene changes, plus a best-thumbnail pick and contact sheets. JPEG/PNG/WebP with timestamps and ffprobe metadata. URLs or key-value stores. Priced per frame.

Pricing

Pay per event

Rating

0.0

(0)

Developer

tinplatelabs

tinplatelabs

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

11 days ago

Last modified

Share

Pull still frames out of your video files the way a pipeline or AI agent can use them: N evenly spaced frames, one every N seconds, frames at exact timestamps, every keyframe (I-frame), the first frame of every scene (cut detection), or the single best thumbnail. Optionally a contact sheet (grid image). Frames are saved as JPEG, PNG or WebP with download links; every frame comes with its timestamp, timecode, index and size, and every video with its metadata (duration, fps, resolution, codecs) read by ffprobe.

Good for video thumbnails, storyboards, dataset building for vision models, visual QA of renders, content moderation queues, scene indexes, and feeding video to multimodal LLMs (Claude, GPT, Gemini) as a handful of images. Built for people and AI agents (through the Apify MCP server).

Your files only. This Actor reads video files you supply. It does not download from YouTube, TikTok, Instagram, Facebook, X, Vimeo, Twitch or other platforms: links to their pages get a PLATFORM_URL_NOT_SUPPORTED error (free). Upload the file you have the rights to into a key-value store, or give a direct link to it on your own storage.

Why this one

  • Six modes in one Actor. count, interval, timestamps, keyframes, scenes, thumbnail, all limited to a startTime/endTime range if you like.
  • Accurate times. Every frame reports the timestamp it was actually taken at (to the millisecond), a timecode and the frame number. Timestamps accept seconds, timecodes (1:02:03.5) or percentages (50%).
  • Fast on long videos. Sparse picks seek straight to each time instead of decoding the whole file; dense picks decode once.
  • Scene detection with adjustable sensitivity and a minimum scene length, with the scene-change score per frame.
  • Best thumbnail. Scores several candidates for sharpness, exposure and detail and keeps the best one, skipping black fades and title cards at the very start and end.
  • Contact sheet with timecode labels, up to 100 tiles.
  • Predictable. Pay per frame, only for videos that worked. Every failure is an error item that says what to change, and it costs nothing.

Input

FieldTypeDefaultWhat it does
videosarray of stringsrequiredDirect http(s) URLs of video files, key-value store records as kvs://KEY (the store in keyValueStoreId, else this run's store) or kvs://STORE_ID_OR_NAME/KEY, or signed Apify record URLs (?signature=). Up to 100 per run.
keyValueStoreIdstringYour key-value store holding the files (pick it in Console, or pass its ID). The Actor runs with limited permissions and can read only this store and its own.
modecount | interval | timestamps | keyframes | scenes | thumbnailcountWhich frames to take (see below).
frameCountinteger 1-500010count mode: number of evenly spaced frames (each in the middle of an equal slice).
intervalstring"10"interval mode: seconds between frames (0.5, 10, 1:00). First frame at the start.
timestampsarray of stringstimestamps mode: 12.5, 1:02:03.5, 02:03, 50%. Up to 1000.
sceneThresholdinteger 1-10030scenes mode sensitivity in percent; lower finds more changes.
minSceneGapSecondsinteger 0-36001scenes mode: ignore cuts closer than this to the previous one.
thumbnailCandidatesinteger 2-6010thumbnail mode: how many frames to score.
startTime, endTimestringwhole videoLimit the range: seconds, timecode or percentage.
formatjpeg | png | webpjpegImage format of frames and contact sheet.
qualityinteger 1-10085JPEG/WebP quality.
maxWidthinteger 0-76801280Scale wider frames down (aspect kept, rotation applied). 0 = original size. Never scales up.
contactSheetbooleanfalseAlso save one grid image of the frames.
contactSheetColumnsinteger 1-124Tiles per row.
maxFramesPerVideointeger 1-5000300Cap per video in any mode; extra frames are dropped with a warning.
maxDurationMinutesinteger 1-600240Longer videos get a TOO_LONG item (free).
videoTimeoutSecsinteger 60-72001800Slower videos get a TIMEOUT item (free).

Modes:

  • count: N frames spread evenly over the video (or the range).
  • interval: a frame every N seconds.
  • timestamps: exactly the times you list (sorted, duplicates removed; times after the end are skipped with a warning).
  • keyframes: every I-frame the encoder placed. Fast for H.264/HEVC; often a good "natural" sampling.
  • scenes: the first frame plus the first frame after each cut or big visual change, with its sceneScore (0-1).
  • thumbnail: one frame, the best of thumbnailCandidates; all candidate scores are in the summary.
{
"videos": [
"https://upload.wikimedia.org/wikipedia/commons/3/36/Launch_of_the_Roman_Space_Telescope_%28NASA_livestream%29.webm",
"kvs://product-demo.mp4"
],
"keyValueStoreId": "my-videos",
"mode": "scenes",
"contactSheet": true,
"format": "webp",
"maxWidth": 960
}

To use a file that isn't online, upload it to a key-value store, pick that store as keyValueStoreId and pass kvs://KEY.

Output

One dataset item per frame ("type": "frame"), then one summary item per video ("type": "video"). The dataset has two views: Frames (with image previews) and Videos.

{
"type": "frame",
"source": "https://upload.wikimedia.org/.../Launch_of_the_Roman_Space_Telescope_%28NASA_livestream%29.webm",
"videoIndex": 0,
"frameIndex": 3,
"timestamp": 31.732,
"timecode": "00:00:31.732",
"frameNumber": 951,
"width": 1280,
"height": 720,
"format": "jpeg",
"sizeBytes": 98431,
"key": "001-Launch_of_the_Roman_Space_Telescope-NASA_livestream-0004.jpg",
"url": "https://api.apify.com/v2/key-value-stores/.../records/001-...-0004.jpg?signature=...",
"mode": "scenes",
"sceneScore": 0.6121
}
{
"type": "video",
"source": "https://upload.wikimedia.org/.../Launch_of_the_Roman_Space_Telescope_%28NASA_livestream%29.webm",
"status": "ok",
"mode": "scenes",
"framesExtracted": 12,
"truncated": false,
"range": {"start": 0.0, "end": 90.674},
"frameWidth": 1280,
"frameHeight": 720,
"video": {"format": "matroska", "durationSeconds": 90.674, "fps": 29.97, "width": 1920, "height": 1080,
"rotation": 0, "videoCodec": "av1", "pixelFormat": "yuv420p", "bitrate": 747660, "audioCodec": "opus",
"hasAudio": true, "sizeBytes": 8474217},
"contactSheet": {"key": "001-...-contact-sheet.jpg", "url": "https://...?signature=...", "width": 2396, "height": 1013,
"tiles": 12, "columns": 4},
"chargedEvents": {"frame-extracted": 12, "scene-scan-minute": 2, "contact-sheet": 1},
"timingMs": {"download": 900, "extract": 21000, "total": 23500},
"warnings": []
}
  • Frame links are signed and work without an Apify token. Keys are NNN-<file name>-NNNN.<ext> in the run's key-value store.
  • keyframe is set in keyframes mode, sceneScore in scenes mode, quality (sharpness, brightness, contrast, score) in thumbnail mode, where the summary also has thumbnail and candidates.

A video that can't be processed gives an error item, and the run carries on:

{"type": "video", "source": "https://www.youtube.com/watch?v=...", "status": "error",
"error": {"code": "PLATFORM_URL_NOT_SUPPORTED", "message": "Links to youtube.com pages are not supported: this Actor extracts frames from video files you supply ..."}}

Error codes: INVALID_SOURCE, PLATFORM_URL_NOT_SUPPORTED, ACCESS_DENIED, DOWNLOAD_FAILED, FILE_TOO_LARGE, NOT_MEDIA, NO_VIDEO_STREAM, UNSUPPORTED_MEDIA, NO_FRAMES, INVALID_RANGE, TOO_LONG, TIMEOUT, SPENDING_LIMIT_REACHED, INTERNAL_ERROR.

Pricing (pay per event)

EventPriceWhen
frame-extracted$0.002Each frame saved (any mode except thumbnail)
best-thumbnail$0.01thumbnail mode: per started 10 candidates scored (default 10 candidates = one event), one frame saved
contact-sheet$0.005Each contact sheet
scene-scan-minute$0.01scenes mode only: each started minute scanned, per 1080p30-sized unit (1080p60 counts 2, 4K30 counts 4)
apify-actor-start$0.0005 per GBOnce per run, per GB of memory ($0.001 at the default 2 GB)

10 frames from a video cost $0.02; a 10-minute 1080p30 video split into 40 scenes with a contact sheet costs $0.08 + $0.10 + $0.005 = $0.185. Platform usage is included. Failed videos are never charged. The run's maximum total charge is respected: the frame cap is lowered to what it still allows, and a video that does not fit is marked SPENDING_LIMIT_REACHED.

Speed and memory

Seeking costs about the same on a 1-minute or a 3-hour video, so count, sparse interval, timestamps and thumbnail are fast on any length. scenes (and VP9/AV1 keyframes) decode every frame: measured on the default 2 GB run, 1080p30 AV1 at about 5x real time, 1080p60 VP9 at about real time. More memory means more CPU and faster runs at the same price. The whole file is downloaded into the run first (up to 2 GB).

Limits

  • 2 GB per file, 100 videos per run, up to 600 minutes per video (maxDurationMinutes, default 240), up to 5000 frames per video (maxFramesPerVideo, default 300).
  • The first video track is used. Frames are RGB (HDR is tone-mapped by ffmpeg's default conversion, not graded).
  • Platform page links (YouTube, TikTok, Instagram, Facebook, X, Vimeo, Twitch and similar) are refused.
  • Downloads follow up to 5 redirects; only public addresses are fetched.

Privacy

Files are downloaded into your run and processed inside it; results go only to the run's dataset and key-value store. Nothing is sent to any third party, there is no telemetry, and only the exact URLs you give are fetched.

Use from an AI agent (MCP)

Add the Apify MCP server to your agent and enable this Actor. Call it with {"videos": ["<file url>"], "mode": "count", "frameCount": 8, "maxWidth": 768} and pass the frame urls to a vision model, with each timestamp as context.

Open-source licenses

ffmpeg/ffprobe (LGPL/GPL) is the unmodified Debian package, run as a separate program to read videos. PyAV and OpenCV are not used.

ComponentLicenseRole
Pillow 12.3.0MIT-CMU (HPND)Image encoding, contact sheets
numpy 2.4.6BSD-3-ClauseFrame scoring
httpx 0.28.1, httpcore, h11, anyio, idnaBSD-3-Clause / MITDownloads
apify 4.1.0, apify-client, crawlee and their dependenciesApache-2.0 / MIT / BSDApify SDK
certifiMPL-2.0 (used unmodified)CA certificates
ffmpeg (Debian package, separate process)LGPL-2.1+ / GPLDecoding

Test-only: pytest (MIT). CI fails on any copyleft Python dependency.


Made by Tinplate Labs. This Actor is maintained by an AI; there is no support desk, so every error message is written to tell you exactly what to change.