Press Fn, speak, paste anywhere. Speech-to-text for macOS that stays out of your way.
A menu bar speech-to-text app for macOS. Hit a hotkey, talk, and your words land on the clipboard -- ready to paste into any app. Uses ElevenLabs or OpenAI for transcription. No electron wrapper, no bloat, no window stealing focus.
Install | How It Works | Features | Configuration | Contributing
macOS dictation is slow and unreliable. Third-party voice typing apps are heavy, expensive, or both. RivaVoice is a single Python script that sits in your menu bar, records when you press Fn, and pastes the result. That's it.
Built for people who think faster than they type and don't want to fight their tools.
git clone https://github.com/longevityboris/rivavoice-transcriber.git
cd rivavoice-transcriber
# Install dependencies
pip install -e .
# Run the menu bar app
python menubar.py# Build .app bundle
./build_app.sh
# Or create a standalone .dmg
python create_standalone.py- macOS 10.15 Catalina or later
- Python 3.8+
- An ElevenLabs or OpenAI API key
- Microphone permission
- Accessibility permission (for global hotkey)
You press Fn --> PyAudio records a WAV --> ElevenLabs/OpenAI transcribes it --> Text hits your clipboard --> You paste
RivaVoice runs as a macOS menu bar app using PyQt6. It registers a global hotkey (default: Fn) via pynput. When you press it, pyaudio captures audio from your microphone. When you press it again, the recording stops and gets sent to the ElevenLabs Scribe API (or OpenAI's real-time WebSocket transcription). The text comes back, lands on your clipboard via pyperclip, and optionally auto-pastes into the active app.
No audio is stored. No data leaves your machine except the audio sent to the transcription API.
- Global hotkey -- Record from any app without switching windows. Default is Fn, fully configurable.
- Menu bar only -- No dock icon, no window to manage. Click the tray icon for controls and settings.
- Auto-paste -- Optionally paste transcribed text directly into the active text field.
- Dual transcription engines -- ElevenLabs Scribe (batch) or OpenAI real-time WebSocket transcription.
- Visual recording indicator -- A pulsing orb shows when you're recording. Hard to miss, easy to ignore.
- Clipboard-first -- Every transcription goes to your clipboard. Paste it wherever you want.
- Single instance -- Only one copy runs at a time. No duplicates, no conflicts.
- First-run onboarding -- Walks you through API key setup, permissions, and hotkey configuration.
Settings live in ~/.rivavoiceconfig.json. You can edit this file directly or use the settings view in the app.
| Setting | Default | Description |
|---|---|---|
api_key |
-- | Your ElevenLabs API key |
openai_api_key |
-- | Your OpenAI API key (optional) |
hotkey |
Fn |
Global recording hotkey |
auto_paste |
true |
Paste text after transcription |
transcription_engine |
elevenlabs |
elevenlabs or openai |
Copy .env.example to .env and add your API keys there as an alternative to the config file.
rivavoice-transcriber/
├── menubar.py # Menu bar app entry point (PyQt6)
├── rivavoice.py # Terminal UI entry point
├── rivacore/ # Core backend
│ ├── backend.py # Main orchestrator
│ ├── audio.py # PyAudio recording
│ ├── transcriber.py # ElevenLabs API client
│ ├── hotkey.py # Global hotkey management
│ ├── config.py # Configuration loading
│ ├── permissions.py # macOS permissions handling
│ └── text_utils.py # Text processing utilities
├── build_app.sh # Build macOS .app bundle
├── create_standalone.py # Create standalone .dmg
└── pyproject.toml # Project metadata and dependencies
Contributions are welcome. See CONTRIBUTING.md for guidelines.
Short version: fork, branch, PR. Keep changes focused. Follow the existing code style (Black, 100 char lines).
MIT License. See LICENSE for the full text.