Snapframe is a native macOS tool for frame-accurate video scrubbing, cue-based navigation, and free-form crop export.
Open a video, jump between marked moments, frame a crop or cut with scissors, and save stills next to the source — without a heavyweight NLE.
| Platform | macOS |
| Version | 1.4.0 |
| License | MIT |
| Playback | AVFoundation |
- Open
Snapframe_1.4.0.dmg. - Drag Snapframe.app into Applications.
- Double-click Quarantine.command in the DMG.
If macOS blocks it: right-click → Open → Open. - Launch Snapframe from Applications.
Downloaded builds are quarantined by Gatekeeper. Quarantine.command clears that flag. Manually:
xattr -dr com.apple.quarantine /Applications/Snapframe.app
open /Applications/Snapframe.appOr right-click the app → Open.
- Live video stage with frame-accurate scrubbing and still capture
- Cue list: mark moments in-app (N), double-click to edit, or import a sidecar JSON
- Snap to cues (S) with separate time / frame tolerances in Preferences
- Frame crop overlay (width × height), optional aspect lock / square
- Scissors crop: drag to save on release (hold Shift for square); hover shows center-offset coordinates
- Crop bar: size, center offset, locks, ratio readout
- Export crops as PNG or JPEG into a
{name}_crops/folder - Timeline with pan, zoom, follow playhead, markers, and a fixed time/frame grid
- Transport: playback, frame skip, time skip (−5s…+5s), speed, go to start
- Recents with thumbnails
- Light / Dark / System appearance
- Check for Updates… via the latest GitHub release
- Keyboard-first workflow (physical keys, any input layout)
- Open a video (⌘O), drop a file onto the window, or pick a recent item.
- Mark cues at the playhead (N), or load a list: auto-import
Movie.cues.jsonbeside the file, or Import Cues… (⌘I). Double-click a cue (or right-click → Edit) to change time and label. Time / Frame on the timeline also switches the inspector lists. Snap to cues (S) pulls the playhead onto a nearby cue; snap range is in Preferences (separate time / frame values). - Scrub the timeline; step frames with ← / → (⇧ for ±10). Click the scrollbar track to jump the viewport. Return jumps to the start.
- Frame crop (C) shows the overlay and crop bar. Place and size the crop, then Save crop (⌘S).
Scroll adjusts height; ⇧scroll adjusts width. Aspect lock (L) keeps the current ratio; Square (R) forces 1:1.
Scissors crop (X) is an alternative: the viewer stays clean until you drag. Press, drag to the opposite corner, release — the crop saves immediately. Hold Shift while dragging for a square. Hover shows center-offset frame coordinates (
+x, +y). Esc exits scissors. Frame crop and scissors are mutually exclusive. - Find exports in
Movie_crops/next to the source, withmetadata.json.
.mp4 · .m4v · .mov
Adding a cue (N) creates this sidecar next to the video. Snapframe also auto-imports it on open, or you can Import Cues….
For Movie.mp4:
Movie.cues.json
| Field | Notes |
|---|---|
format |
snapframe-cues |
source |
Must match the video filename |
t / timecode |
Seconds and/or HH:MM:SS.mmm (compact digits and flexible separators also work in the app) |
done |
Mark finished cues |
Example: Examples/Sample.cues.json
Movie_crops/
crop_001.png
crop_002.jpg
metadata.json
Each crop stores x / y / width / height (legacy square size still loads).
UI offsets use the frame center as origin (+0, +0); export metadata keeps top-left x / y.
Example: Examples/Sample_crops/metadata.json
Shortcuts use physical key positions (US QWERTY), so they work the same on any input layout.
| Key | Action |
|---|---|
| Space | Play / pause |
| ← / → | Frame −1 / +1 |
| ⇧← / ⇧→ | Frame −10 / +10 |
| ⌥← / ⌥→ | Seek −1s / +1s |
| ⇧⌥← / ⇧⌥→ | Seek −5s / +5s |
| 1 / 2 / 3 | Speed 0.5× / 1× / 2× |
| M | Mute |
| N | Add cue at playhead |
| [ / ] | Previous / next cue |
| ⌫ | Delete active cue |
| ⇧⌫ | Delete active crop |
| C | Frame crop |
| X | Scissors crop |
| L | Aspect lock |
| R | Square proportions |
| P | Follow playhead |
| S | Snap to cues |
| G | Go to timecode |
| Return | Go to start |
| Esc | Exit scissors / close video |
| ⌘O | Open video |
| ⌘I | Import cues |
| ⌘S | Save crop |
| ⌘R | Refresh preview |
| ⌘\ | Toggle inspector |
| ⌘, | Preferences |
| Snapframe → Check for Updates… | Compare with latest GitHub release |
Requires Xcode.
open snapframe.xcodeprojSelect the Snapframe scheme and run (Debug or Release).
Unit tests live in the snapframeTests scheme (⌘U in Xcode), or:
xcodebuild test -scheme snapframeTests -destination 'platform=macOS'snapframe/
Domain/ entities + ports (CropRepository, CueRepository, ImageEncoding)
Application/ use cases (e.g. SaveCropUseCase)
Infrastructure/ AVFoundation player, stores, file access, image encode, GitHub update check
Presentation/ SwiftUI + AppKit UI, AppState composition root
snapframeTests/ XCTest coverage for domain, persistence, and update version compare
AppState is the composition root: it owns Infrastructure types and drives the one Application use case (SaveCropUseCase). Domain stays Foundation / CoreGraphics only.
Snapframe is released under the MIT License.
See CHANGELOG.md.