内容
<p align="center">
<img src="docs/assets/logo.png" width="140" alt="Tamlil">
</p>
<h1 align="center">Tamlil</h1>
<p align="center">
<strong>自动、私密的会议转录,支持希伯来语和英语混合。</strong>
</p>
<p align="center">
<a href="https://github.com/Steven17D/tamlil/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/Steven17D/tamlil/ci.yml?branch=main&label=CI" alt="CI status"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" alt="License: Apache-2.0"></a>
<a href="Tamlil/Package.swift"><img src="https://img.shields.io/badge/macOS-15%2B-black" alt="macOS 15+"></a>
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.12-blue" alt="Python 3.12"></a>
</p>
Tamlil 是一款 macOS 菜单栏应用程序,可以记录 Zoom 和 Slack 通话,并将其转换为干净的、带有发言人标签的转录文本 - 即使在对话中途从希伯来语切换到英语。它在通话开始时自动开始录音,通话结束后转录文本即可供查看。所有内容都保留在您的 Mac 上;只有转录请求会离开 Mac - 通话音频和简短的识别提示(会议标题、与会者姓名、学习术语)- Tamlil 会在收到转录文本后立即从提供商删除上传内容。
<p align="center">
<img src="docs/assets/hero.png" width="760"
alt="Tamlil 在 macOS 菜单栏中:一个弹出窗口,显示带有发言人标签和内联双轨音频播放的希伯来语和英语会议转录文本">
</p>
## 为什么选择 Tamlil
- **它自动记录。** 加入 Zoom 通话或 Slack 聚会,Tamlil 开始捕捉;挂断后,自动生成转录文本。无需启动、点击或记住打开它。
- **为希伯来语和英语一起构建。** 大多数转录服务要求您为每个会议选择一种语言。Tamlil 能够处理双语实时语音,标记每个单词的语言,因此以希伯来语开始、以英语结束的句子也能正确转录。
- **每个发言者都有标签 - 并且可播放。** 您的音频和对方的音频被分开并命名,生成的录音内联播放波形,您可以跳转到任意行并准确听到所说的内容。
- **纠正后它会记住。** Tamlil 在转录文本中标记它不确定的单词。修正一个后,它会记住该术语,以便在未来的所有会议中正确使用,因此您的名称、产品和专业术语不会再出错。
- **默认私密。** 录音、转录文本和学习词汇库仅存储在您的 Mac 上。您的 API 密钥存储在 Keychain 中,从不存储在文件中。每次会议后,Tamlil 会删除音频和转录文本上传,以便确保私密。
## 内部一览
<table>
<tr>
<td width="50%" valign="top" align="center">
<img src="docs/assets/calls-log.png" alt="Tamlil 菜单栏中记录的会议列表及其状态">
<em>所有通话都在一个列表中 - 录音中、处理中或已准备好阅读。</em>
</td>
<td width="50%" valign="top" align="center">
<img src="docs/assets/review.png" alt="带有内联低置信度单词标志的转录文本,一键纠正">
<em>不确定的单词内联标志;修正一个,Tamlil 会记住它。</em>
</td>
</tr>
</table>
## 安装
一条命令即可安装。您需要 macOS 15(Sequoia)或更高版本,安装了 Xcode Command Line Tools 16 或更高版本(`xcode-select --install`;构建需要 Swift 6 工具链);安装程序会处理其他所有事情。
```bash
curl -fsSL https://raw.githubusercontent.com/Steven17D/tamlil/main/scripts/install.sh | zsh
```
它克隆 Tamlil,构建并安装应用程序,将转录连接器放在您的 PATH 上,询问您的 Soniox API 密钥(来自 [console.soniox.com](https://console.soniox.com)),并启动。第一次通话记录时,macOS 会要求您批准 **麦克风** 和 **系统音频记录** - 请允许。重新运行命令会更新现有安装;可选的 Google 日历会议标题需要一次性 OAuth 客户端设置 - 请参阅 [Google 日历设置](#google-日历设置-自带-oauth-客户端)。
<details>
<summary>希望手动安装?</summary>
```bash
git clone https://github.com/Steven17D/tamlil.git
cd tamlil
uv sync # Python 依赖项(从 astral.sh/uv 安装 uv)
make app # 构建 Tamlil.app
rm -rf /Applications/Tamlil.app && cp -R Tamlil/dist/Tamlil.app /Applications/
defaults write dev.dashevsky.tamlil repoPath "$PWD"
scripts/launch-agent.sh restart # 在崩溃监督下启动
# 将您的 Soniox 密钥存储在 Keychain 中(永远不要在文件中)
security add-generic-password -s tamlil-soniox -a soniox -w "<KEY>" -U
```
要从 AI 代理读取会议,请将连接器放在您的 PATH 上:`uv tool install --force .` 然后 `claude mcp add tamlil --scope user -- "$HOME/.local/bin/tamlil-mcp"`。
</details>
**更新。** 点击菜单中的 **检查更新**,或重新运行安装命令 - Tamlil 拉取最新版本,从源代码重建并重启。
## 工作原理
1. **加入通话。** 当通话应用程序(Zoom 或 Slack 通话或聚会)开始使用您的麦克风时,Tamlil 记录两个本地音轨:您的麦克风和会议的系统音频。
2. **挂断。** 通话结束,录音停止,自动在完成的录音上进行转录。
3. **阅读转录文本。** 两个音轨被转录、合并、标记发言者、清理麦克风回声,并通过学习词汇库重写。完成的转录文本出现在菜单栏应用程序中,并保存在 `~/Recordings/Tamlil/` 下。
4. **询问代理(可选)。** Claude Code 或 Codex 通过只读连接器读取完成的会议并编写自己的摘要。
有关菜单栏应用程序、管道、转录、词典、连接器和 Google 日历如何协同工作的详细信息,请参阅 [架构概述](docs/architecture.md)。
## 隐私和数据处理
Tamlil 记录实际的会议音频,因此有必要准确说明离开您的机器的内容和不离开的内容。转录提供商是 [Soniox](https://soniox.com);以下事实基于 Soniox 的已发布服务条款和隐私政策(两者最近于 2026-06-29 更新)。`docs/soniox-data-processing.md` 包含完整的说明和来源。
- **捕获的内容。** 每会议两个本地音频音轨:您的麦克风(`raw/mic.wav`)和会议应用程序的系统音频(`raw/system.wav`)。当通话应用程序开始捕获您的麦克风时,录音自动开始。
- **离开您的机器的内容。** 两个服务之间的流量,其他内容均不发送。两个音频音轨上传到 Soniox 的异步语音转文本 API(默认端点 `api.soniox.com`),每个请求携带识别提示 - 会议标题、与会者姓名和学习词汇库术语 - 以便 Soniox 正确拼写它们。如果您连接 Google 日历,会议标题和与会者姓名从中读取。只读连接器本地为代理提供服务,不会发送任何内容。
- **训练和二次使用。** Soniox 在其具有约束力的服务条款和隐私政策中承诺,不使用客户内容“训练、微调、评估、基准测试或改进”其模型或服务,也不将其出售。 这是默认设置;无需选择加入。
- **保留。** 异步 API 是 Soniox 的存储服务:上传的音频和生成的转录文本存储在服务器端,无自动删除,因此清理是调用者的责任。每次运行后,管道删除存储的转录文本,这也删除上传的音频文件,因此在正常操作下,音频和转录文本均不会被 Soniox 保留。(删除是尽力而为:失败会被记录,不会失败运行。对于单个文件 `tamlil-transcribe` 运行,`--keep-remote` 跳过它。)
- **数据驻留。** 由于管道调用默认 `api.soniox.com`,音频和转录文本在美国处理和存储,除非明确请求和配置了区域性 Soniox 项目(欧盟或日本)。
- **法律依据。** 使用受 Soniox 的自行提供的服务条款和隐私政策管辖。数据处理协议和 HIPAA BAA 可通过 Soniox 控制台获得,但不是自动的 - 除非接受了某个帐户,否则两者都不生效。
- **日历范围。** 名册查找是只读且可选的。它请求单个范围 `https://www.googleapis.com/auth/calendar.events.readonly` 并仅读取会议标题和与会者姓名。每用户刷新令牌存储在您的 macOS Keychain 中(`tamlil-google`);如果没有它,会议仍然会记录和转录,但没有标题或与会者姓名。
- **本地存储。** 录音、转录文本和学习词典存储在您的 Mac 上 - 录音存储在 `~/Recordings/Tamlil/<recording-id>/` 下,学习词典存储在存储库根目录下。Soniox API 密钥存储在 Keychain(`tamlil-soniox`)中,从不存储在文件中。连接器以只读方式打开录音数据库。
- **删除。** 要本地删除录音,请在 `~/Recordings/Tamlil/` 下删除其目录。在 Soniox 上,上传的音频和存储的转录文本在每次运行后自动删除,因此在正常操作下,无需手动删除任何内容。
要报告安全问题,请参阅 [SECURITY.md](SECURITY.md)。
### 录音同意
Tamlil 一起记录您的麦克风和会议应用程序的系统音频,因此每个参与者的声音都被捕捉到。录音对话受电线窃听和偷听法律的管辖,这些法律根据管辖范围的不同而有所不同。
- **您负责获得同意。** Tamlil 是一个本地工具,代表您进行记录。运行它的人员 - 而不是项目的作者和软件 - 有责任从通话中的每个人那里获得法律要求的同意,并在录音开始之前获得。
- **全党 vs. 单方面。** 管辖范围不同,对参与者同意的要求也不同。在单方面管辖范围(美国大部分地区)中,您自己的同意就足够了。在全党管辖范围 - 通常称为两党 - 每个参与者都必须同意:加利福尼亚州要求对私人通信的同意(刑法第 632 条),欧盟通常要求根据 GDPR 和国家法律的合法依据和参与者的同意。跨越边界的通话可能会使您受到适用于其中任何人的最严格规则的约束。
- **不是法律建议。** 以上是一般信息,而不是法律建议,并且不详尽。同意规则因国家、州和上下文而异,并且会随着时间的推移而变化。请在录音前检查您自己的司法管辖区和每个参与者的司法管辖区的法律,并获得自己的法律建议。
## 开发者
Tamlil 是两个共享录音数据库的半部分:`Tamlil/` 中的 SwiftUI 菜单栏应用程序和 `src/tamlil/` 中的 Python 转录管道(通过 `uv` 运行)。以下命令假设安装程序在 `$HOME/Library/Application Support/Tamlil/repo` 处创建的存储库;如果您在其他地方克隆了存储库,请替换您的路径。
```bash
REPO="$HOME/Library/Application Support/Tamlil/repo"
cd "$REPO"
```
### 手动运行管道
```bash
uv run tamlil-pipeline ~/Recordings/Tamlil/<recording-id>
```
麦克风音轨以您的 macOS 名字命名;可以使用 `--me-name` 覆盖。转录单个文件 `uv run tamlil-transcribe path/to/audio.wav`。如果运行失败,音频会保存在 `raw/` 下;修复原因(通常是 Soniox 密钥或余额)并重新运行;`--skip-transcribe` 重用现有的合并并且只重新执行廉价的本地阶段。
管道,按顺序:查找会议名录并构建识别上下文;可选地对麦克风音轨进行降噪;同时转录两个音轨;按时间戳合并并标记发言者;从系统音轨中抑制麦克风回声;应用学习词典重写;从低置信度范围保存澄清卡并写入 `final/transcript.{json,md}`。
### 从 AI 代理读取会议
连接器(MCP 服务器)是只读的,访问录音数据库和转录文件,公开 `list_meetings`、`get_meeting`、`get_transcript` 和 `search_transcripts`。安装程序为您注册了它与 Claude Code;要手动添加:
```bash
claude mcp add tamlil -- uv run --project "$REPO" tamlil-mcp
```
对于 Codex (`~/.codex/config.toml`),请指向绝对路径:
```toml
[mcp_servers.tamlil]
command = "uv"
args = ["run", "--project", "/Users/<you>/Library/Application Support/Tamlil/repo", "tamlil-mcp"]
```
它遵循 `TAMLIL_DB_PATH` / `TAMLIL_RECORDINGS_ROOT` 覆盖并且永远不会写入 - 数据库以只读方式打开。
### 录音存储
每个录音都是 `~/Recordings/Tamlil/<recording-id>/` 下的一个目录:`raw/` 包含捕获的 `mic.wav` 和 `system.wav`;`work/` 包含管道中间件(降噪音频、音轨转录、合并草稿、回声报告);`final/` 包含 `transcript.json` 和 `transcript.md`;`logs/` 包含管道日志。`transcript.json` 保存分段文本、发言者分割、语言 ID、单词计时和置信度、低置信度范围和回声报告。
### Google 日历设置(自带 OAuth 客户端)
日历功能 - 会议标题和与会者姓名,也作为识别器提供上下文 - 是 **可选** 的,直到您注册自己的 Google OAuth 客户端并指向 Tamlil(Tamlil 不附带自己的)。这是一个五分钟的一次性设置:请参阅 ** [docs/google-calendar-setup.md](docs/google-calendar-setup.md)**。
### 源代码交付
Tamlil 从源代码构建和安装,而不是作为已签名的二进制文件提供。有两个故意的设计:
- **临时代码签名。** `Tamlil/build.sh` 使用 `codesign --sign -`(无开发者 ID,无认证)签名应用程序。因为您自己构建它,所以 macOS 运行它时不会有 Gatekeeper 绕过,并且麦克风和系统音频权限授予 - 绑定到 bundle id - 只要签名保持一致,每次重建后都有效。
- **拉取和重建更新器。** **检查更新** 运行 `scripts/update.sh`,它将最新的源代码拉取到您的存储库,重建、重新安装并重启。没有 Sparkle 源或单独的更新频道可供信任;您可以阅读的源代码就是运行的源代码。
因为应用程序从您的存储库运行,所以其存储库路径是一个首次运行设置(**设置 → 管道 → tamlil 存储库**);安装程序为您设置它。
### 故障排除
- **无权限提示 / 静默录音** - 检查 Tamlil 是否在系统设置 > 隐私和安全 > 麦克风和系统音频录音下启用,然后重启。授予权限绑定到 bundle id,如果它更改,则需要重新批准。
- **`swift build` 立即失败** - 使用 `xcode-select --install` 安装或更新命令行工具;构建需要 CLT 16+(Swift 6)。`swift test` 不受支持(软件包未定义测试目标);使用 `make test-swift`,它运行应用程序的内置自我检查。
- **会议上的管道错误** - 音频保存在 `raw/` 下;修复原因(通常是 Soniox 密钥或余额)并重新运行 `uv run tamlil-pipeline <dir>`。
- **空名录 / 无会议标题** - 运行 `uv run tamlil-auth` 连接您的 Google 账户;请参阅上面的 Google 日历设置。
### 贡献和堆栈
请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。堆栈:`uv`(Python 3.12)、Soniox `stt-async-v5`、`requests`、`numpy`、`static-ffmpeg`、SwiftUI 和 SQLite。
## 许可证
Apache-2.0 - 请参阅 [LICENSE](LICENSE)。捆绑的第三方组件在 [NOTICE](NOTICE) 和 [THIRD_PARTY_LICENSES](THIRD_PARTY_LICENSES) 中有说明。