说话人分离
OpenASR 的说话人分离功能可以为转写结果中的不同说话人打上标签。整个流程——语音活动检测、说话人分割与嵌入、聚类、归属——全部在本地完成,不涉及任何网络调用(首次使用时的能力包安装除外)。
在 transcribe 或 live 命令中加上 --diarize 即可启用说话人分离:
openasr transcribe --diarize meeting.wavopenasr live --diarize启用后,输出中的每个片段会带有匿名说话人标签,格式为 SPEAKER_00、SPEAKER_01……(两位数字,从零开始)。
指定说话人数量
Section titled “指定说话人数量”transcribe 支持通过 --speakers <n> 强制指定说话人数量,用于已知参与人数的场景:
openasr transcribe --diarize --speakers 3 meeting.wav--speakers 依赖 --diarize,不能单独使用。注意:live 子命令不支持此参数。
能力包自动安装
Section titled “能力包自动安装”说话人分离依赖 WeSpeaker 说话人嵌入能力包。首次使用 --diarize 时,如果该能力包尚未安装,CLI 会自动拉取并安装——传入 --diarize 本身即视为用户对此次下载的授权。安装过程复用与 openasr pull 相同的进度显示(终端环境下显示进度条,非终端环境输出周期性日志)。
如果公共目录中不包含该能力包,CLI 会报错退出,不会静默跳过。
说话人分离是一个与 ASR 模型无关的前后处理阶段,通过时间区间契约与任意本地 ASR 执行器组合,不修改核心识别流程。其管线包含以下组件:
- 语音活动检测——基于 FireRedVAD Stream-VAD(纯 Rust 实现,内置,始终可用)
- 说话人分割与嵌入——由 pyannote 分割模型和 WeSpeaker 嵌入模型提供(均为辅助能力包)
- 聚类与归属——将嵌入聚类后,将说话人标签映射回时间区间
如果在不支持说话人分离的后端或模型包上传入 --diarize,CLI 会直接报错退出(fail-closed),不会静默忽略。
你可以为常见说话人注册本地声纹,这样分离结果中匹配到的说话人会显示自定义名称,而不是匿名标签。
openasr speaker enroll enroll.wav --name Alice --match-similarity 0.6| 参数 | 说明 |
|---|---|
<input> | 16 kHz 单声道 PCM16 WAV 文件,至少包含五秒语音 |
--name | 匹配成功时显示的名称,默认值为 SPEAKER_ME |
--match-similarity | 余弦相似度阈值(0–1),达到此值才判定为匹配,默认 0.5 |
如果输入文件格式不符,CLI 会在错误信息中给出 ffmpeg 转换命令:
ffmpeg -i <input> -ac 1 -ar 16000 -c:a pcm_s16le enroll.wav注册成功后,下一次带 --diarize 的转写会自动使用该声纹进行匹配。
清除所有声纹
Section titled “清除所有声纹”openasr speaker clear此命令会删除本地声纹存储文件中的全部配置。
声纹注册的设计以隐私优先为原则:
- 不存储原始音频——声纹存储文件中只保留 L2 归一化后的嵌入向量和当前说话人嵌入模型的标识,原始录音永远不会写入存储。
- 非认证用途——声纹匹配仅用于在分离结果中显示自定义名称,不是身份认证机制。
- 纯本地处理——分离全流程在本地完成,除首次能力包安装外不发起任何网络请求。
- 无遥测——OpenASR 不包含遥测。
声纹存储默认位于 OPENASR_HOME/diarize/voiceprints.json,可通过环境变量 OPENASR_SPEAKER_PROFILES 覆盖路径。
服务端说话人接口
Section titled “服务端说话人接口”openasr serve 启动的 HTTP 服务提供一组 /v1/speakers REST 接口,用于管理说话人声纹。所有 /v1/speakers 路由均需管理员权限(启用配对认证时需要管理员令牌)。
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /v1/speakers | 列出已注册的声纹 |
POST | /v1/speakers | 上传 WAV 注册新声纹(multipart:name + wav) |
PATCH | /v1/speakers/{id} | 重命名声纹(JSON:{ "name": "..." }) |
DELETE | /v1/speakers/{id} | 删除声纹,返回 { id, deleted: true } |
POST | /v1/speakers/{id}/reenroll | 用新录音替换声纹嵌入,保留原 id(multipart:wav) |
GET /v1/speakers 返回的每条声纹记录包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 声纹唯一标识 |
name | string | 显示名称 |
created_at | string | 创建时间 |
sample_seconds | number | 注册音频时长(秒) |
compatible | bool | 该声纹的嵌入是否与当前活跃的说话人嵌入模型兼容 |
curl -X POST http://127.0.0.1:8080/v1/speakers \ -F name=Alice \当更换了说话人嵌入模型导致 compatible 为 false 时,可以用新录音重新生成嵌入:
curl -X POST http://127.0.0.1:8080/v1/speakers/{id}/reenroll \ -F wav=@new_enroll.wav