当我写代码戴上降噪耳机的时候, 听不到键盘声,有些不习惯, 于是想找一个按键音的软件, 但不是收费就是占我的内存, 功能也不符合我的需求.
所以------自己写了一个
KeyTone,常驻菜单栏的键盘 / 鼠标音效引擎,MIT 开源。

它能做什么
把每一次敲击和点击变成声音:机械轴的清脆、打字机的咔哒、老式薄膜键盘的闷响。
内置 21 个音色包------19 个是真实录音采样,2 个是运行时用波形合成的。键盘和鼠标各自独立,可以分别切换。
挑几个名字你大概有感觉:Cherry MX 棕 / 蓝 / 黑、Holy Panda、NK Cream、Gateron 红墨 / 黑墨、Alpaca、Logitech G915 TKL、打字机、iOS 键盘。鼠标那边有 G502 X、Corsair M65 Elite、M570 轨迹球、Magic Mouse。
一共 174 个音频文件,全部编译进二进制,首次启动自动装好,不用你手动找素材。
三个我真正在意的细节
一、延迟必须压到感觉不到
这是最容易被做砸的地方。很多实现是"收到事件 → 读文件 → 解码 → 播放",一路下来几十毫秒就出去了,打字快的时候声音会拖在手指后面,非常难受。
KeyTone 的做法是启动时把音频全部预解码进内存,按下时直接推给音频线程。实测从按键到出声在 10ms 级别------比你眨眼快两个数量级。
中间还踩了个坑:rodio 默认按 采样率 / 20 算缓冲(48kHz 下是 2048 帧),但部分声卡实际只接受几百帧的区间,直接开会失败。最后改成按 [480, 960, 256, 240] 逐个降级试,480 帧正好 10ms。
二、同一个键不能永远是同一个声音
真人敲键盘,每一下的力度、角度、时机都不同,所以听起来是"活的"。如果每个键只有一份采样,连打就变成了复读机。
所以每个键位可以绑定多个采样变体,播放时随机挑一个。同时做了峰值归一化------不同音色包的录音电平差异最大能到 10 倍,加载时统一归一到接近满刻度,切包不会出现"这个听不见、那个炸耳朵"。
三、它不该打扰你
这一条听着像产品废话,但落到实现上很具体:
- 本应用窗口在前台时不发声。 你点自己的界面、在自己的窗口里打字,不该被自己的音效吵到。
- 关闭窗口是真的销毁 WebView,不是隐藏。常驻内存明显下降------毕竟 99% 的时间它只是躺在菜单栏里。
- 关窗口只是收进托盘,进程不退出,音效一直在。
一个有点怪但很好用的功能
键位语音播报。
打开之后,每按一个键,系统会用语音把键名念出来。中文模式下 A 念"啊"、B 念"波"------这里做了个小处理:直接把拉丁字母丢给中文语音,它会把 A 读成英文字母名,很出戏,所以用同音汉字把读音锁死。
中文模式还特意区分了鼠标左键 和左箭头键:前者念"左键",后者念"左箭头",不会混。
说实话我一开始觉得这是个玩具功能,直到我开始用它检查键盘------哪个键没触发、哪个键连击,听声音比看日志快多了。打字快的时候它会打断上一句,保证念的永远是你刚按下的那个键。
技术上几个不太显然的点
如果你也是写 macOS 应用的,这几条能帮你省几天:
CGEventTap 的修饰键走 FlagsChanged 事件,没有独立的按下 / 抬起。必须读事件里的 flag 位判断当前状态,否则 Shift 和 Command 会一直被判为"按住不放"。
AXIsProcessTrusted() 永远不会弹授权框。 想弹只能用 AXIsProcessTrustedWithOptions 配 kAXTrustedCheckOptionPrompt。
菜单栏图标会被系统强制缩放到 18pt 高。 你提高 PNG 分辨率不会让它变大,只会变糊。想让图形占满画框,只能收紧 SVG 的 viewBox。
还有一个不算技术但很要命的:打包时如果没签名,辅助功能授权是拿不到的。 TCC 必须把授权绑定到一个稳定的代码签名身份上,.app 包没签名(只有内层可执行文件带链接器的 ad-hoc 签名)时,用户在系统设置里勾了也没用,AXIsProcessTrusted() 永远返回 false。
更麻烦的是 ad-hoc 签名的授权绑在 cdhash 上,每次重新编译都失效。解法是本机造一张自签名证书来签,授权就绑在证书上,只需要勾一次。
现在能用到什么程度
说清楚,免得你装完失望:
| 平台 | 状态 |
|---|---|
| macOS 13+ | 已实机验证,键盘 / 鼠标 / 语音全部可用 |
| Windows 10+ | 已实现并通过编译与单测,还没实机验证 |
| Linux | evdev 实现已写,未验证,需要 input 组权限 |
Windows 那边低级钩子(WH_KEYBOARD_LL + WH_MOUSE_LL)已经接好了,不需要任何授权------这点比 macOS 省事。但语音播报还没做,Windows 要接 SAPI,暂时是隐藏状态。
macOS 安装时 Gatekeeper 会拦一次(没做公证),右键「打开」就行,或者:
sh
xattr -dr com.apple.quarantine /Applications/KeyTone.app
然后记得去「系统设置 → 隐私与安全性 → 辅助功能」勾上,否则捕获不到全局按键。
关于开源
MIT,代码在 GitHub 上:github.com/PikachuGits...
技术栈是 Tauri 2 + Rust,前端就是一个单文件静态 HTML,没有框架也没有构建步骤------改完 HTML 直接 cargo build 就能看效果,这点我挺喜欢的。
音色包的命名沿用了这个生态里的通行写法(backspace / enter / leftshift),所以现成的音色包可以原样导入 ,不用改包。想自己做一套也很简单,一个 profile.yaml 加几个音频文件就行。
最后说一句为什么做这个。
不是因为市面上没有同类工具,是因为我想要一个不用配置、装上就响、敲起来像那么回事的东西。它不该是一个需要研究的软件,应该像键盘本身的一部分------你在打字,它在发声,仅此而已。
如果你也总觉得敲键盘少了点声音,可以试试。