ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Anarlog 多说话人识别全解:一段会议录音如何被拆成“谁在什么时候说了什么“

Anarlog 多说话人识别全解:一段会议录音如何被拆成“谁在什么时候说了什么“ Anarlog 多说话人识别全解一段会议录音如何被拆成谁在什么时候说了什么【免费下载链接】anarlogOpen source Granola AI Alternative项目地址: https://gitcode.com/GitHub_Trending/hy/anarlogAnarlog 是一个开源的 AI 会议记录工具定位类似 Granola其中最能体现工程含量的部分是多说话人识别——也就是语音行业常说的 speaker diarization说话人分离把一条混在一起的录音切分成0:00–0:12 是说话人 A0:12–0:30 是说话人 B这样的时间轴再挂到转写的文字上。有意思的是Anarlog 同时维护了两条管线一条跑在本地的 ONNX 模型上完全离线另一条通过自建网关代理 pyannote 云服务。下面把这两条路径拆开讲。两条管线本地离线推理与云端 API 代理先看仓库里的模块分工两个 crate 承担了全部 diarization 逻辑crates/pyannote-local/本地离线管线。代码注释里写得很直白——Mirrors the structure of the pyannote.audio 3.1 pipeline, tuned for CPU batch use即复刻了 pyannote.audio 3.1 的算法结构但针对 CPU 批处理场景做了调优在录音结束后运行而不是边录边算。crates/api-pyannote/云端管线的代理层。暴露/v1/diarize、/v1/identify、/v1/voiceprint三个接口把请求转发给 pyannote 云 API。云代理层看似只是转发实际上做了几件安全上很关键的事媒体的 URL 只接受media://users/{用户ID}/前缀、且逐段校验禁止..路径穿越确保用户只能提交自己的文件上游返回的 jobId 会被重新签名为一个带 HMAC-SHA256 签名的job handle绑定到发起调用的用户别人拿到这个句柄也查不到任务结果。这些细节在 crates/api-pyannote/src/routes.rs 里都有对应的测试用例。十秒滑窗语音分离Segmentation到底在做什么本地管线的第一步是分割。它加载的 ONNX 分割模型segmentation-3.0有两个硬约束每次只能吃10 秒的 16kHz 单声道音频每个窗口内最多区分3 个本地说话人。模型的输出不是逐帧概率而是 7 类幂集分类静音、3 个单人、3 种双人组合。每个输出帧覆盖 270 个采样点模型在 7 个类别里取 argmax解码回这个时刻哪些本地说话人在发声。代码在 crates/pyannote-local/src/segmentation.rs幂集解码逻辑就十几行。长录音靠滑窗覆盖默认步进 2 秒每个时刻最多被约 5 个重叠窗口同时观测到——这个少数服从多数的冗余正是后面抑制误检的基础。同时管线对窗口总数设了上限默认 1800 个录音越长步进自动增大保证计算量有界不会让两小时的录音把 CPU 打满。声纹嵌入与聚类从窗口内的 3 个人到全场 N 个人分割模型只知道这个窗口里有 3 个人在说话但窗口 A 的本地 1 号和窗口 B 的本地 2 号很可能是同一个人。桥接两者的工具是声纹嵌入embedding把一段某人说话时的音频压缩成一个固定长度的向量向量越接近代表声音越像。这里的细节是整条管线里最见功力的部分掩码masking提取只对该说话人独自发声的帧提取嵌入。两人重叠说话的片段会污染向量所以代码专门统计每个本地说话人的 clean frames独占帧不足 1 秒的短促发言不配当聚类锚点只会被归入最近的簇。嵌入计算在 crates/embedding/ 中完成。凝聚式聚类先用锚点向量做质心链接centroid-linkage聚类切割阈值默认 0.7045这是对着 pyannote 官方参数调出来的支撑时长过短的簇会被邻居吸收避免把一个人的声音拆成两半。全局投票重建每个窗口的活动图带着聚类标签投到全局帧网格上某帧获得过半票数才判为该说话人正在说。最后按首次出现顺序给说话人编号再经过min_duration_on/off的后处理合并碎片、桥接短停顿。对齐文字assign_words函数把转写的每个词按时间重叠最大原则分配给某个说话人落在空档里的词归给最近的发言段——这样 diarization 结果就能和 Whisper 转写逐词对齐了。声纹库与已知说话人让匿名簇挂上真名前两步产出的是说话人 1、说话人 2。要变成张伟、李娜靠的是声纹库。crates/voiceprint/ 负责从已有转写里挑选干净的单人片段来建立声纹候选合并间隔小于 400ms 的词、剔除同通道上的重叠语音重叠段直接整段切掉、每段保留 1.5 到 10 秒超长段只保留中段因为句首句尾的犹豫声更多、每人最多取 3 段最长的。有了声纹后crates/pyannote-local/src/pipeline.rs 里的apply_known_speakers会做两件事合并碎片簇本地 diarization 最常见的失败模式是同一个人的声音被拆成两个簇。如果两个簇都和同一个已知声纹高度相似它们会被强制合并——这是声纹库对质量最大的贡献。命名合并后每个簇与声纹库做余弦相似度匹配只有匹配唯一且超过阈值时才会把名字挂上去宁缺毋滥。云端路径上/v1/voiceprint负责生成声纹、/v1/identify负责用声纹库识别人两者都走前面提到的安全代理。用 DER 和 RTF 度量这套算法被怎么验收本地管线有一个专门的自动化评估协议crates/pyannote-local/eval/PROGRAM.md值得新手借鉴指标是 DERDiarization Error Rate说话人分离错误率collar 设为 0.25 秒即标注边界允许 0.25 秒的容差数据集用的是公开的 AMI 和 VoxConverse 会议语料。同时盯 RTF实时率处理 1 秒音频花多少秒验收线是 0.15 以内——意味着 1 小时的录音在参考机器上约 1 分半内跑完这是本地 CPU 可用的硬约束。工作流是棘轮式的一次只改一个参数聚类阈值、锚点时长、后处理等跑一遍 dev 集DER 没有改善超过 0.1 个点就回滚test 集留到最后才碰。这套协议也解释了代码里那些魔法数字的来源2 秒步进是为了让每个帧被约 5 个窗口覆盖12 秒的最小簇时长对应 pyannote 官方的 12 个锚点0.7045 的阈值直接沿用了 pyannote 3.1 的调优值。边界在哪重叠语音与本地/云端的取舍读代码能看出作者对失效场景的清醒认知每个窗口只能分辨 3 个说话人所以 5 人以上同时密集插话时窗口内就会出现本地标签混叠重叠发言越多可用于嵌入的 clean frames 越少簇的质量随之下降——这是滑窗式离线管线的结构性上限不是调参能解决的。云端管线对超长、超高密度会议的鲁棒性更好代价是音频要经过自建代理转发到第三方服务而本地图谱的卖点正是录音不离开你的设备这也是 Anarlog privacy-first 定位的直接体现。从 10 秒窗口分割、掩码嵌入、凝聚聚类到投票重建和声纹命名pyannote-local用大约两千行 Rust 代码把学术界的标准管线搬进了 CPU 上的批处理流程并且每一个默认参数都有评估协议背书。想验证效果的读者克隆仓库后直接跑cargo test -p pyannote-local就能看到它在内置双人测试音频上的断言通过情况。【免费下载链接】anarlogOpen source Granola AI Alternative项目地址: https://gitcode.com/GitHub_Trending/hy/anarlog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表