Open Source, Free Tier Capable Whispr Using Cloudflare AI
Architecture
Voice-to-text tool that captures speech, transcribes it via Whisper, and formats the output with an LLM. Press a hotkey, speak, release - formatted text lands in your clipboard and is auto-pasted into whatever you were typing in.
โโโโโโโโโโโโโโโโโโโโโโโโ PCM chunks โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Wails Desktop App โ โโWebSocketโโโถ โ Cloudflare Worker (Durable Obj) โ
โ (Go + React WebView)โ โโโโโโโโโโโโโโ โ Whisper STT โ LLM Formatter โ
โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
formatted text
โ
โผ
Clipboard โ Auto-paste
Usage Flow
- Hold
Ctrl+Cmd- focus context is captured, recording starts, overlay appears at top-center - Speak into your microphone (voice level meter shows input)
- Release
Ctrl+Cmd- audio streams to the cloud - Whisper transcribes, LLM formats, result is copied to clipboard and auto-pasted into the originating app
Project Structure
voicebox/
โโโ main.go # Wails entrypoint, app menu
โโโ app.go # App lifecycle, hotkey handlers, pipeline orchestration
โโโ window_darwin.go # macOS window management (overlay, settings, dock click)
โโโ window_other.go # Stub for non-macOS builds
โโโ internal/
โ โโโ audio/ # PCM audio capture (malgo/miniaudio), RMS level
โ โโโ pipeline/ # WebSocket client, streams audio + focus context to worker
โ โโโ accessibility/ # macOS AX API: focused element context + auto-paste (Cmd+V)
โ โโโ config/ # TOML config loading and saving
โ โโโ hotkey/ # Global hotkey registration
โ โโโ stt/ # STT provider interface (stubs)
โ โโโ formatter/ # LLM formatting provider interface (stubs)
โโโ frontend/ # React + Tailwind overlay UI (Vite)
โ โโโ src/
โ โโโ App.tsx # Routes between settings mode and overlay mode
โ โโโ components/
โ โ โโโ settings-form.tsx # Config editor (react-hook-form + zod)
โ โ โโโ title-bar.tsx # Frameless title bar with drag region
โ โโโ hooks/
โ โโโ use-voicebox.ts # voicebox:state / voicebox:mode / voicebox:level events
โ โโโ use-config.ts # GetConfig / SaveConfig / GetConfigPath bindings
โโโ worker/ # Cloudflare Worker (TypeScript)
โ โโโ src/
โ โ โโโ index.ts # Router: /ws (WebSocket), /health
โ โ โโโ session.ts # Durable Object: audio accumulation + AI pipeline
โ โ โโโ prompt.ts # System prompt + user message builder
โ โ โโโ wav.ts # PCM-to-WAV wrapper
โ โ โโโ types.ts # Shared types
โ โโโ test/ # Vitest tests
โ โโโ wrangler.jsonc # Worker configuration
โโโ go.mod
โโโ voicebox.toml # User config (gitignored)
Prerequisites
- Go 1.24+
- Node.js + pnpm
- Wails v2 CLI
- A Cloudflare account with Workers AI access
- macOS (accessibility permission required for auto-paste)
Quick Start
cd worker
pnpm install
wrangler secret put VOICEBOX_TOKEN # set a shared secret
pnpm deploy
On first launch, VoiceBox opens a settings window. You can also create the config manually at ~/.config/voicebox/voicebox.toml:
[provider]
mode = "cloud"
[cloud]
worker_url = "https://voicebox.<your-subdomain>.workers.dev"
token = "your-shared-secret"
[audio]
sample_rate = 16000
channels = 1
chunk_size = 4096
[hotkey]
record = "ctrl+cmd"
Config is loaded from (in order): ~/.config/voicebox/voicebox.toml, next to the binary, then ./voicebox.toml.
Accessibility Permissions
Auto-paste requires macOS Accessibility access. On first use, macOS will prompt for permission, or you can grant it manually in System Settings โ Privacy & Security โ Accessibility.
Development & Build
wails dev # dev mode with hot reload
wails build # production binary
UI Windows
- Settings (700ร450, centered): Opens on launch, dock click, or via the Recording menu. Edit config here.
- Overlay (160ร48, top-center, floating): Appears during recording. Shows recording indicator with voice level meter, spinner while processing, checkmark on success.
WebSocket Protocol
Client connects to GET /ws?token=<token>. After receiving {"type":"ready"}, the client sends a configure message with audio and focus context, then streams binary PCM chunks:
Client Server
โโโ connect /ws?token=... โโโโโโโถ โ
โโโโ {"type":"ready"} โโโโโโโโโโ โ
โโโ {"type":"configure", ...} โโโถ โ
โโโ [binary PCM chunk] โโโโโโโโโโถ โ
โโโ [binary PCM chunk] โโโโโโโโโโถ โ
โโโ {"type":"audio_end"} โโโโโโโโถ โ
โโโโ {"type":"processing",...} โโ โ
โโโโ {"type":"result",...} โโโโโโ โ
The configure message carries audio params and focused element context (app name, bundle ID, element role, title, placeholder, current value) used by the LLM formatter to tailor output.
AI Models
- STT:
@cf/openai/whisper-large-v3-turbo - Formatter:
@cf/qwen/qwen3-30b-a3b-fp8
Local Fallback
- STT: faster-whisper
- Formatter: Ollama
Provider interfaces exist at internal/stt/ and internal/formatter/.
Audio Specifications
- 16kHz sample rate, mono, PCM signed 16-bit LE
- ~4096 byte chunks (~128ms each)
- Max recording: ~25 MiB (~13 minutes)
Commands
Desktop App
wails dev # dev server (Go + Vite hot reload)
wails build # production build
go vet ./... # lint Go
go test ./internal/... # test Go
Frontend
cd frontend && pnpm install && pnpm build
Worker
cd worker
pnpm dev # local dev server
pnpm lint # type-check
pnpm format # prettier
pnpm test # vitest
pnpm deploy # deploy to Cloudflare
Comments
No comments yet. Start the discussion.