SqueezeBar - macOS Menu Bar File Compression
Overview
SqueezeBar is a macOS menu bar app that compresses files locally on your Mac. Born from the frustration of using slow online compression websites multiple times a day for administrative documents and Pull Request videos, this app makes file compression as simple as dragging and dropping.
No uploading to random websites, no waiting for processing, no privacy concerns. Just drop your file, pick your compression settings, and you’re done. It lives in your menu bar, ready whenever you need it.
Built entirely in Swift and SwiftUI, it handles images (JPEG, PNG, HEIC), videos (MP4, MOV) with native macOS frameworks, and PDFs with Ghostscripts. Because sometimes you just want to compress a file without opening a browser.
Key Features
- Menu Bar Integration: Quick access from anywhere - no need to open a full app
- Drag & Drop Interface: Just drop your file and it compresses automatically
- Multiple File Formats: Supports images (JPEG, PNG, HEIC, BMP, TIFF), videos (MP4, MOV, QuickTime), and PDFs
- Smart Compression: Automatically chooses the best compression method for each file type
- Three Compression Modes:
- Quality-based: Pick a quality percentage (0-100%)
- Target size: “Make this 5MB” and it figures out the right quality
- Percentage reduction: “Make it 50% smaller”
- Local Processing: Everything happens on your Mac - no internet required, no privacy concerns
- Smart Fallback: If compression makes the file bigger (already compressed files), it just uses the original
- Format Conversion: Automatically converts inefficient formats (PNG → JPEG when it makes sense)
Technical Highlights
Native macOS Development
Built using Apple’s native frameworks for optimal performance:
- SwiftUI + AppKit: Modern SwiftUI UI with AppKit menu bar integration
- ImageIO Framework: Hardware-accelerated image compression with format conversion
- AVFoundation: Hardware-encoded video compression using the Mac’s video chip
- Ghostscript Integration: Industry-standard PDF compression bundled with the app
Compression Strategies
Implemented Strategy pattern for clean, extensible architecture:
- Image Compression: Two-strategy approach (direct compression for light work, decode-recode for heavy compression)
- Video Compression: Uses AVFoundation export presets (High/Medium/Low quality)
- PDF Compression: Ghostscript with three quality levels (prepress/ebook/screen)
- Smart Format Selection: Converts lossless formats to efficient lossy formats when beneficial
Quality Calculation Algorithm
One of the trickier parts - reverse-engineering compression to hit target sizes:
- Image Formula: Uses empirical formula
size = 0.15 + 0.85 × quality^1.8to estimate quality from target size - Video/PDF Mapping: Maps target sizes to discrete preset quality levels
- Adaptive Calculation: Different algorithms for different file types based on testing
macOS Sandbox & Security
Proper security-scoped bookmark handling for sandboxed macOS apps:
- Security-scoped Bookmarks: Persists folder access permissions across app launches
- Proper Resource Management: Starts and stops accessing security-scoped resources correctly
- Bookmark Staleness Handling: Gracefully handles when permissions become invalid
Modern Concurrency
Swift async/await for responsive UI:
- Async Compression: All heavy operations run asynchronously
- MainActor Updates: UI updates properly isolated to main thread
- Structured Cleanup: Auto-cleanup after compression with Task.sleep
Technical Challenges Solved
- Menu Bar Popover Focus: Popover appeared greyish and unresponsive - fixed by ensuring popover window becomes key window using
makeKey()on the main queue - SwiftUI Publishing Warnings: “Publishing changes from within view updates” errors - solved by wrapping all
@Publishedupdates inDispatchQueue.main.async - Sandbox File Access Persistence: Lost file access after app restart - implemented security-scoped bookmarks with proper bookmark data persistence
- Quality Estimation: Hard to predict what quality gives what file size - developed empirical formulas through testing with real files
- Already-Compressed Files: Sometimes compression made files bigger - added size comparison and fallback to original file with hard links
Implementation Details
- MVVM Architecture: Clean separation between Views, ViewModels, and Models
- Strategy Pattern: Each file type has its own compression strategy implementation
- Lazy Initialization: Strategy map built once and cached for O(1) lookups
- Hard Links Over Copies: Uses hard links when possible for instant “copying” without data duplication
- Timestamp-based Naming: Avoids sequential file existence checks with Unix timestamp-based unique names
- Resource Values API: Uses modern
resourceValues(forKeys:)instead of deprecated file attributes API - UTType for File Detection: Uses UniformTypeIdentifiers instead of unreliable file extensions
- Cached Strategy Lookup: Pre-computed map for instant compression strategy selection
Performance Optimizations
Small things that add up to a snappy experience:
- Direct system calls for file size instead of dictionary lookups
- Hard links for instant file “duplication” when compression doesn’t help
- Timestamp-based unique filenames (no checking if file exists)
- Background queues for file operations to keep UI responsive
- Cached strategy map built once at initialization
- Smart compression path selection (fast path for light compression, full decode for heavy)
Lessons Learned
This project taught me a lot about macOS development. SwiftUI is great for UI, but you still need AppKit for menu bar stuff - thankfully bridging them is straightforward with NSHostingController.
Security-scoped resources are essential for sandboxed apps, and while they’re a bit annoying to work with, they’re necessary for proper macOS citizenship. The bookmark system makes sense once you understand it.
The Strategy pattern proved perfect for this use case. Adding support for new file types is trivial - just create a new strategy class and add it to the array. No touching existing code.
Swift’s async/await made concurrency so much easier compared to completion handlers. Code reads linearly, errors propagate automatically, and it’s just easier to reason about.
Most importantly, I learned that quality estimation for compression is really hard. Compression isn’t linear, it varies by format and content, and the only way to get good formulas is empirical testing with lots of real files. I still don’t have perfect formulas (spoiler: I’m not a wizard), but they work well enough.
Also learned that sweating the small performance details (hard links, resourceValues, cached lookups) makes the difference between “it works” and “it feels fast.” Users notice when things are snappy, even if they don’t know why.
What’s Next
Some ideas for future versions if I ever get around to them:
- Batch processing for multiple files at once
- Support for audio files (MP3, WAV, FLAC)
- Archive file compression (ZIP, RAR)
- Compression presets for common scenarios (“Email attachment”, “Web upload”, etc.)
- Before/after image preview
- More detailed progress reporting for large video files
- Option to replace original file instead of creating new compressed version
The architecture is clean enough that these additions should be pretty straightforward. Famous last words, right?
Built with Swift 5, SwiftUI, and a lot of trial and error. All code examples in the technical deep dive are from the actual SqueezeBar project. Hope this saves someone else from the online compressor grind!