A native macOS screen recorder built with Rust, ScreenCaptureKit, and AVFoundation.
It captures screen + optional microphone audio, writes MP4 (H.264 + AAC), supports preview-before-save, and provides local/global shortcuts.
This repository is in active development.
- ✅ Implemented through Phase 9 (shortcuts) in
specs/0004-tasks.md - ✅ Audio write path enabled in encoder (
src/encode/pipeline.rs) - ✅ Recording, preview/discard, save flow, and settings persistence are available
⚠️ Phase 10 (background stability hardening) and parts of Phase 11 (polish/docs) are still pending
Screenshots are not committed yet. You can add them under assets/ and reference them here.
Example placeholders:


- Screen capture via ScreenCaptureKit
- Optional microphone capture (fallback to video-only if mic is unavailable)
- MP4 output via AVAssetWriter
- Video: H.264
- Audio: AAC (when mic capture is enabled and available)
- Region selection
- Full screen (display picker)
- Single window (window picker)
- Area (beta UI + settings path)
- Preview workflow
- Open in QuickTime
- Accept (save) / Discard (delete temp file)
- Save workflow
- Select output folder
- Timestamped filename generation
- Reveal in Finder
- Completion toast
- Persistent settings
- Resolution (
Native,1080p,720p) - Frame rate (
24,30,60) - Quality (
Low,Medium,High) - Capture region
- Microphone toggle
- Output directory
- Resolution (
- Keyboard shortcuts
- Global:
⌘⇧Rstart,⌘⇧Sstop - In-app preview:
⌘↩accept,⌘⌫discard
- Global:
The app is command-driven with clear module boundaries:
- UI (
src/ui/*)- egui panels:
main_window,settings_panel,preview_panel,save_panel - Emits
RecorderCommand
- egui panels:
- Orchestration (
src/app.rs)- Owns
AppState - Runs async
command_loopon Tokio - Coordinates
CaptureEngine+EncodingPipelineviaRecordingOrchestrator
- Owns
- Capture (
src/capture/*)- Permission checks (
permissions.rs) - Region/content filter (
content_filter.rs) - Screen/audio stream lifecycle (
engine.rs,audio.rs)
- Permission checks (
- Encoding (
src/encode/*)- AVAssetWriter pipeline (
pipeline.rs) - Temporary output lifecycle (
temp_file.rs) - PTS utilities (
sync.rs)
- AVAssetWriter pipeline (
- Output + Config
- Finalize/move/reveal output (
src/output/save.rs) - Load/save settings (
src/config/settings.rs)
- Finalize/move/reveal output (
- User triggers
Start(button or shortcut) command_loopvalidates state and permissionsCaptureEnginestarts ScreenCaptureKit stream and publishes sample buffersEncodingPipelinedrains video/audio channels and writes MP4- User triggers
Stop - Encoder finalizes temp file and app enters
Previewing - User accepts (save) or discards (delete temp file)
- Language: Rust (edition 2024)
- Runtime: Tokio
- UI: eframe / egui
- Capture:
screencapturekit - Encoding:
objc2-av-foundation(AVAssetWriter) - ObjC bridge:
objc2,objc2-foundation,objc2-core-media,objc2-core-video,objc2-app-kit - Serialization:
serde,serde_json - Logging:
tracing,tracing-subscriber - Testing: Rust unit/integration tests (with
integrationfeature gate)
- macOS 12.3+
- Rust stable toolchain (pinned by
rust-toolchain.toml) - Screen Recording permission
- Microphone permission (optional; required for audio track)
# Build (dev) + ad-hoc sign
make build
# Run
make run
# Run with debug logs
make run-debugRelease build:
make build-releaseOr directly:
cargo build --release- Launch app:
make run - Grant Screen Recording (and optionally Microphone) permission
- Configure settings in the bottom settings panel
- Press
Startor⌘⇧R - Press
Stopor⌘⇧S - In Preview:
Accept/⌘↩to saveDiscard/⌘⌫to delete
Settings file:
~/Library/Application Support/screen-recorder/settings.json
Default output directory:
- Desktop
- Fallback: home directory
- Fallback:
/tmp
| Action | Shortcut | Scope |
|---|---|---|
| Start recording | ⌘⇧R |
Global + app-local |
| Stop recording | ⌘⇧S |
Global + app-local |
| Accept preview | ⌘↩ |
App-local |
| Discard preview | ⌘⌫ |
App-local |
Quality gates:
make fmt-check
make lint
make testIntegration-gated tests:
cargo test --features integrationSecurity/dependency checks:
make audit
cargo deny check- Run
make reset-tcc - Relaunch app
- Re-grant permissions in System Settings
- Ensure microphone permission is granted
- Ensure mic capture is enabled in settings
- Check logs with
RUST_LOG=screen_recorder=debug make run
- Confirm output directory exists and is writable
- Try changing folder in Save panel
- Retry save from the error prompt
Q: Does this support macOS below 12.3?
A: No, ScreenCaptureKit requires macOS 12.3+.
Q: Does it support HEVC/ProRes export?
A: Not yet; current implementation targets MP4/H.264 (+ AAC audio).
Q: Is area capture fully implemented?
A: Area mode exists in settings/UI; full sub-region behavior remains part of ongoing implementation work.
Near-term items from tasks plan:
- Background recording stability hardening (Phase 10)
- Error routing and observability polish (Phase 11)
- Final regression and release validation
See specs/0004-tasks.md for details.
Contributions are welcome.
- Create a branch from
main - Keep changes focused and well-tested
- Run quality gates locally:
make fmt-checkmake lintmake test
- Open a PR with a clear summary and verification notes
src/
app.rs
main.rs
lib.rs
error.rs
capture/
encode/
output/
config/
ui/
tests/
specs/
assets/
No license file has been added yet.