The Problem
Users on macOS need a fast, offline voice‑to‑text tool that integrates with the OS (menu bar, global shortcuts) without sending audio to the cloud. Existing solutions either rely on heavyweight cloud APIs or lack tight macOS UI integration, resulting in latency, privacy concerns, and poor user experience.
What This Does
VoiceInk is a native macOS app (requires macOS 14+) that captures microphone input, runs it through local AI transcription models, and inserts the resulting text wherever the cursor is positioned. The core logic lives in the VoiceInk/ source tree:
AppDelegate.swift– application entry point; registers menu bar UI (MenuBarManager.swift), global hotkeys (HotkeyManager.swift), and the recording pipeline.CoreAudioRecorder.swift– low‑level audio capture using CoreAudio, feeds raw buffers toAudioFileProcessor.swift.TranscriptionServiceRegistry.swift+ concrete services (NativeAppleTranscriptionService.swift,CloudTranscription/*) – select and invoke the appropriate transcription backend.Models/Transcription.swift&Models/TranscriptionModel.swift– data structures that travel from the service back to UI components (Views/Recorder/AudioVisualizerView.swift,Views/History/TranscriptionHistoryView.swift).
The UI layer (Views/*) is pure SwiftUI; it consumes the model objects and updates the menu bar popover, mini‑recorder window, or on‑screen overlay.
How It Is Wired
Execution starts in AppDelegate.swift (the @main entry). On applicationDidFinishLaunching it:
- Instantiates
MenuBarManager→ creates the menu bar icon and binds actions toMenuBarManager.showMiniRecorder. - Starts
HotkeyManager→ registers global shortcuts that callRecorder.startRecording()(found inRecorder.swift). Recorder.startRecordingcreates aCoreAudioRecorderinstance, which streams PCM frames toAudioFileProcessor.process(buffer:).- The processor writes a temporary audio file and hands the file URL to
TranscriptionServiceRegistry.shared.activeService.transcribe(url:). - The selected service (default
NativeAppleTranscriptionService) returns aTranscriptionmodel;Recorderposts this toNotificationCenter. - UI observers in
Views/Recorder/AudioVisualizerView.swiftandViews/History/TranscriptionHistoryView.swiftreceive the notification and update the SwiftUI state, causing the text to appear in the active document viaCursorPaster.swift.
All side‑effects (file writes, keychain access for API keys, user defaults) are confined to the Services/ layer. No circular import edges were detected; the import graph consists of a flat hierarchy of Swift files.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/VoiceInk
cd VoiceInk
# Build with Xcode (project file included) or make
make # invokes xcodebuild as defined in Makefile
open VoiceInk.xcodeproj
No additional configuration files are required. If you wish to use a cloud transcription provider, place the API key in the macOS Keychain; Services/APIKeyManager.swift reads it at runtime. Run the app from Xcode or the generated .app bundle; the menu bar icon appears, and the default global shortcut (⌥⌘R as defined in HotkeyManager.swift) starts/stops recording.
Real‑World Use
A technical writer installs VoiceInk, configures a shortcut, and activates the mini‑recorder while drafting a document. Each utterance is transcribed locally within seconds and injected at the cursor position, eliminating the need to switch to a separate dictation window. The writer can also enable “Power Mode” (PowerMode/PowerModeSessionManager.swift) to load per‑application prompts automatically when switching between IDE, email client, and word processor.
Code Health & Issues
- HIGH – Deep nesting (59 occurrences, e.g.,
Models/CustomPrompt.swift,Notifications/AnnouncementView.swift). Indentation depth up to 11 makes control flow hard to follow. - HIGH – Duplicated code blocks (≈190 repeating 6‑line snippets across 44 files such as
CoreAudioRecorder.swift,AudioDeviceManager.swift). Refactor into shared helpers. - HIGH – No test suite – repository contains 184 source files but no test files. Add unit/UI tests for each public API and integrate into CI.
- HIGH – No CI pipeline – no GitHub Actions or other build automation. Add a workflow that runs
make(orxcodebuild) on push and pull request. - Repository hygiene – tests present: no; CI: no; Dockerfile: no; licence: yes (GPL‑3.0); lockfile: no; committed secrets: none.
The Bottom Line
VoiceInk delivers a tightly integrated, offline voice‑to‑text experience for macOS, with a clear SwiftUI UI and modular service layer. However, the codebase suffers from deep nesting and duplicated snippets, and it lacks automated testing and CI. Engineers planning to extend or maintain the project should first address these hygiene gaps to reduce regression risk. Suitable for teams comfortable with native macOS development who need on‑device transcription with a customizable UI.