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

# a shell glob, or any mix of files and directories
finder-adjust-thumbnails *.wmv --offset 10
finder-adjust-thumbnails ~/Movies ~/Desktop/clip.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

Any mix of files and directories can be given at once, so shell globs work as you would expect. A file named explicitly is always processed, whatever its extension, and a video reached twice — by a glob overlapping a directory, say — is only done once.

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.1

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.1
File Size Uploaded
finder_adjust_thumbnails-0.1.1.tar.gz 37.8 kB Details

Built distribution (wheel)

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

Total release size: 55.5 kB

Release files / finder_adjust_thumbnails-0.1.1.tar.gz

Download URL finder_adjust_thumbnails-0.1.1.tar.gz
Size 37.8 kB
Tags Source
SHA-256 checksum
How to use checksums
c4d4d37757a60c12508cd2bdb39fb4f98e24619316923afca3b270383878c3d4
BLAKE2b-256 checksum
How to use checksums
3a5f29f1c59b754d64191b8b36c79b294b6a5bea68a6cfa2ab6021e47fc14043
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.1-py3-none-any.whl

Download URL finder_adjust_thumbnails-0.1.1-py3-none-any.whl
Size 17.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0c04eaa4af1ca83cd052d025b0410715126a3cf6ddc1477a3379035c9a17e806
BLAKE2b-256 checksum
How to use checksums
71f36d13eb9b6c85cb3343f42652f41ab97d009b5e1aee614101e75a7b55f0c4
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

This release

0.1.1 This release

2 release files

0.1.0

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