Multi-clip trim and join editor for macOS.
Add clips, mark keep-segments in each one, put them in order, export one video at one exact frame rate.
Free and open source · MIT license · no third-party dependencies
Ad-hoc signed, not notarized — distributed via GitHub Releases, see below.
Prebuilt macOS binary (Apple Silicon, macOS 14+):
- Grab
Slate-v2.0-macos.zipfrom the release page. - Double-click to unzip — you'll get
Slate.app. - Move
Slate.appinto/Applications(optional but recommended). - First launch: the app is ad-hoc signed (no Apple Developer ID), so Gatekeeper will refuse to open it normally. Right-click
Slate.app→ Open → confirm in the dialog. macOS remembers the choice; subsequent launches work like any normal app.
Prefer to build from source? Read on.
- macOS 14 (Sonoma) or newer — uses
@Observable, modern SwiftUI APIs. - Apple Command Line Tools — ships Swift 5.9+,
sips,iconutil,codesign. Full Xcode is not required. - No third-party dependencies — the project links only against Apple frameworks (SwiftUI, AVFoundation, AVKit, AppKit, CoreMedia, VideoToolbox).
If you don't already have them:
xcode-select --installA dialog will appear; accept and let it finish (a few minutes).
Verify:
swift --version # Apple Swift 5.9 or newer
xcode-select -p # /Library/Developer/CommandLineTools
sips --version # part of macOS, sanity-check it resolves
iconutil --help # dittogit clone https://github.com/novolg/Slate.git
cd SlateThat's it — no npm install, no brew install, no SwiftPM resolve step (no external packages).
scripts/build-app.sh # release build → build/Slate.app
scripts/build-app.sh debug # debug build (faster compile, larger binary)
open build/Slate.appThe script compiles the SPM target, assembles build/Slate.app/, generates build/Slate.icns from assets/icon-source.png if it's newer than the existing .icns, and ad-hoc code-signs the bundle.
swift run # launches the executable directlyFaster iteration but no Dock icon and the window may activate as a background agent on first launch.
- Replace
assets/icon-source.pngwith a 1024×1024 PNG. - Run
scripts/build-app.sh— the script detects the source is newer thanbuild/Slate.icnsand regenerates all macOS icon sizes viasips+iconutil, copies the result into the bundle, and re-signs.
To force-regenerate the icon without rebuilding the app:
scripts/build-icon.sh # output: build/Slate.icns- Add clips: click Add Clips, press
Cmd+O, or drag mp4 / m4v / mov files onto the window. Each clip becomes a card in the clip strip. - Trim: select a card. A new clip is kept whole. Press
IandOto mark the parts you want to keep. You can drag segment edges on the timeline. - Order: drag cards to reorder them. Right-click a card to duplicate, remove, show in Finder or locate a missing file.
- Preview: press
Tabor click Project to play all clips in order. - Pick the frame rate: Constant (default) or Mixed. See below.
- Export: press
Cmd+E. The sheet shows what happens to each clip before Slate writes anything. - Save:
Cmd+Swrites a.slateproject file. Saved projects autosave. An untitled project is offered back after a crash.
| Key | Action |
|---|---|
Space |
play / pause |
J / K / L |
reverse / pause / forward (rate ladder) |
← / → |
step one frame |
I |
mark in-point at playhead |
O |
mark out-point, commit segment |
Delete / Backspace |
remove selected segment |
Esc |
clear in-point / segment selection |
Tab |
toggle Clip / Project player |
[ / ] |
previous / next clip |
Cmd+N |
new project |
Cmd+O |
open clips or a .slate project |
Cmd+S / Shift+Cmd+S |
save / save as |
Cmd+D |
duplicate selected clip |
Cmd+Delete |
remove selected clip |
Cmd+Z / Shift+Cmd+Z |
undo / redo (whole project) |
Cmd+E |
export |
+ / = |
zoom timeline in |
- |
zoom timeline out |
0 |
reset zoom |
| pinch (trackpad) | zoom timeline |
Slate has two frame-rate modes.
Constant (default). Every clip is re-encoded to one frame rate. The fps menu picks it; auto follows the highest frame rate in the project. The output has an exact, constant cadence, so it plays correctly everywhere: upload sites, any player, any editor. Re-encodes use the source codec family (H.264 or HEVC) at the highest bitrate among your clips. Audio is AAC.
Mixed. Clips are copied without re-encoding (AVAssetExportPresetPassthrough). Each clip keeps its own frame rate. This is fast and lossless, but only Apple players (QuickTime, Safari, Final Cut) play the joins between different frame rates correctly. Use Constant for upload.
All timing math uses exact rational numbers on the real frame timestamps, so there is no floating-point drift. After each export, Slate checks every frame time and the audio sync. If the check fails, Slate writes no file and names the clip that caused it. Slate also refuses unsafe projects before it starts, for example an unsupported codec or clips with and without audio in one project.
Engineering details: docs/notes.md and docs/superpowers/specs/2026-09-29-multi-clip-concat-design.md.
swift run SlateChecks --strict # 160 checks, no Xcode needed
scripts/make-test-clips.sh # optional: media fixtures (needs Homebrew ffmpeg)Slate/
├── Package.swift SPM manifest: SlateCore library, Slate app, SlateChecks
├── Sources/SlateCore/ multi-clip logic, no UI: planner, timing math,
│ re-encoder, validator, .slate file, autosave, undo
├── Sources/SlateChecks/ test harness (replaces XCTest)
├── Sources/Slate/
│ ├── SlateApp.swift @main entry, menus
│ ├── ViewModels/ ProjectViewModel (@Observable)
│ ├── Views/ EditorView, TimelineView, ClipStripView, ProjectExportSheet, …
│ └── Services/ KeyframeScanner, ThumbnailGenerator
├── scripts/
│ ├── Info.plist bundle metadata, document types
│ ├── build-app.sh SPM build + .app wrapper + ad-hoc sign
│ ├── build-icon.sh source PNG → .icns pipeline
│ └── make-test-clips.sh dev-only test fixtures
├── assets/
│ └── icon-source.png 1024×1024 source for the app icon
└── docs/notes.md engineering notes (keyframe model, AVFoundation gotchas)
v2.0. Multi-clip projects, Constant / Mixed export, .slate project files, autosave. Release notes: docs/release-notes-v2.0.md.
MIT. Free and open source — use, modify, and redistribute freely, keep the copyright notice.
