Evan's Blog

开源了一个 macOS 语音输入法:Gravity — 按住 Fn 说话,AI 帮你写

·
#开源#macOS#语音输入#AI#Flutter
开源了一个 macOS 语音输入法:Gravity — 按住 Fn 说话,AI 帮你写

起因

作为一个每天要打很多字的人,我一直在寻找更高效的输入方式。macOS 自带的语音听写功能(Dictation)体验很一般——识别准确率不高,不支持润色,更别提翻译了。市面上的语音输入工具要么需要付费订阅,要么需要把音频传到别人的服务器,要么操作繁琐,需要切换应用窗口。

我想要的很简单:按住一个键说话,松开后文字就自动出现在光标位置。就像 walkie-talkie 一样自然。

自己动手

有了这个想法后,我开始研究 macOS 上如何实现全局快捷键录音。最终选择了 Fn 键 ——它在 Mac 键盘上是最不常用的一个键,而且位置很顺手。通过 Swift 的 NSEvent.addGlobalMonitorForEvents 可以监听全局按键事件,再结合 Flutter 做 UI,整个方案就成型了。

核心流程非常简洁:

  1. 按住 Fn → 开始录音,屏幕顶部出现 Dynamic Island 风格的悬浮录音条,实时显示音频波形
  2. 松开 Fn → 录音结束,音频发送到 AI 服务进行语音识别(ASR)
  3. ASR 返回文字 → 再经过 LLM 润色或翻译
  4. 最终结果 → 自动粘贴到当前前台应用的光标位置

整个过程不需要切换窗口,不需要点击任何按钮,说完话就继续工作。

两种模式

使用中我发现,语音输入不只是”转文字”这一个需求。有时候我用中文说了一段话,但需要英文输出;有时候我口语化的表达需要变成更正式的书面语。于是我设计了两种模式:

这两种模式覆盖了我日常 90% 的语音输入场景。

不需要服务器

这个应用的一个重要设计原则是:所有 AI 处理都在客户端完成,使用你自己的 API Key

我不想搭建后端服务,也不想收集用户的音频数据。用户只需要注册一个 AI 服务商(比如 Groq 或 SiliconFlow,都有免费套餐),把 API Key 填进去就能用。

为了适应不同地区的网络环境,我做了按区域路由的设计:

区域ASR(语音识别)LLM(文本处理)
美国区域Groq Whisper-large-v3OpenRouter GPT-4o-mini
中国区域SiliconFlow SenseVoiceSiliconFlow Qwen2.5-32B

中国区域只需要一个 SiliconFlow 的 Key 就能同时搞定语音识别和文本处理,注册即送免费额度,非常方便。

一些技术细节

开发过程中有几个有意思的技术点:

Dynamic Island 风格录音条:参考了 iPhone 上 Dynamic Island 的设计语言,做了一个悬浮在屏幕顶部的录音状态条,带实时音频波形。这样用户随时能知道当前的录音状态,又不会遮挡正常工作区域。

语音活动检测(VAD):为了避免误触发——比如不小心碰了一下 Fn 键——我加入了静音检测。如果录音内容全是静音,会自动丢弃,不会发送到 AI 服务浪费额度。

剪贴板注入:转录完成后,结果是通过模拟 Cmd+V 粘贴到前台应用的。为了不干扰用户剪贴板中原有的内容,粘贴完成后会自动恢复之前的剪贴板数据。

焦点抢占防护:作为一个始终在后台运行的工具,Gravity 的窗口不会抢占前台应用的焦点。录音条是一个独立的 overlay 窗口,不会让你正在编辑的文档失去焦点。

技术栈

层级技术
客户端Flutter 3.32.0(macOS 专属)
原生层Swift(Fn 键检测、剪贴板注入)
ASRGroq Whisper / SiliconFlow SenseVoice
LLMOpenRouter 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 键检测和剪贴板粘贴所必需)。