← 多模态与文档智能

转写出来的说话人标签怎么对应到真人?转写错字怎么人工修订?

中等 语音转写与说话人分离 · 第 2 / 2 问 更新于 2026/09/29
说话人分离说话人识别语音转写人工校对会议纪要
本题落地项目AI Agent智能会议纪要辅助系统

简化版

说话人分离只回答「哪几句是同一个人说的」,给出的是 0、1、2 这样的编号,不回答「这个人是谁」。把编号对到真人有三条路:人工指认、声纹注册后比对、按发言内容推断(点名、自我介绍、职务相关的话题)。不管走哪条路,写库都应该按标签整批写,一个标签选一次人;候选范围收窄到这场会议的参会人员;机器给出的只是建议,最后由人确认。

转写错字的修订要保留模型原文:原文一份不动,另存一份可修订的文本,并记下谁在什么时候改的。下游的全文、纪要、检索统一读修订后的文本,改了之后由它派生的数据要跟着刷新;原文留作对照,也能用来统计转写质量。

详细版

办法前提优点局限
人工指认有人愿意听几句、选个人最准,不需要额外数据标签多、会议多时费人工
声纹比对事先采集每个人的声纹全自动,跨会议稳定要注册声纹,涉及生物特征隐私;换设备、感冒会漂移
内容推断发言里有点名、自我介绍不需要声纹,能给出依据依赖会议里有线索,只能作为建议

数据上分两层:

说话人层  分离标签(分离给的编号,不再改动)-> 匹配到的人(可为空,可解除)
文本层    模型原文(写入后不再改动)
          当前文本(页面展示、人工修订、下游读取的都是它)
          最后修订人、最后修订时间

落地要点:

  1. 按标签整批匹配,选一次人,这个标签下的全部句子一起更新;清空即解除。
  2. 候选只来自参会人员名单,前端下拉和后端校验两道都要有。
  3. 切段转写时,同一个人在不同分段是不同标签,要分别匹配或跨段合并。
  4. 修订只改可修订文本,原文不动,全文等派生数据随之重算。

完整版教学

一、分离和识别是两件事

说话人分离(Diarization)回答「谁在什么时候说话」里的「谁」,但它的「谁」是匿名的:模型把声音特征相近的句子聚成一类,按出现顺序编号。说话人识别(Identification)才回答「这个声音属于张三」,它需要事先知道张三的声音长什么样。

任务输入输出需要提前准备
说话人分离一段多人音频每句的匿名编号不需要
说话人识别一段音频 + 已注册的声纹库每句对应的具体身份每个人的声纹样本

会议场景里,识别接口一般只提供分离。编号只是一个类别,纪要要写「张三提出」「李四反对」,就必须再做一步:把编号对到真人。

二、把标签对到真人的三条路

人工指认最直接:页面列出每个标签和它的几句发言,由人选出这是谁。准确率最高,成本是人工时间。

声纹比对把每个标签的音频提取成声纹向量,和已注册的声纹库算相似度,超过阈值就认定。它全自动,但前提重:每个人都要事先录一段声纹,而声纹属于生物特征信息,采集、存储、删除都要合规;同一个人换了麦克风、在嘈杂会议室、嗓子哑了,相似度都会下降。

内容推断让大模型读带标签的发言,从线索里推断身份:主持人说「下面请小周讲一下进度」,紧接着开口的标签多半就是小周;「我是财务部的刘洋」是自我介绍。它不需要声纹,还能给出判断依据,但线索不一定有,推断也可能错,只适合作为给人看的建议。

实际系统常常组合使用:模型或声纹先给建议,人确认后才写库。

三、按标签整批,而不是逐句

一小时的会议可能有 600 句、5 个说话人。逐句指认要选 600 次;按标签指认只要选 5 次,选一次就把这个标签下的一百多句一起更新。

逐句:600 句 × 每句 1 次选择 = 600 次
整批:5 个标签 × 每个标签 1 次选择 = 5 次

整批的前提是分离结果可信:同一个标签下确实是同一个人。分离也会出错,比如两个声音相近的人被聚成一类,或一个人被拆成两类。后一种情况按标签分别指认到同一个人就能合并;前一种情况整批匹配会把另一个人的话也算过来,需要逐句改说话人的能力兜底,代价是多一套逐句覆盖的数据结构。

四、候选范围为什么要收窄

公司通讯录可能有几千人,下拉框里全部列出来,选错的概率和查找成本都很高;让模型推断时,名单越长越容易编出一个看似合理的人。把候选限定在这场会议的参会人员,通常只剩几个到十几个。

收窄要前后端各做一次:前端下拉只列参会人员,是为了好选;后端再校验提交的人确实是这场会议的参会人员,是因为请求可以绕过页面直接发,不校验就可能把发言记到一个无关员工头上。模型给出的推荐同样要按名单过滤一遍,名单以外的人直接丢掉。

五、切段转写带来的标签不一致

长录音常常切成若干段分别识别,而分离是在每段内部做的,每段的编号都从 0 开始。于是同一个人在第 1 段是 01-0,在第 2 段可能是 02-1:

标签发言片段数实际是谁
01-042张三
01-135李四
02-038李四
02-140张三

处理办法有两种:一是把四个标签都列出来,人分别指认,张三选两次、李四选两次;二是跨段比对声纹,自动把 01-0 和 02-1 合成一类。前者简单可靠,后者省人工但依赖声纹质量。无论哪种,都不能因为编号相同就直接合并 01-0 和 02-0。

六、人工修订:原文和修订稿分开存

转写总会有错字,尤其是人名、产品名、专业术语。修订时如果直接覆盖模型输出,会丢掉三样东西:

丢掉的后果
模型原文无法对照改了哪里,改错了也回不去
修订人和时间出了争议不知道是谁改的
原文与修订的差异无法统计转写模型到底错了多少

所以每句转写存两份文本:模型原文写入后不再改动,当前文本是页面显示和人工修订的那一份,同时记下最后修订人和修订时间。下游一律读当前文本,原文只用于对照。

七、修订之后,派生数据要跟着刷新

转写句子往往还派生出别的数据:按顺序拼好的全文、基于全文生成的纪要、切片后写进向量库的索引。修订了一句话,这些派生数据就过期了:

修订一句 -> 按序号重新拼接全文(立即)
         -> 已生成的纪要:不自动改,重新生成时才读到新文本
         -> 检索索引:对应片段重新向量化

哪些立即刷新、哪些等下次重新生成,要按代价定:重拼全文只是字符串拼接,可以每次修订都做;重新生成纪要要调模型,还可能覆盖人工确认过的内容,应该由人决定什么时候做。

八、用修订衡量转写质量

保留原文之后,原文和修订稿的差异就是一份现成的人工标注。中文常用字错误率(CER)衡量:

CER = (替换 S + 删除 D + 插入 I) ÷ 参考文本字数 N

以修订稿为参考文本、模型原文为识别结果。例如原文「下周三把借口联条完」,修订为「下周三之前把接口联调完」,参考文本 11 个字:「借」改「接」、「条」改「调」是 2 处替换,原文漏掉的「之前」是 2 处删除,CER = (2 + 2 + 0) ÷ 11 ≈ 36%。

心法:分离给编号,匹配给身份,修订给正确的文本。三件事各存各的字段,谁也不覆盖谁:分离标签不改,模型原文不改,变的只有「匹配到的人」和「当前文本」。

按会议、按说话人统计修订率,能发现哪类场景转写最差,比如某个会议室的麦克风、某个口音重的发言人。

九、常见误区与追问

  • 误区:打开了说话人分离,就知道每句话是谁说的。 分离只给匿名编号,身份要靠人工指认、声纹比对或内容推断。
  • 误区:不同分段里编号相同的标签是同一个人。 编号在每段内部独立,01-0 和 02-0 可能是两个人,同一个人也可能是 01-0 和 02-1。
  • 误区:模型推荐的人直接写库,省掉人工。 内容推断依赖线索,可能错;推荐只作为建议,确认后才写库,名单外的推荐要过滤掉。
  • 误区:候选范围只在前端下拉框里限制就够了。 请求可以绕过页面,后端必须再校验提交的人是这场会议的参会人员。
  • 误区:修订时直接覆盖模型输出。 原文丢了就没法对照、回退和统计错误率,原文和修订稿要分开存。
  • 追问:分离把两个人聚成了一个标签怎么办? 整批匹配会把另一个人的话也算过来,需要支持逐句改说话人;这种情况多发生在声音相近、发言很短的人身上。
  • 追问:为什么不直接上声纹识别? 要事先采集声纹,涉及生物特征的采集和存储合规;设备、环境变化还会让相似度漂移,适合固定成员、固定会议室的场景。

十、加强记忆

先分清两个词:分离给匿名编号,识别给身份,会议转写默认只有分离。编号对到真人有三条路:人工指认最准,声纹比对全自动但要注册、有隐私负担,内容推断靠点名和自我介绍、只能当建议。写库按标签整批,一小时 600 句、5 个人,选 5 次而不是 600 次;候选收窄到参会人员,前端限制、后端校验、模型推荐按名单过滤三道。切段转写时同一个人在各段标签不同,01-0 和 02-1 可能是一个人,01-0 和 02-0 可能是两个人。修订存两份:原文不动,修订稿给下游用,记下修订人和时间;修订后全文立即重拼,纪要和索引按代价决定何时刷新;原文和修订稿的差异算 CER,就是现成的质量统计。

录音怎么切段转写、时间轴怎么拼、标签为什么带段号,见「会议录音怎么转写成带时间轴和说话人的文本?长录音怎么分段处理?」。

项目实战落地

项目里怎么做的

《AI Agent智能会议纪要辅助系统》在转写完成后的详情弹窗里放了两张表:上面是说话人表,下面是时间轴表。

  • 说话人汇总。 详情接口把片段按标签归并,统计每个标签的发言片段数;表格顺序是各标签在时间轴上第一次出现的顺序。
  • 按标签整批匹配。 在某个标签那一行的下拉框里选一位参会人员,这个标签下的全部片段一次写入同一个 speaker_user_id;清空下拉框就是解除匹配:
# 圈定这个任务下、这个标签的全部片段
label_query = TranscriptSegment.filter(task_id=task.id, speaker_label=payload.speaker_label)
if not await label_query.exists():
    raise CustomException("说话人标签不存在")
# 传了用户时校验他确实是这场会议的参会人员,不能匹配到无关员工
if payload.user_id is not None:
    if not await MeetingParticipant.filter(meeting_id=task.meeting_id, user_id=payload.user_id).exists():
        raise CustomException("只能匹配该会议的参会人员")
# user_id 为 None 时相当于把这批片段的匹配清空
await label_query.update(speaker_user_id=payload.user_id)
  • 跨段分别匹配。 录音超过 20 分钟被切成多段时,同一个人在不同分段里是不同的标签(例如 01-0 和 02-1),说话人表格里是两行,需要分别匹配。
  • 时间轴显示。 说话人列匹配前显示「说话人 01-0」,匹配后显示姓名。不想逐个去听的,可以点「AI建议匹配」让模型读发言内容推荐人选,做法见「如何估计大模型回答的置信度?」。
  • 逐条修订。 时间轴每一行都有「修订」按钮,修订只动三列:
字段修订时
original_text不动,始终是模型的原始输出
content改成新文本,页面展示的就是它
revised_by、revised_time记下当前用户和修订时间

每次修订之后,按顺序号把全部片段的 content 重新拼接,覆盖转写任务上的全文 full_text。

为什么这样取舍

  • 分离只知道哪几段是同一个人。 模型认不出这个人是谁,标签只是编号,所以要人来对上参会人员。
  • 一个标签选一次。 同一个音频分段里,同一个人的发言被标成同一个编号,选一次就更新这个标签下的全部片段。
  • 原文留着对照。 original_text 写入后不再改动,用于和修订后的文本对照;页面和后续环节用的都是 content。
  • 全文跟着片段走。 全文是由片段拼出来的,片段改了不重拼,读全文的环节看到的还是旧文本。

面试官还会追问

  • 匹配下拉框里的候选人员是怎么取的?已经停用的账号会出现吗?
  • 匹配请求被后端拒绝时,页面上已经被改掉的下拉框怎么恢复成数据库里的值?
  • 转写任务还在执行时能修订片段吗?为什么?

学完《AI Agent智能会议纪要辅助系统》,上面这些追问你都会迎刃而解。

本题落地项目地狱锤炼AI Agent智能会议纪要辅助系统基于LangChain+LangGraph的AI Agent智能会议纪要辅助系统 包括会议管理 资料管理 音视频转写 说话人分离 会议纪要生成 Agent自检更正 Agent运行观测等。FastAPILangChainLangGraphAgent多模态源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目