shrinkit compresses macOS screen recordings and speeds them up. Drop a .mov into a folder, or
right-click it in Finder, and a much smaller .mp4 comes back. A QuickTime capture that started at
a few hundred megabytes usually ends up in single digits.
A raw screen capture is almost always too big to attach to a pull request, a Jira ticket or a Slack message, and too slow to sit through. Playing it back at 2x and re-encoding it at a fixed quality deals with both at once.
The encoding is ffmpeg. A launchd agent watches the folder for you, so the whole thing runs without an app to open. Every part of it is configurable, and it can also cut a stretch out of the middle, to shorten a recording or redact something in it.
2026-07-30.13.34.12-2x.mp4
git clone https://github.com/noxend/shrinkit.git
cd shrinkit
./install.shThe installer copies the script to ~/.local/bin/shrinkit, creates the working folders under
~/Movies/shrinkit, registers a launchd agent that watches input/, and puts a shrinkit
shortcut on your Desktop. Run it again any time to update; it never overwrites your settings.
For a different working folder:
SHRINKIT_DIR="$HOME/Movies/clips" ./install.sh~/Desktop, ~/Documents and ~/Downloads are guarded by macOS privacy protection, and a
background job is refused there until you grant it Full Disk Access by hand. If you install into
one of them the script prints the steps. Anywhere else, ~/Movies included, needs nothing.
- Open the
shrinkitshortcut on your Desktop and drop a recording intoinput/. QuickTime.mov,.mp4and.m4vall work. - Give it a few seconds.
- Collect the result from
output/, converted to.mp4and namedclip.mp4.
The original goes to a hidden .processed/ folder, so the working folder holds only
settings.conf, presets/, input/ and output/.
Most of the right-click menu is the list of your presets. Every file in presets/ gets an entry
named after it, so out of the box you get shrinkit: 2x, the everyday one, shrinkit: sharp,
sharper than the default for something like a PR, and shrinkit: tiny, as small as it gets. The
result is named after the preset that ran, clip-2x.mp4, clip-sharp.mp4 or clip-tiny.mp4, and
lands beside the original, which stays where it is. You can select several files to do them
together.
Add a preset and it becomes a new entry; the installer rebuilds the menu from presets/ every
time it runs. One entry isn't a preset: shrinkit: mark cuts, for marking a stretch to remove
before shrinking (see below).
Every setting doubles as a flag, so one file can be handled differently without editing anything:
shrinkit --speed 4 --crf 32 recording.mov
shrinkit --no-remove-audio recording.movA true/false setting takes no value: --remove-audio turns it on and --no-remove-audio turns it
off. Name no files and the flags apply to whatever is sitting in input/. Flags beat the config
file.
One flag is not a setting: --cut takes a range to remove from the recording, and needs the file
named. See below.
From the command line, name the ranges with --cut, once each:
shrinkit --cut 0:32-0:35 --cut 2:30-end recording.movThat is the whole feature for a one-off. The rest of this section is the other way in, a file you edit next to the recording, which is what the right-click menu uses and what survives being closed and come back to.
Right-click a recording and choose shrinkit: mark cuts. It opens the recording, so you can find
the moment, and a <recording>.cuts text file next to it (creating one the first time) where you
mark what to remove, one range per line:
# clip.mov.cuts
0-0:20
0:32-0:35
1:10-1:12.5
2:30-end
Save it, then process the recording as usual: drop it into input/ or right-click it and pick a
preset. Each range is removed entirely, not just skipped past on playback, since the frames are
never written to the output at all. Good for cutting a secret out of a recording, a password typed
into a form, a private chat glanced at mid-recording, and works just as well for plain shortening.
end reaches the real length of the clip without you having to know it, so trimming the end is the
same .cuts line as everything else, not a separate mechanism: 2:30-end cuts from 2:30 on. 0 is
already the start, so trimming the beginning needs nothing special: 0-0:20 cuts the first 20
seconds.
Times are M:SS, M:SS.f, or plain seconds, in the file and in --cut alike. # starts a
comment, a range under a tenth of a second is too short to reliably land on a real frame, a range
starting at or past the clip's real length cuts nothing and is skipped rather than silently doing
nothing while claiming success, and a line that does not parse is skipped rather than stopping the
run. All of these are logged, so check the log if a cut you expected does not show up in the
result. If you edit the file in TextEdit rather than through the menu entry, save it as plain text
(Format > Make Plain Text) with Smart Dashes off (Edit > Substitutions), or it will not parse as
written.
--cut replaces the sidecar for that run rather than adding to it, the same way every other flag
beats the config file, and says so in the log when there was one to ignore. Unlike the other flags
it needs the recording named on the same command line: a timestamp only means something in one
particular file, so applying one to whatever happens to be sitting in input/ is never what you
meant. Name several files and the same ranges apply to all of them, sidecars included, so that is
worth a second look before you do it.
Cutting needs a steady frame rate to land exactly where it is told to, so a recording gets
resampled to fps (30 if fps = 0) before anything is removed, even when fps = 0 would
otherwise mean "keep the original" for the rest of the recording.
Dropping a recording into input/ files the .cuts sidecar away with the original once
processing is done. Right-clicking a file directly leaves both in place, the same way it leaves
the recording itself in place. Once you have the result, check it and clean up the source
yourself.
A preset is a file of the same settings in presets/, read on top of settings.conf. Whatever it
leaves out stays as the config has it, so a preset only spells out what it changes. The finished
file is named after the preset that made it, which is how you can tell two copies apart.
shrinkit --preset tiny recording.movCopy a preset file to make your own, then give it a menu entry without reinstalling:
shrinkit preset install tiny # adds "shrinkit: tiny" to the right-click menu
shrinkit preset remove tiny # takes the entry out, keeps the fileFlags beat a preset, and a preset beats the config file.
From the command line:
shrinkit config # what is in effect right now
shrinkit config crf 32 # change one
shrinkit config edit # open it in $EDITOROr edit ~/Movies/shrinkit/settings.conf yourself. It is one key = value per line, and a line
starting with # is a comment. Changes take effect on the next recording. A value you get wrong
goes back to its default and the log says so, and a line that makes no sense is skipped, so a typo
here will never leave a recording unprocessed.
| Setting | What it does | Default |
|---|---|---|
speed |
Speed multiplier. 2 is twice as fast, 1 leaves it alone |
2 |
fps |
Cap the frame rate, up to 240; 0 keeps the original |
30 |
crf |
Quality against size, the main knob. Lower is sharper and bigger, higher is smaller (18 high, 23 good, 28 small, 32 tiny) | 28 |
codec |
h264 plays everywhere, hevc is about 30% smaller and less compatible |
h264 |
remove_audio |
true drops the sound, false keeps it and speeds it up to match |
true |
max_height |
Downscale tall videos to this height; 0 keeps the original |
0 |
keep_original |
true files the original in .processed/, false deletes it |
true |
keep_days |
Delete originals from .processed/ once this many days old, up to 3650; 0 keeps them forever |
0 |
notify |
Post a macOS banner when a file is done | true |
notify_sound |
Glass, Ping, Pop, Hero and the rest, or none |
Glass |
notify_start |
Also post a quiet banner when a file starts | true |
copy_to_clipboard |
Put the finished file on the clipboard, ready to paste | false |
Logs go to a hidden .logs/ folder. The watched folder is fixed when you install, because launchd
wants an absolute path; to move it, run the installer again with SHRINKIT_DIR. To have results
land somewhere else, a synced folder for instance, replace output/ with a symlink to it.
System Settings > Login Items will list shrinkit from an unidentified developer. That is your own
script rather than a signed application, so there is nothing to sign.
./update.sh # pull and reinstall; settings and recordings are untouched
./uninstall.sh # remove the agent, the script and the menu entriesUninstalling leaves your recordings and settings where they are.
MIT