开源了一个 macOS 语音输入法:Gravity — 按住 Fn 说话,AI 帮你写
起因
作为一个每天要打很多字的人,我一直在寻找更高效的输入方式。macOS 自带的语音听写功能(Dictation)体验很一般——识别准确率不高,不支持润色,更别提翻译了。市面上的语音输入工具要么需要付费订阅,要么需要把音频传到别人的服务器,要么操作繁琐,需要切换应用窗口。
我想要的很简单:按住一个键说话,松开后文字就自动出现在光标位置。就像 walkie-talkie 一样自然。
自己动手
有了这个想法后,我开始研究 macOS 上如何实现全局快捷键录音。最终选择了 Fn 键 ——它在 Mac 键盘上是最不常用的一个键,而且位置很顺手。通过 Swift 的 NSEvent.addGlobalMonitorForEvents 可以监听全局按键事件,再结合 Flutter 做 UI,整个方案就成型了。
核心流程非常简洁:
- 按住 Fn → 开始录音,屏幕顶部出现 Dynamic Island 风格的悬浮录音条,实时显示音频波形
- 松开 Fn → 录音结束,音频发送到 AI 服务进行语音识别(ASR)
- ASR 返回文字 → 再经过 LLM 润色或翻译
- 最终结果 → 自动粘贴到当前前台应用的光标位置
整个过程不需要切换窗口,不需要点击任何按钮,说完话就继续工作。
两种模式
使用中我发现,语音输入不只是”转文字”这一个需求。有时候我用中文说了一段话,但需要英文输出;有时候我口语化的表达需要变成更正式的书面语。于是我设计了两种模式:
- 单按 Fn → 润色模式(Refine):AI 会把你的口语表达润色成通顺的书面语
- Fn + Shift → 翻译模式(Translate):AI 会把你说的话翻译成目标语言,支持 19 种语言
这两种模式覆盖了我日常 90% 的语音输入场景。
不需要服务器
这个应用的一个重要设计原则是:所有 AI 处理都在客户端完成,使用你自己的 API Key。
我不想搭建后端服务,也不想收集用户的音频数据。用户只需要注册一个 AI 服务商(比如 Groq 或 SiliconFlow,都有免费套餐),把 API Key 填进去就能用。
为了适应不同地区的网络环境,我做了按区域路由的设计:
| 区域 | ASR(语音识别) | LLM(文本处理) |
|---|---|---|
| 美国区域 | Groq Whisper-large-v3 | OpenRouter GPT-4o-mini |
| 中国区域 | SiliconFlow SenseVoice | SiliconFlow Qwen2.5-32B |
中国区域只需要一个 SiliconFlow 的 Key 就能同时搞定语音识别和文本处理,注册即送免费额度,非常方便。
一些技术细节
开发过程中有几个有意思的技术点:
Dynamic Island 风格录音条:参考了 iPhone 上 Dynamic Island 的设计语言,做了一个悬浮在屏幕顶部的录音状态条,带实时音频波形。这样用户随时能知道当前的录音状态,又不会遮挡正常工作区域。
语音活动检测(VAD):为了避免误触发——比如不小心碰了一下 Fn 键——我加入了静音检测。如果录音内容全是静音,会自动丢弃,不会发送到 AI 服务浪费额度。
剪贴板注入:转录完成后,结果是通过模拟 Cmd+V 粘贴到前台应用的。为了不干扰用户剪贴板中原有的内容,粘贴完成后会自动恢复之前的剪贴板数据。
焦点抢占防护:作为一个始终在后台运行的工具,Gravity 的窗口不会抢占前台应用的焦点。录音条是一个独立的 overlay 窗口,不会让你正在编辑的文档失去焦点。
技术栈
| 层级 | 技术 |
|---|---|
| 客户端 | Flutter 3.32.0(macOS 专属) |
| 原生层 | Swift(Fn 键检测、剪贴板注入) |
| ASR | Groq Whisper / SiliconFlow SenseVoice |
| LLM | OpenRouter GPT-4o-mini / SiliconFlow Qwen2.5-32B |
| 国际化 | slang(支持 6 种 UI 语言) |
开源
今天我把这个应用整理了一下,开源到了 GitHub:
👉 https://github.com/muwe/audio_translater_input
如果你也厌倦了传统的打字方式,想试试用语音来提高输入效率,欢迎下载试用。项目采用 MIT 协议,也欢迎贡献代码和提出建议。
快速开始只需要三步:
cd app_demo
flutter pub get
flutter run -d macos
首次启动时记得授予辅助功能权限(Fn 键检测和剪贴板粘贴所必需)。