Skip to main content

finder-adjust-thumbnails

Set the Finder thumbnail of your videos to the frame at an offset you choose, instead of whatever QuickLook picked.

How it works, and what that means

macOS gives you no way to tell QuickLook which frame to use as a video's poster frame. What it does give you is a custom file icon — an image stored in the file's resource fork and flagged in com.apple.FinderInfo — which Finder shows in place of the generated thumbnail.

So this tool grabs the frame you asked for and installs it as the file's icon. Three consequences worth knowing up front:

  • It is reversible. --clear removes the custom icon and Finder goes back to its own thumbnail.
  • It does not travel. The icon lives in the resource fork, so it survives copies and moves within macOS but is lost through zip archives and most cloud sync.
  • Icons are square, frames are not. macOS stretches whatever it is given to fill a square, which would squash a 16:9 frame. The frame is therefore centred at its own proportions with the surrounding space left fully transparent — so what you see in Finder is the frame at its true shape, with no letterbox bars.

The video file's own content is never modified.

Install

Requires macOS and Python 3.12+:

uv tool install .

ffmpeg is optional — see below.

Use

# every video in a directory, one quarter of the way in
finder-adjust-thumbnails ~/Movies --offset 25%

# a fixed timestamp, recursively
finder-adjust-thumbnails ~/Movies --recursive --offset 1:30

# a single file
finder-adjust-thumbnails ~/Movies/holiday.mp4 --offset 10

# see what would happen, change nothing
finder-adjust-thumbnails ~/Movies --offset 25% --dry-run

# put the default thumbnails back
finder-adjust-thumbnails ~/Movies --clear

Offsets

Form Example Meaning
seconds 10, 90s, 2.5 that many seconds in
clock time 1:30, 1:00:30 mm:ss or hh:mm:ss
percentage 25% that far through the video

An offset past the end of a video is clamped to just inside it, so one command works across clips of very different lengths.

Options

Option Default
--offset, -o where to take the frame from
--clear remove custom icons instead
--recursive, -r off descend into subdirectories
--ext avi,m4v,mkv,mov,mp4,webm,wmv extensions to consider in a directory
--icon-size 512 pixel size of the square icon
--dry-run off report without changing anything
--jobs, -j up to 8 videos to decode in parallel

A file named explicitly is always processed, whatever its extension.

Exit status is 0 on success, 1 if any file failed, 2 for bad arguments.

Which decoder runs

macOS decodes video itself through AVFoundation, so that is tried first: no external binary, no subprocess, and a video's preferred track transform is honoured — footage shot in portrait comes out upright rather than on its side.

ffmpeg is the last resort, used only for the formats QuickTime never learned: Matroska, WebM and WMV. If you have none of those, you never need it. When the fallback is used the report says so:

     updated  holiday.mp4 (frame at 1.50s)
     updated  archive.mkv (frame at 1.50s, via ffmpeg)

If a file needs ffmpeg and it is not installed, only that file fails — everything macOS can read is still done — and the message tells you to brew install ffmpeg.

Disk space

Each icon is stored in its file's resource fork, so it does cost real bytes. Measured on a detailed 1080p frame:

--icon-size per file
256 ~20 KB
512 (default) ~44 KB
1024 ~100 KB

Finder's icon slider tops out at 512pt, so the default covers every view without storing pixels nobody sees. Drop to --icon-size 256 for a large library, raise it if you live in huge-icon view. (For reference, an unbounded full-resolution frame costs about 180 KB a file.)

If Finder keeps showing the old thumbnail

Finder caches aggressively. The tool touches the containing directory to prod it; if a stale thumbnail persists, killall Finder.

Development

uv sync
uv run pre-commit install   # ruff check, ruff format and hygiene hooks on every commit
uv run pytest

Linting and formatting are both ruff, run through pre-commit; CI runs the same hooks, so pre-commit run --all-files is the whole check locally.

Tests run against real videos generated by ffmpeg and assert on the real com.apple.FinderInfo flag, the real stored icon pixels, and real resource fork sizes — nothing that matters here is mocked. Proportions are checked by putting a known square in the frame and measuring whether it is still square in the icon.

Two things to know before changing this code:

  • AppKit's setIcon:forFile: takes an internal IconServices lock and deadlocks when called from several threads at once. Frame extraction is parallel; icon writing is deliberately serial, and test_icon_writes_never_happen_on_a_worker_thread holds that line.
  • PyObjC has no type metadata for the CGImageRef AVFoundation returns, so it arrives as an untyped pointer and is passed straight into NSBitmapImageRep. It works, but it is the fragile seam; tests/test_backends.py pins it.

Release files for finder-adjust-thumbnails 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for finder-adjust-thumbnails 0.1.0
File Size Uploaded
finder_adjust_thumbnails-0.1.0.tar.gz 37.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for finder-adjust-thumbnails 0.1.0
File Interpreter ABI Platform
finder_adjust_thumbnails-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 54.5 kB

Release files / finder_adjust_thumbnails-0.1.0.tar.gz

Download URL finder_adjust_thumbnails-0.1.0.tar.gz
Size 37.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c26926f93066b46fe5c8bbf5a0125b89f7ce05b5321f7a9ec4a8b242ecdc39ec
BLAKE2b-256 checksum
How to use checksums
ce929b8caeae40443f5a326f110b44bb12a04f04e5f33a9227a8f40b06c633d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / finder_adjust_thumbnails-0.1.0-py3-none-any.whl

Download URL finder_adjust_thumbnails-0.1.0-py3-none-any.whl
Size 17.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fe6034368c6374ce71f3ac92ce2e477e831341366e97fc66c878f48829e9a1a0
BLAKE2b-256 checksum
How to use checksums
d6914de99d3ffcd462df2aecd1203b0acbc0e6b8db291a520de33b03fee92f0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page