会议与转录
Control Center 可以录制通话,并交回一份整洁的成稿——摘要、待办事项和决策——语音识别和说话人分离都运行在你自己的硬件上。可以把它想成 Granola,但由你自托管,并接入你的智能体所处的同一个工作区。
会议是什么
标题为“会议是什么”的部分会议是一次被录制并转写的会话。它与日历日程并不相同:日程是从 Google 同步来的既定安排,而会议是你实际录制下来的内容。两者可以关联——你可以从某个日程开始录制——但它们仍是彼此独立的记录。
和 Control Center 里的其他一切一样,每场会议都以工作区为范围。在一个工作区里录制的会议绝不会出现在另一个工作区中。
工作发生在哪里
标题为“工作发生在哪里”的部分“设备端”这个直觉没错,但用的名词不对。客户端采集音频,把 16 kHz PCM16 帧流式发送到运行 cc_server 的那台机器。其余一切都由那台主机完成:把各声道的 WAV 写到 <dataDir>/meetings/<meetingId>/ 下,在工作进程隔离区中转写,事后过滤回声并做说话人分离。在单机桌面上,那台主机就是同一台机器;指向远程服务器时则不是——所以“什么都不离开我的笔记本电脑”只在服务器就是你笔记本电脑时才成立。
还有一处例外,而且恰恰是最重要的那处。
摘要之前的一切——采集、转写、回声消除、说话人分离、声纹匹配——都在服务器上运行,不发生任何网络调用。
随附哪些模型
标题为“随附哪些模型”的部分嵌入、说话人分离和语音(ASR)模型会在首次启动时强制安装(演示模式下跳过),因此无需进入设置就能使用说话人分离和录制。ASR 仍然可选——它有几百兆,选择器里提供四种构建。首次下载后,语音功能仍需要一次重启,因为转写器会在下载完成之前就解析好它的模型。
选择器中的四项,在体积、语言覆盖和准确度上各有不同:
- Parakeet TDT 0.6B v3 —— 多语言,推荐的默认项(约 600 MB)
- Parakeet TDT 0.6B v2 —— 英语(约 480 MB)
- Whisper large-v3-turbo —— 多语言(约 626 MB)
- Whisper base.en —— 仅英语,体积较小的历史默认项(约 198 MB)
模型是服务器在运行时唯一会拉取的产物;所有原生库都随安装包一起提供。
采集如何工作
标题为“采集如何工作”的部分会议会同时录制两个音频声道:
- 你(“me”):你的麦克风。
- 对方(“them”):会议的音频输出,通过免驱动的环回采集——macOS 上是 Core Audio 的进程/设备 tap,Windows 上是 WASAPI 环回,Linux 上是 PipeWire / PulseAudio 监听。
由于两个声道是分别采集的,转写从一开始就带有说话人归属:你说的话标记为 me,通话中的其他人标记为 them。
你自己的声音会从系统输出串回麦克风,否则会被转写两次。有两道过滤器阻止这一点。信号级的 AEC3 会在每次远程模式录制中运行,并且是必需的——如果原生 AEC 库无法加载,录制会拒绝启动,而不是默默地把被回声污染的麦克风流式送出。(面对面模式没有远端参考可供抵消,因此那里的 AEC 只是原样透传。)在此之上,主机侧还有一道文本级回声过滤器,在所有平台上都会运行。
操作系统层面的所有麦克风处理都被有意禁用。在 macOS 上启用系统自带的回声消除或自动增益会让麦克风切换到 Voice Processing I/O,而在当前构建中,这会让麦克风_和_系统音频 tap 双双失效。
转写与说话人分离
标题为“转写与说话人分离”的部分录制期间,音频会在 UI 线程之外以滚动窗口的方式解码——窗口在尾部出现短暂静音时切分,或达到最大窗口长度时切分。每个窗口都会变成一段带说话人标记的转写片段,并带有毫秒级偏移量。
从未超过某个 RMS 阈值的窗口会被完全跳过、不做解码,因为语音模型会把静音渲染成幻觉出的非语音 token,白白浪费 CPU。实际后果是:一直很轻的说话人不会产生任何转写。如果某个人一直是空白,先检查他的输入电平,再怪模型。
停止之后,说话人分离会离线地在整段录音上运行,把远端声道拆分成一个个可重命名的说话人(Person 1、Person 2……)。说话人数量是根据聚类阈值推断出来的,而不是你设定的数目——因此它只是阈值带来的产物,一个声音轻或与他人重叠的说话人可能会被并进相邻的那位。转写会渲染成 [mm:ss] SPEAKER: text 这样的行。
声纹档案
标题为“声纹档案”的部分重命名说话人不只是给一段转写贴上标签。Control Center 可以把说话人的声纹保存为一个声纹档案,这样它就能在之后的会议中自动识别此人。当你给一个经说话人分离的说话人命名时,系统会询问你是否保存声纹;如果保存,它会被融入该名字对应的一个持续累积的质心,并在遇到新说话人时用余弦相似度进行匹配,因此同一个人下次出现时会直接带上名字,无需你重新标注。
声纹档案以工作区为范围,绝不会越界。可在设置 → 工作区 → 会议中管理它们。重命名一个此前已保存的说话人会注销旧名字,并询问是否登记新名字;删除档案会移除已存储的声纹,但之前已经应用到过往会议上的名字会原样保留。
摘要流水线
标题为“摘要流水线”的部分录制停止时,服务器会发布一个 MeetingRecordingStopped 领域事件。内置的 meeting_summary 流水线模板由该事件触发。录制器不会等它;会议只是经历自己的状态生命周期:
recording → processing → done总结智能体会收到标题、你随手记的实时笔记和转写内容,并返回结构化 JSON。它写哪些小节,由工作区的当前会议笔记模板(设置 → 工作区 → 会议)决定;当前模板会应用于新建和重新生成的摘要。随后,流水线的持久化步骤会把这份 JSON 写入一条条独立的记录:
enhancedNotes和summary→ 会议的笔记- 每个待办事项 → 一行
MeetingActionItem(内容、负责人、可选的工单链接) - 每个决策 → 一行
MeetingDecision
待办事项和决策绝不会从自由形式的 Markdown 中解析出来,只会取自智能体的结构化数组。如果某次运行没有产生结构化输出,持久化步骤会被跳过,原始转写会作为兜底保留下来,因此你永远不会丢失这份记录。流水线中没有任何环节会把会议标记为 done——那是由一个单独的对账器根据运行的终止事件来完成的,这样即便某个兄弟步骤失败,也不会让一场已经看起来完成、实际却只写了一半的会议卡在那里。
会议会出现在哪里
标题为“会议会出现在哪里”的部分| 界面 | 显示内容 |
|---|---|
/meetings |
会议列表,含待办事项和决策的数量 |
/meetings/record |
实时录制 HUD:一侧是你的笔记,另一侧是流式转写 |
/meetings/:meetingId |
会议的详情:笔记、转写、待办事项和决策标签页 |
| 设置 → 工作区 → 会议 | 此工作区的笔记模板和已保存的声纹档案 |
平台支持
标题为“平台支持”的部分在三大桌面平台上,采集都是免驱动的(macOS 上是 Core Audio tap,Windows 上是 WASAPI,Linux 上是 PipeWire)。
Web 客户端也能录制,本页其余部分以桌面为主的叙述可能会掩盖这一点:浏览器通过 getUserMedia 获取你的麦克风,并通过 getDisplayMedia(屏幕共享)获取会议音频,降采样到 16 kHz PCM16 后流式发送到同一台主机。这里有三个注意事项:
- 共享的界面必须带有音轨。Safari、Firefox 和 macOS 的全屏共享不会提供音轨,录制会直接拒绝启动。
- 没有原生 AEC3。会对麦克风请求浏览器自带的回声消除;主机侧的文本回声过滤器仍会运行。HUD 会显示一个由麦克风 PCM 驱动的输入电平表。
- 重新生成摘要和取消处理仅在桌面端可用。
日历的录制并链接操作仅在桌面端可用,在 Web 上会如实说明这一点,尽管会议界面自己的录制流程在 Web 上可以正常工作。