内容
# 语音笔记
**中文** · [English](README.md) · [日本語](README.ja.md)








> 首页 → 会议的 3 层总结 → 跨会议知识图谱。
> _(以占位演示数据显示。)_
独立的本地语音笔记,从 [`type-by-voice`](https://github.com/kotaro-nakata/type-by-voice) 中提取。
该工具记录或导入音频,本地使用 `faster-whisper` 转录,并写入:
- `transcript.md`
- `notes.md`
- `summary.md`
- `audio.wav`
- `meta.json`
它不执行全局按键说话式听写,托盘 UI 或将文本粘贴到聚焦的应用中。这些仍然是 [`type-by-voice`](https://github.com/kotaro-nakata/type-by-voice) 的责任。
## 设置
需要 Python 3.11+。
```bash
cd voice-notes
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
```
运行 Web 界面:
```bash
./record-notes
```
默认页面是 <http://127.0.0.1:8765>。它可以启动/停止录音,上传音频文件,导入 macOS 语音备忘录,并下载生成的 文件。
三层严格按顺序运行 — 第 1 层 → 第 2 层 → 第 3 层:
- 第 1 层:原始分段转录,实时写入每个音频段完成时。其他层必须等待整个转录完成。
- 第 2 层:当第 1 层完成后,整个转录被一次性交给本地 Ollama 模型,生成按主题分组的详细全文摘要(决策,数字,名称,待办事项,开放问题)。对于模型上下文过长的转录,内部会将其分成几个大块并合并 — 在输出中不可见。
- 第 3 层:第二层的完整摘要再次被压缩成一页笔记: 一句话结论 / 核心要点 / 行动待办 / 检查点。
`summary.md` = 第三层一页总结,接着是第二层完整摘要。`notes.md` 显示所有三层。
第 2/3 层需要一个 LLM。后端解析(`[summary] backend = "auto"`):
1. 如果设置了 `openai_url` 并可访问,则使用兼容 OpenAI 的服务器 — 例如,通过 Tailscale 在更大的机器上运行 LM Studio(`openai_url = "http://100.x.x.x:1234/v1"`;空 `openai_model` 使用服务器报告的第一个模型)。
2. 否则使用本地 Ollama(`ollama_url`,`ollama_model`)。
3. 否则使用基于规则的抽取式回退(效果要差得多)。
对于上传/导入的音频,列表和会话页面显示转换进度:转录时间,总音频时间 和 完成百分比。对于实时录音,进度将已转录部分与当前录音时长进行比较。
上传/导入的音频在 `chunks.json` 中按块检查点。如果转换被中断,请打开会话并点击 **恢复转换**;已完成的块将被重用,只有缺失的块被转录。这保持管道面向块:
```text
块 N 音频 -> 原始转录 -> 核心笔记 -> 价值/待办/检查点 -> 检查点
块 N+1 音频 -> 原始转录 -> 核心笔记 -> 价值/待办/检查点 -> 检查点
...
最终转录 -> 最终 summary.md
```
所有转录块完成后,生成最终的 `summary.md`。
## 命令
```bash
./record-notes # 启动本地 UI
./record-notes --record # 从终端录音;Enter 停止
./record-notes --import file.m4a # 导入一个音频文件并等待
./record-notes --import file.m4a --language zh
./record-notes --list-devices # 列出麦克风设备
```
有用的覆盖参数:
```bash
./record-notes --port 8770 --no-browser
./record-notes --data-dir ~/.local/share/voice-notes/sessions
```
## 知识图谱
每个完成的会话都经过知识图谱提取:相同的 LLM 从笔记中提取实体(人/项目/组织/概念/决策/待办事项)及其关系,缓存在会话的 `entities.json` 中。
`/api/graph` 聚合每个会话的 `entities.json` 成一个图 — 每个实体按名称在会话间合并,因此一个项目或人员在不同会议中重复出现,成为一个中心,链接所有提到它的会议。图以通用 `{nodes, edges}` 契约提供,由捆绑的 `graph.html` 观察者渲染(可用于任何数据源,以相同的契约说话)。
在首页(或 `/graph`)打开 **🕸️ 知识图谱** 以查看交互式力导向图:点击节点查看详细信息,双击会话节点打开,会话搜索聚焦。
为现有会话(它们在本次传递之前已创建)回填实体:
```bash
.venv/bin/python -c "import voice_notes as v, tomllib; \
c=tomllib.load(open('$HOME/.config/voice-notes/config.toml','rb'))['summary']; \
s=v.Summarizer(**{k:c[k] for k in ('backend','ollama_model','ollama_url','openai_url','openai_model','openai_api_key')}); \
import pathlib; [v.build_entities(p,s,force=True) for p in sorted((pathlib.Path.home()/'.local/share/voice-notes/sessions').glob('2026*'))]"
```
## MCP 服务器(从 Claude 读取笔记)
`voice-notes-mcp` 是一个只读 [MCP](https://modelcontextprotocol.io) 服务器(stdio),它将 voice-notes 已经生成的笔记暴露给任何 MCP 客户端 — Claude Code,Claude Desktop 等。无需运行任何操作;它读取磁盘上的会话文件夹。工具:
- `list_notes(limit=50)` — 最新会话,包含 id,标题,日期,时长,状态
- `read_note(session_id, part="summary")` — `part` 是 `summary`(一页 + 完整),`one_page`,`full`,`notes`(所有三层),或 `transcript`
- `search_notes(query, limit=20)` — 摘要/笔记中的关键词搜索
- `knowledge_graph(top=20)` — 跨会议图概览:计数,实体类型 和 最常被提及的实体及其出现会议
- `find_entity(name)` — 查找人员/项目/概念:描述,哪些会议提到它,及相关实体
添加到 **Claude Code**:
```bash
claude mcp add voice-notes --scope user -- /ABS/PATH/voice-notes/voice-notes-mcp
```
添加到 **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"voice-notes": {
"command": "/ABS/PATH/voice-notes/voice-notes-mcp"
}
}
}
```
它读取与应用程序相同的数据目录;使用 `--data-dir DIR` 或 `VOICE_NOTES_DATA_DIR` 环境变量覆盖。然后询问 Claude 类似的问题,如“列出我的语音笔记”,“阅读昨天的会议的一页摘要”,或“在我的笔记中搜索关键词”。
## 配置
首次运行创建:
```text
~/.config/voice-notes/config.toml
```
默认会话数据存储在:
```text
~/.local/share/voice-notes/sessions/<session-id>/
```
每个会话文件夹包含 `meta.json`,`transcript.md`,`summary.md`,`notes.md`,`chunks.json`(用于导入音频),通常还有 `audio.wav`。
默认转录语言是中文(`zh`)。在网页上使用语言选择器或 `--language auto` 进行故意混合语言的音频。自动是按块进行的:每个音频块检测自己的语言。如果置信度低,则回退到前一个块的语言,以避免短中文块被误读为英文。
## 准确性说明
该项目运行本地 Whisper,因此转录质量主要受模型,音频质量,块长度 和 模型获取的上下文影响。它不使用像 Doubao 这样的云输入方法,因此云端的中文 ASR/后处理可能更好。
默认情况下,偏好中文笔记准确性:
- 默认强制使用中文代替自动语言检测。
- 导入音频使用更长的块,以便中文口语有更多上下文。
- 每个块接收最近的前面转录作为上下文。
- `beam_size` 默认值为 `8`。
如果您想要更高的准确性,并且可以接受更慢的速度,请编辑 `~/.config/voice-notes/config.toml`:
```toml
[model]
name = "large-v3"
language = "zh"
# 或使用按块检测:
# language = "auto"
# auto_language_threshold = 0.45
[transcription]
chunk_seconds = 45.0
beam_size = 8
condition_on_previous_text = true
```
如果您想要更快的预览,请使用 `large-v3-turbo` 和更低的 `chunk_seconds`,但可能会有更多的识别错误。
## 本地摘要
摘要是本地的:
- 如果 Ollama 正在运行,`voice-notes` 使用配置的本地模型。
- 否则,它回退到内置的抽取式摘要。
该项目不使用任何云 API。
## 系统音频
Linux 扬声器捕获使用 `pactl` 和 `parec` 读取默认的 sink 监视器。在 macOS 上,扬声器捕获需要一个环回设备,如 BlackHole 和一个多输出设备。如果系统捕获不可用,则录音继续仅使用麦克风。
对于导入的文件,请在可能的情况下安装 `ffmpeg`。macOS 也可以回退到 `afconvert`。