开源了一个 macOS 语音输入工具,用多模态大模型替代传统 ASR,按住说话文字就出来 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
Maxwin
V2EX    分享创造

开源了一个 macOS 语音输入工具,用多模态大模型替代传统 ASR,按住说话文字就出来

  •  
  •   Maxwin 4 天前 634 次点击
    周末花了两天写的,解决自己的痒点,顺手开源了。

    ## 背景

    之前一直用 Typeless 做 macOS 上的语音输入,体验确实好按住快捷键说话,文字直接出现在光标处。但 $8/月(约 60 )让我觉得有点贵,本质上就是个 API 调用的壳。于是自己动手写了一个。

    ## SpeakMore 是什么

    菜单栏常驻的语音输入工具。按住 Fn (或自定义热键)说话,松开后文字流式插入到当前光标位置。任何 App 都能用VS Code 、Slack 、浏览器、终端、微信,都行。

    ## 跟 Whisper 方案的区别

    大多数语音输入走的是:`录音 → Whisper 转文字 → 后处理清理`

    SpeakMore 不走 ASR ,直接把音频丢给多模态大模型( Gemini Flash 、通义千问等),一次 API 调用同时完成识别和优化。关键是连带发送的上下文:

    **三层上下文系统:**

    1. **实时上下文** 通过 macOS Accessibility API 读取当前 App 名称、窗口标题、文档路径。在 VS Code 里编辑 `deployment.yaml` 时说 "Kubernetes",不会被识别成"库伯内提斯"
    2. **短期记忆** 每 10 次输入分析最近 1 小时的转录,提取话题和高频词。聊了半小时数据库迁移,不会把 "Postgres" 听成 "post grass"
    3. **长期画像** 每天从 7 天数据中构建用户画像(职业、领域、语言习惯),PII 自动脱敏

    效果就是:专业术语不需要手动加词典,用着用着就准了。

    ## 踩坑最多的地方:文本插入

    在 macOS 上往别人的文本框里塞字,比想象中难多了。最后做了三级回退:

    1. **Accessibility API** 直接设 AXValue ,最快最干净,但不是所有 App 都支持
    2. **CGEvent 键盘模拟** 逐字符模拟按键,兼容性好但长文本慢
    3. **剪贴板粘贴** 保存剪贴板 → 写入文字 → Cmd+V → 恢复剪贴板,万能但不优雅

    几个坑:
    - iTerm2/Terminal.app 用 Accessibility 插入会字符重复,得检测终端 Bundle ID 直接跳到 CGEvent
    - 中文输入法激活时 CGEvent 会被 IME 拦截,要先发 Escape 关掉候选框
    - SSE 流式传输在弱网下会截断 JSON ,做了行级缓冲+容错

    老实说文本插入的调试时间比其他所有功能加起来都多。

    ## 技术细节

    - 纯 Swift 5.9 ,SwiftUI + AppKit ,零外部依赖
    - 音频:AVAudioEngine → 16kHz 单声道 PCM → 手动构建 WAV 头 → Base64 → HTTPS
    - SSE 流式响应,30ms 缓冲刷新,文字边生成边出现
    - 状态机架构:空闲 → 录音 → 转录 → 插入
    - 安装包 ~2MB ,没有 Electron ,没有捆绑模型

    ## 支持的服务商

    | 服务商 | 说明 |
    |--------|------|
    | Google Gemini | gemini-2.5-flash ,速度快 |
    | 通义千问 (DashScope) | qwen-omni-turbo ,国内访问友好 |
    | OpenRouter | 一个 Key 用多家模型 |
    | 自定义 | 任意 OpenAI 兼容接口 |

    自带 API Key ,单次转录成本大约 0.01 以内。

    ## 链接

    GitHub: https://github.com/Maxwin-z/SpeakMore-macOS

    MIT 协议,macOS 14+ 。

    有问题随时问,尤其是文本插入那块,可以聊很久(苦笑
    9 条回复    2026-03-20 15:54:53 +08:00
    andforce
        1
    andforce  
       4 天前
    “付费输入”代价还是有点高的奥,先收藏再说
    minminzi
        2
    minminzi  
    PRO
       4 天前
    上传的文件是不是漏了 SpeakMoreLite.xcodeproj ?
    xream
        3
    xream  
       4 天前
    希望能直接支持本地模型
    Maxwin
        4
    Maxwin  
    OP
       4 天前
    @minminzi 有 scheme 可以生成哈,让 vibe coding 做一下
    Maxwin
        5
    Maxwin  
    OP
       4 天前
    @andforce 成本还好,再说阿里云现在 token 也有免费额度。
    Maxwin
        6
    Maxwin  
    OP
       4 天前
    @xream 这个叫 lite ,实际我有个 full 版本,的用的是 openai-whisper ,效果不行,识别出来还要大量编辑。
    runking
        7
    runking  
       4 天前
    看了不下于 5 个这样的 APP 了

    等两天看看我的
    Maxwin
        8
    Maxwin  
    OP
       3 天前
    @runking 那说明 Typeless 这一类的产品真的技术壁垒太低了呀。
    runking
        9
    runking  
       1 天前
    @Maxwin #8 我的也上线了

    https://aether.7caifei.com/
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2990 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 13:50 PVG 21:50 LAX 06:50 JFK 09:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86