做了一个 Typeless 的开源平替:Mac 上的本地语音输入工具
按住说话,松开就是去掉口头禅、改好口误的文字。和 Typeless 体验类似,但声音从不离开你的 Mac;AI 整理接上 Ollama 本机模型或 macOS 自带的 Apple 智能,连文字也不出电脑。免费、开源、不用注册。
Typeless 很好用,但我不想把声音交出去
最近 Typeless 很火,我也用了一阵。它确实好用:随口说一段,出来的是通顺的书面文字,"嗯、那个"没了,说错改口的地方也理顺了。
但用久了有几件事让我不太舒服:
- 语音在云端识别。 Typeless 的数据说明里写得很清楚:转写在云端完成。它承诺不保存音频,服务商也不拿数据训练,但声音毕竟离开了我的电脑。
- 要注册账号。 想用就得先登录。
- 免费版每周有字数限制。 说得多就得订阅,Pro 按年付每月 12 美元,按月付每月 30 美元。
我每天会说很多工作上的内容:还没公开的需求、客户名字、内部讨论。这些东西我更希望只在自己电脑上处理。
所以我做了 Tidytalk:同样是"说完自动整理",但整条链路都可以在本机跑完。
| 你说的 | 输出 |
|---|---|
| 嗯那个我想问一下就是这个 API 的那个 rate limit 呃是多少 | 我想问一下这个 API 的 rate limit 是多少? |
| 项目要延期到下周三,不对,是下周四 | 项目要延期到下周四。 |
和 Typeless 比一比
先说清楚:Typeless 是成熟的商业产品,支持 Mac、Windows、Linux 和手机,开箱即用,这些 Tidytalk 都比不了。下面只对比我最在意的几项(Typeless 的信息来自它的官网价格页和数据说明页,2026 年 10 月核对):
| Tidytalk | Typeless | |
|---|---|---|
| 价格 | 免费,不限字数 | 免费版每周有字数限制;Pro 按年付每月 12 美元,按月付每月 30 美元 |
| 语音在哪里识别 | 你的 Mac 上 | 云端 |
| AI 整理 | 自己选:Ollama、LM Studio、Apple 智能在本机跑,或接自己的云端 API | 内置,在云端 |
| 能否离线 | 能 | 不能 |
| 账号 | 不需要 | 需要 |
| 平台 | 仅 Mac(macOS 26+、Apple 芯片) | Mac、Windows、Linux、iOS、Android |
| 开源 | 是,MIT 协议 | 否 |
如果你需要在手机和 Windows 上用,或者完全不想折腾设置,Typeless 更合适。如果你在意隐私、想离线用、经常中英文混着说,可以试试 Tidytalk。
"本地"到底本地到什么程度
"本地运行"这个词被用得很泛,所以我把每一步都拆开说清楚。
一直在本机的:
- 录音:只放在内存里,不写入磁盘。识别完就丢掉。
- 语音识别:用 sherpa-onnx 在本机跑模型,默认是阿里通义实验室开源的 SenseVoice。没有任何"云端识别"的选项,想上传也上传不了。
- 词库替换、中英文排版、粘贴:都是本地代码。
- 最近记录:最近 20 条结果只在内存里,退出就清空。
- 实时字幕:只录电脑播放的声音、不录麦克风,在本机识别,关掉字幕就清空。
- 自动学词:粘贴后一分半钟内比较你在输入框里改了哪些词,只提示、不保存。
可能会离开电脑的,只有一项:AI 整理。
| 你的设置 | 声音 | 文字 |
|---|---|---|
| Ollama / LM Studio 本机模型 | 不离开 | 不离开 |
| Apple 智能(macOS 内置端侧模型) | 不离开 | 不离开 |
| 关闭"整理文字"(直接输出识别结果) | 不离开 | 不离开 |
| 云端接口(DeepSeek、OpenAI 等) | 不离开 | 只发送识别出的文字 |
另外,应用会联网的地方,我在代码里一个个列出来了,一共就这几处:
- 第一次使用时下载识别模型(Hugging Face,失败自动换 HF-Mirror 国内源),下载完会做 SHA-256 校验;
- 检查更新:启动时访问一次 GitHub 上的最新版本,一天最多一次,可以在设置里关掉;
- 你配置的 AI 服务(选 Ollama、LM Studio 时是本机通信;选 Apple 智能时不走网络);
- 转写视频链接时:第一次会从 yt-dlp 的 GitHub 官方 Release 下载它并校验,然后下载你给的视频的音频,转写完立刻删除。
没有统计、没有埋点、没有账号。保存 API Key 的配置文件 ~/.tidytalk.json 权限是 600,只有你自己的用户能读。
别信我,自己验证
隐私这种事,"我说没上传"没什么说服力,所以 Tidytalk 是开源的,你可以用下面几种办法自己确认。
1. 断网试一下
关掉 Wi-Fi,AI 服务选 Ollama(或者关闭整理),照常按住快捷键说话。能正常出字,就说明整条链路没有依赖网络。
2. 看它在连哪里
一边用,一边在终端看 Tidytalk 的网络连接:
# 实时查看 Tidytalk 的网络流量
nettop -p Tidytalk
# 或者列出它当前打开的网络连接
lsof -i -n -P | grep -i tidytalk
用本机模型时,你只会看到它连 127.0.0.1(Ollama 默认端口 11434,LM Studio 默认 1234)。
3. 直接看代码
所有发网络请求的地方只有这 4 个文件,一眼就能看完:
git clone https://github.com/byteyu2436/tidytalk.git
cd tidytalk
grep -rln "URLSession" Sources
Sources/Tidytalk/Services/ChatCompletionClient.swift # 调用你配置的 AI 服务
Sources/Tidytalk/Services/ModelManager.swift # 下载识别模型
Sources/Tidytalk/Services/UpdateChecker.swift # 检查更新
Sources/Tidytalk/Services/FileTranscription.swift # 下载 yt-dlp
三步配一个完全离线的语音输入
第一步:装 Ollama,拉一个模型
brew install ollama
ollama serve # 或者直接打开 Ollama 应用
ollama pull qwen2.5:7b
整理口语这件事,7B 左右的模型基本够用。模型太小的话,容易不听"只整理、不回答"的要求。
第二步:在 Tidytalk 里选 Ollama
打开"设置 › 配置 AI",在"AI 服务"里选 Ollama,确认模型名,点"测试连接"。本机模型不需要 API Key。
更省事的选择:Apple 智能
如果你的 Mac 支持 Apple 智能,第一步都可以省掉:在"系统设置"里打开 Apple 智能,再回到 Tidytalk 的"配置 AI"选 Apple 智能 就行。
- 用的是 macOS 内置的端侧模型(Foundation Models 框架),整理和翻译都在本机完成;
- 不用装 Ollama、不用下载模型、不用 API Key;
- Mac 不支持或者没打开 Apple 智能时,这个选项会变灰,并写明原因(比如上图里"这台 Mac 不支持 Apple 智能")。
实现上不复杂。先用 SystemLanguageModel.default.availability 判断能不能用,不能用时把原因直接显示在选项上:
switch SystemLanguageModel.default.availability {
case .available:
nil
case .unavailable(.deviceNotEligible):
String(localized: "这台 Mac 不支持 Apple 智能")
case .unavailable(.appleIntelligenceNotEnabled):
String(localized: "请先在系统设置里打开 Apple 智能")
case .unavailable(.modelNotReady):
String(localized: "Apple 智能还没准备好,请稍后再试")
case .unavailable:
String(localized: "Apple 智能暂时不可用")
}
整理时复用了给 OpenAI 兼容接口准备的那套对话消息:system 消息和示例对话合并成 instructions,最后一条用户消息作为输入,用贪心采样让同样的话每次整理结果一致:
let session = LanguageModelSession(instructions: instructions)
let text = try await session.respond(
to: prompt,
options: GenerationOptions(samplingMode: .greedy)
).content
说句实话:我手上这台 Mac 用不了 Apple 智能,这一项还没有在真机上完整测过。如果你的 Mac 支持,欢迎试试并告诉我效果。
第三步:选一个识别模型
在"设置 › 识别模型"里选,所有模型都在本机运行:
| 模型 | 大小 | 适合 |
|---|---|---|
| SenseVoice(默认) | 约 240 MB | 速度最快,20 秒的话约 0.3 秒识别完,中英文混说效果好 |
| Qwen3-ASR | 约 1 GB | 最准确,支持 30 种语言和 22 种中文方言,能直接认出词库里的人名和术语 |
| Fun-ASR-Nano | 约 1 GB | 中文、英文、日文,准确度接近 Qwen3-ASR,稍快 |
| Whisper Turbo | 约 1 GB | 约 99 种语言,适合小语种;中文会漏字 |
| Apple 系统识别 | 不用下载 | 按系统语言识别,中英文混说一般 |
到这里,从录音、识别到整理,没有任何一步需要联网。
Typeless 有的,这里也有
除了"说完自动整理",Typeless 常用的几个功能 Tidytalk 也都做了:
- 语音改写选中文字:选中一段,按住右侧 Option 说"改得正式一点""缩短成一句话",松开就替换好。
- 说中文,出英文:设置输出语言,整理时顺便翻译,支持 8 种语言。
- 个人词库:常用词、固定替换、快捷短语、自定义规则。
- 自动学词:粘贴后你手动改了某个词,会提示你一键加入词库。
另外还有两个功能:
- 实时字幕:按 ⌃⌥C 给电脑正在播放的视频、网课、会议加字幕,可以边听边翻译。
- 转写文件和链接:拖入录音、视频,或者粘贴 YouTube、B 站链接,转成带时间戳的文字,导出 TXT、SRT 或 Markdown。
两个和"本地"有关的坑
做本地识别时踩了两个不太明显的坑,记录一下。
坑 1:VAD 一次喂一大段音频,只返回最后一句
转写长录音时,我先用 Silero VAD 按停顿把音频切成一句一句,再逐句识别。一开始图省事,把整段音频一次塞给 VAD,结果只拿到了最后一小段。
sherpa-onnx 的 VAD 是按"实时流"设计的,实时字幕那边本来就是一小块一小块送进去的。文件转写也改成同样的做法,按 0.1 秒一块喂,每喂一块就把已经切好的片段取出来,就正常了:
let vad = try VoiceActivityDetector(minSilence: 0.5, maxSpeech: 20)
var segments: [VoiceActivityDetector.Segment] = []
// 和实时收听一样小块送入(0.1 秒);一次送入很长的音频时,检测器只会切出最后一段
let step = AudioMath.sampleRate / 10
var offset = 0
while offset < samples.count {
let end = min(samples.count, offset + step)
segments += vad.acceptSegments(Array(samples[offset..<end]))
offset = end
}
segments += vad.flushSegments()
坑 2:转写的每一段都少了开头几个字
切好的片段送去识别,经常丢掉开头的一两个字。原因是 VAD 判断"开始说话"有一点延迟,切出来的起点比真正开口晚了一点点。
解决办法是每段的起点往前多留 0.3 秒,宁可多一点静音,也不切掉开头的字:
// 检测器确认开始说话时,这句话已经开始了一小会儿;往前多取 0.3 秒,免得吞掉开头的字
let padding = AudioMath.sampleRate * 3 / 10
let start = max(0, segment.start - padding)
不足
说几句实话:
- 只支持 macOS 26 及以上、Apple 芯片的 Mac,没有 Windows 和手机版;
- 安装包还没有经过苹果公证,第一次打开要去"系统设置 › 隐私与安全性"点"仍要打开";
- 本机小模型(包括 Apple 智能的端侧模型)的整理效果比不上云端大模型,长段落偶尔会整理得不够干净;
- 第一次要下载识别模型(240 MB 到 1 GB 不等)。
安装
- 到 GitHub Releases 下载 DMG,把 Tidytalk 拖进"应用程序"文件夹;
- 第一次打开被拦的话,去"系统设置 › 隐私与安全性"点"仍要打开",或者在终端执行:
xattr -dr com.apple.quarantine /Applications/Tidytalk.app
3. 按引导授权麦克风和辅助功能、选 AI 服务(可以跳过)、下载识别模型,就能用了。
最后
项目以 MIT 协议开源,欢迎试用、提 Issue,也欢迎点个 Star ⭐️:
- GitHub:github.com/byteyu2436/…
- 官网:tidytalk.zayen.dev/zh/
- 和 Typeless 的详细对比:tidytalk.zayen.dev/zh/alternat…
你平时用语音输入吗?更在意识别准不准,还是声音会不会被上传?欢迎在评论区聊聊 🙌