HTTP 200 不等于转写成功:会议录音的验收清单
一次请求返回了文本,离“这份会议记录可以交给同事”还有多远?把 ASR 接进字幕、会议纪要或按说话人剪辑时,需要分别验收内容、说话人、时间和处理完整性。下面用 FunASR 的 MOSS 结果讲清这些层次,并提供一个只依赖 Python 标准库的结构检查脚本。

先分清四个问题
| 检查层次 | 要回答的问题 | 不能用什么代替 |
|---|---|---|
| 请求与结构 | 请求完成了吗?字段、单位、顺序是否符合约定? | HTTP 200、非空 JSON 不能证明内容正确。 |
| 文本 | 名字、数字、否定词和关键决策是否转对? | 语句流畅不能证明没有漏句或幻觉。 |
| 说话人 | 每次轮次和重叠发言分给了谁? | 输出了两个标签,不等于两位人物分得正确。 |
| 时间与覆盖 | 字幕能定位到正确声音吗?开头、中段和结尾有无遗漏? | 最后一个时间戳接近总时长,不等于全程转写完整。 |
三项常见混淆值得单独拆开。VAD 检测哪些时间段可能有语音;ASR 给出说了什么;说话人分离(diarization) 给匿名说话人划分发言区间。它们不是同一个评测目标。S01 是当前录音内的标签,不是姓名、已注册声纹或跨录音身份。
给应用选对输出,而不只是选模型
MOSS-Transcribe-Diarize 是 OpenMOSS 维护的第三方模型。FunASR 集成把它的输出整理成文本和带匿名标签的时间段;采用这条路径不需要再外接 VAD 或说话人模型。不要为了“加上 VAD”先把会议任意切成独立请求,然后假定每段的 S01 都是同一个人。
- 整句字幕或说话人片段:段级时间戳是合适的接口,但仍须回听边界与说话人轮次。
- 逐字高亮或任意文本精确剪辑:段级时间戳不够。选择有对应字/词对齐输出的路径,例如检查 Paraformer 的时间戳能力与适用语言,不能把一句话的时长平均分配成“准确字时间”。
- 会议纪要:先保留可回溯的原文、匿名标签与时间段,再生成摘要;错误的人名、数字或决策不能靠摘要模型自动修复。
具体服务版本和安装命令集中维护在 MOSS 部署页及 集成指南。本文不另写一套会随版本漂移的安装流程。FunClip 的能力与限制见 说话人剪辑实践;模型选型从 模型页进入。
一个能自动化、但不冒充质量评估的检查器
下载 transcript-audit.py,也可以直接阅读源码。它只读文件,不访问网络,不修改转写结果。输入是 FunASR AutoModel.generate(...)[0] 的单个 MOSS 结果对象,或仓库离线示例写出的 .moss-vllm.json;不是原始 vLLM diarized_json、SRT,也不是 Qwen3 示例的 segments 格式。
以下是人为构造的 12 秒录音结果,不是真实模型输出,也没有准确率含义:
{
"text": "Let's start. Agreed.",
"sentence_info": [
{"start": 1000, "end": 3500, "spk": "S01", "text": "Let's start."},
{"start": 6000, "end": 8000, "spk": "S02", "text": "Agreed."}
]
}
把示例 JSON 作为 result.json。检查器使用毫秒,12 秒应传 12000,不是 12:
python3 transcript-audit.py result.json --duration-ms 12000
输出的 segment_count 是 2,last_end_ms 是 8000,tail_not_covered_ms 是 4000。quality_verified 始终为 false:程序没有听过音频,更没有人工参考答案,因此不能给出质量通过证书。Python 3.12 下的合成样例、非法字段和命令行行为有回归测试;它们验证检查代码,不验证模型。检查器选择拒绝零长度段,这是本文应用验收的额外约束,不表示模型适配器承诺所有时间段都大于零。
- 缺少
sentence_info、非数值/无穷时间、反向、零长度或超出录音范围的区间会报错并以非零状态退出。 - 空文本、开始时间乱序和区间重叠会列出从 0 开始的下标,保留原始结果以便检查。重叠可以是真实抢话,不能直接删除;检查器按开始时间排序判断相交,列出与先开始区间相交的片段原始下标;边界相接不算重叠。
- 空结果会显式显示 0 段和完整的未覆盖尾部。静音录音可能合理,会议录音则需要核验输入或服务结果。
- 尾部差值只是“最后一个输出区间到录音终点”的时间,既不是漏识别时长,也不是语音召回率。中间即使漏掉一句话,这个值也可能是 0。
从结构检查走到人工验收
- 固定输入和配置。保留原音频散列、时长、采样率/声道、模型 revision、服务版本、请求格式和生成上限。记录重采样、混音与裁剪;裁掉静音后必须保存偏移映射,否则时间戳无法回到原视频。
- 回听高风险位置。开头与结尾、长静音两侧、说话人交替、重叠发言、低音量以及关键数字。抽查能发现问题,但抽查通过不等于整段准确。
- 把文本与说话人分开评估。有人工参考转写时,可按统一的标点、大小写及分词规则计算 CER/WER;有人工说话人时间标注时,再使用说话人指标。不要把“输出了两个标签”作为 diarization 的通过条件。
- 冻结说话人评测口径。pyannote.metrics 提供说话人错误率等指标;边界宽容区间(collar)和是否计入重叠语音会影响结果。比较系统时必须使用同一标注与配置,指标数字不能脱离这些前提。
- 完整性异常先定位,再调参。检查响应是否因生成上限中止、结构是否完整、客户端是否漏读。增大 token 上限只可能缓解某些截断,不保证召回;不能用“接口正常返回”关闭用户的问题。
上线前留下什么
遵循授权范围和保留期限,只保存必要的数据,并限制对录音与说话人标注的访问。一份可复查的交付应包含原音频标识、固定配置、原始结果、结构报告和人工确认记录。会议纪要保留到原文的回链;字幕检查可读性、定位及隐私;剪辑回看实际片段,不能只看时间段长度。涉及已知人物身份时另行设计授权、登记和验证流程,不把匿名聚类标签改名后当作身份识别。
这篇文章的检查器是进入验收流程的第一道结构检查,不是模型排行榜,也不会替代回听与标注。下一步可以沿 部署中心跑通实际工作负载,再到 FunASR 仓库查看实现或提交带最小复现的问题。
来源与复现入口
- OpenMOSS 模型项目:模型归属与任务定义;固定 revision 的模型卡解释匿名标签。
- 本文检查的离线结果文件契约:固定仓库提交,MOSS 分支写出单个结果对象。
- pyannote.metrics 官方实现:说话人指标与评测配置。本文没有运行或报告 DER/CER/WER。