Native macOS menu bar application for reading text and URLs aloud, with built-in system TTS and optional Google Cloud TTS for premium voice quality.
- Dual TTS engines: Free system voices (AVSpeechSynthesizer) or premium Google Cloud TTS
- Menu bar interface with SwiftUI
- URL content extraction with HTML parsing
- Customizable voice and playback speed (0.5x - 2.0x)
- Real-time playback progress with text highlighting
- Playback controls: play/stop (input window), pause/resume/stop (menu bar)
- API key stored securely in macOS Keychain
- Structured logging using OSLog
- macOS 14.0+
- Xcode 15.0+ (for development)
- Swift 5.9+
brew tap minac/speakeasy-mac
brew install --cask speakeasy- Download the latest
.dmgfrom Releases - Open the DMG and drag
Speakeasy.appto Applications - Launch from Applications or Spotlight
git clone https://github.com/minac/speakeasy-mac.git
cd speakeasy-mac
./run.sh build release
cp -r build/release/Speakeasy.app /Applications/- Click the speaker icon in the menu bar
- Select "Read Text..."
- Enter text or paste a URL
- Click "Play" to start playback (button changes to "Stop")
- Input Window: Play/Stop toggle button
- Menu Bar: Pause, Resume, and Stop buttons appear during playback with progress indicator
- Engine: Switch between System (free) and Google Cloud TTS
- Voice: Choose from system voices or Google Cloud voices
- Speed: Adjust playback speed (0.5x - 2.0x)
For more natural-sounding free voices on macOS:
- Open System Settings > Accessibility > Spoken Content
- Click System Voice > Manage Voices...
- Download Enhanced or Premium versions
Google Cloud TTS provides dramatically better voice quality than system voices. The free tier includes 1 million characters per month for standard voices and 1 million for WaveNet/Neural2 — most users will pay nothing.
- Go to Google Cloud Console
- Sign in with your Google account (or create one)
- If this is your first time, you'll get $300 in free credits for 90 days
- Click the project dropdown at the top of the console
- Click New Project
- Name it (e.g. "Speakeasy TTS") and click Create
- Make sure the new project is selected in the dropdown
- Go to APIs & Services > Library
- Search for "Cloud Text-to-Speech API"
- Click it, then click Enable
- Go to APIs & Services > Credentials
- Click + Create Credentials > API Key
- Copy the API key
Recommended: Restrict the key to only the Text-to-Speech API:
- Click on the newly created key
- Under API restrictions, select Restrict key
- Choose Cloud Text-to-Speech API from the dropdown
- Click Save
- Open Speakeasy Settings
- Switch the engine to Google Cloud
- Paste your API key — voices load automatically
- Pick a voice (Neural2 and Studio voices sound the most natural)
- Click Save
| Voice | Type | Description |
|---|---|---|
| en-US-Neural2-D | Neural2 | Male, natural conversational tone |
| en-US-Neural2-F | Neural2 | Female, clear and natural |
| en-US-Studio-O | Studio | Male, broadcast quality |
| en-US-Studio-Q | Studio | Female, broadcast quality |
| en-GB-Neural2-B | Neural2 | British male |
| Tier | Free Monthly Quota | Price After |
|---|---|---|
| Standard | 4M characters | $4/1M chars |
| WaveNet | 1M characters | $16/1M chars |
| Neural2 | 1M characters | $16/1M chars |
| Studio | 0.1M characters | $160/1M chars |
A typical article is ~5,000-10,000 characters. With Neural2 voices, the free tier covers 100-200 articles per month.
Full pricing: Google Cloud TTS Pricing
# Debug build (for development)
./run.sh build debug
open build/debug/Speakeasy-build.appswift test --package-path SpeakeasyOr in Xcode: Cmd+U
Speakeasy/
├── Speakeasy/
│ ├── SpeakeasyApp.swift # App entry point
│ ├── Core/
│ │ ├── AppState.swift # Central state management
│ │ ├── SpeechEngine.swift # TTS engine (system + audio playback)
│ │ └── TextExtractor.swift # URL/HTML processing
│ ├── Models/
│ │ ├── SpeechSettings.swift # Settings model
│ │ ├── TTSEngine.swift # Engine enum (system/googleCloud)
│ │ ├── Voice.swift # Voice wrapper (system + Google)
│ │ └── PlaybackState.swift # Playback states
│ ├── Services/
│ │ ├── SettingsService.swift # UserDefaults persistence
│ │ ├── KeychainService.swift # Secure API key storage
│ │ ├── GoogleCloudTTSService.swift # Google Cloud TTS API client
│ │ └── VoiceDiscoveryService.swift # System voice enumeration
│ ├── Utilities/
│ │ ├── Logger.swift # OSLog structured logging
│ │ └── Extensions.swift # String extensions
│ ├── Views/
│ │ ├── MenuBarView.swift # Menu bar interface
│ │ ├── InputWindow.swift # Text input window
│ │ ├── SettingsWindow.swift # Settings interface
│ │ └── Components/
│ │ ├── VoicePicker.swift
│ │ ├── SpeedSlider.swift
│ │ └── HighlightedTextView.swift
│ ├── ViewModels/
│ │ ├── InputViewModel.swift
│ │ └── SettingsViewModel.swift
│ └── Resources/
│ ├── Info.plist
│ ├── Speakeasy.entitlements
│ └── Speakeasy-MAS.entitlements
└── Tests/
├── CoreTests/
├── ServicesTests/
└── ViewModelTests/
- SwiftSoup - HTML parsing
The project uses Swift Package Manager with run.sh to build, sign, and package the app.
./run.sh # Build and run (swift run)
./run.sh build [debug|release] # Build .app bundle
./run.sh sign # Code sign release build
./run.sh dmg <version> # Create signed + notarized DMG
./run.sh mas <version> # Create Mac App Store .pkg
./run.sh release <version> # Full pipeline: build → sign → dmgReleases are automated via GitHub Actions — pushing a v* tag builds, signs, notarizes, and publishes a DMG to GitHub Releases.
Make sure you're running the app as a proper .app bundle (not via swift run), as terminal-launched apps capture keyboard input.
- Verify your API key is correct in Settings
- Ensure the Cloud Text-to-Speech API is enabled in your Google Cloud project
- Check that the API key is not restricted to other APIs
- If you see "API key is invalid", regenerate the key in Google Cloud Console
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests first (TDD)
- Implement feature
- Run tests (
swift test) - Commit your changes
- Push to the branch
- Open a Pull Request
MIT
- Built with Claude Code



