FunASR 说话人分离 10 分钟上手:多人会议记录转写、分角色字幕一次搞定
【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR
FunASR 是一个开源语音识别工具包,其中的说话人分离(Speaker Diarization)能力可以回答"这段话是谁说的"。把一段多人会议录音丢进去,它会输出带说话人标签(S1、S2……)和起止时间的逐句转写结果,直接用于会议记录、访谈整理和多人语音识别场景。下文按"先跑通、再理解、后调优"的顺序,带你从克隆仓库到产出分角色纪要,全程不超过 10 分钟。
3 条命令跑通:克隆、装依赖、出结果
先做最小验证,确认环境没问题再深入原理。
git clone https://gitcode.com/GitHub_Trending/fun/FunASR cd FunASR && pip install -e .启动一个实时识别服务,再用客户端发一条音频测试:
cd runtime/python/websocket && python funasr_wss_server.py --port 10095 python funasr_wss_client.py --host "127.0.0.1" --port 10095 --mode 2pass --chunk_size "5,10,5"客户端收到逐句文本即说明链路已通。完整命令与参数说明见 runtime/quick_start.md。
说话人分离流水线拆解:一张图看懂输入、处理与输出
整条分离管线是"音频进、带标签的文本出",中间分四级,每一级都有对应的源码目录:
- 输入:原始音频(WAV/MP3),先做 VAD(语音活动检测)切出有效语音段,静音部分直接丢弃,省掉无效计算。
- 中间处理一:重叠语音检测。EEND-OLA 模型对特征帧做逐帧说话人数估计,核心代码在 funasr/models/eend/:
encoder.py:Transformer 编码器,提取时序深度特征;encoder_decoder_attractor.py:LSTM 吸引子(Attractor)网络,给每位说话人生成一条"声音轨迹";e2e_diar_eend_ola.py:模型主体,内含 PostNet 对逐帧标签做平滑后处理。
- 中间处理二:说话人聚类。CAM++ 声纹模型对每段语音提取音色向量,把属于同一个人的片段归到一起。
- 中间处理三:转写与后处理。Paraformer 输出文字,funasr/utils/postprocess_utils.py 负责缩写展开、标点等文本修整。
- 输出:逐句
{start, end, spk, text}列表,例如[0.3s, 2.1s, S1, "大家好,会议开始"]。
下面这张图展示了该管线中说话人感知的转写结构:
关键参数建议值速查
| 参数 | 作用 | 建议取值 / 取值依据 |
|---|---|---|
max_speakers/max_n_speaker | 说话人数上限,决定 EEND-OLA 输出多少条轨迹 | 模型默认 8;实时服务 funasr/bin/realtime_ws.py 默认 15。按实际场景取"常有人数 + 2"即可,取太大浪费算力,取太小会把新人并入旧标签 |
chunk_size | 流式分块大小,如"5,10,5" | 决定延迟与精度的平衡;实时用默认值,离线转写可放大以降低拼接误差 |
n_units | 编码器/吸引子隐层维度 | 默认 256,微调时才动 |
batch_size_s | 按"秒"计的批处理大小 | 内存紧张时减半;GPU 显存富余时可翻倍提速 |
vad_model | 前置 VAD 模型 | 长音频必配,短音频(<10s)可关 |
spk_model | 声纹聚类模型(如 CAM++) | 需要区分"谁在说"时必配;只转写不分离可不配 |
按硬件选部署形态:CPU / GPU / 边缘设备
- CPU(首选入门档):官方提供 ONNX 版 Docker 镜像,一条
docker run拉起离线文件转写服务,8 核 CPU 即可支撑日常会议录音批处理。适用边界:非实时、单路或低并发;不适合大模型推理。 - GPU(生产档):走 Transformers 本地推理或 vLLM 后端,MOSS-Transcribe-Diarize 这类长音频"转写+分离"一体模型建议
bf16精度加载。适用边界:需要长会议整段推理、高并发或多路实时流;显存低于 8GB 时改用分块处理。 - 边缘设备(轻量档):仓库提供 Android / iOS 客户端示例(见 runtime/android/、runtime/ios/)以及 llama.cpp 的 GGUF 量化转换脚本(runtime/llama.cpp/)。适用边界:端侧只做流式识别 + 短句分离,不承载大模型聚类,精度上限低于云端方案。
场景落地:三个"输入→处理→产出"实例
场景一:企业会议记录输入:1 小时的多人会议录音。系统处理:VAD 切段 → EEND-OLA 检测重叠发言 → CAM++ 按音色聚类 → Paraformer 转写。产出:按 S1/S2/S3 分角色的逐句纪要,可直接喂给摘要程序生成决议清单。会议室典型效果可参考 docs/m2met2/images/meeting_room.png:
场景二:访谈节目字幕输入:双人访谈音频 + 时间轴要求。系统处理:逐句分离并打时间戳。产出:带说话人列的字幕文件,配套脚本 examples/subtitle/generate_subtitle.py 可直接生成 SRT。
场景三:直播实时分轨输入:推流麦克风音频(多人连麦)。系统处理:流式 VAD + 在线模型出初步结果,说话人中心在线更新(上限由max_speakers控制,见 funasr/bin/realtime_ws.py)。产出:边播边出的分角色滚动字幕,延迟秒级。
排错手册:现象 → 原因 → 处理办法
Q1:两个人被标成了同一个 S1?
- 可能原因:说话人音色接近且
max_speakers偏小,或重叠段过多。 - 处理办法:把
max_speakers调高 2~3;重叠严重场景保留 EEND-OLA 输出,不要只用聚类。
Q2:长音频(>1 小时)直接内存溢出?
- 可能原因:整段一次性载入。
- 处理办法:先 VAD 分段再逐段推理,
batch_size_s减半;GPU 推理加bf16。
Q3:两条录音里同一个人标签不一致(这条 S1,那条 S3)?
- 可能原因:分离标签是"录音内匿名"的,不做跨录音身份对齐。
- 处理办法:需要固定身份时,在聚类后接一个已知声纹比对步骤,或用带注册声纹的方案。
Q4:实时模式延迟比离线高出一截?
- 可能原因:
chunk_size过小导致频繁触发推理。 - 处理办法:按 runtime/quick_start.md 的 2pass 模式调整分块参数,或改用"在线粗出 + 离线精修"的双通道。
Q5:输出文本断句混乱、没有标点?
- 可能原因:只跑了 ASR 未挂标点模型。
- 处理办法:转写后加
punc_model,再经 funasr/utils/postprocess_utils.py 修整。
进阶:多模型组合与实时优化要点
- 离线分离三件套:
fsmn-vad(切段)+paraformer(转写)+cam++(聚类),用 AutoModel 一次装配即可,适合事后批处理。 - 重叠语音重点场景:叠加 EEND-OLA(funasr/models/eend/)做逐帧重叠检测,这是纯聚类方案做不到的。
- 实时场景:优先 2pass 结构(流式出初稿 + 离线模型改错),说话人中心动态更新、超限时不再新开标签,控制内存与标签漂移。
- 一体化替代:长音频可评估 MOSS-Transcribe-Diarize,单模型直接输出
[start][S01]文本[end]结构,省去外部 VAD 拼接,接入方式见 docs/moss_transcribe_diarize_zh.md。
能力边界与下一步行动清单
当前边界要心里有数:分离标签只在单条录音内有效,跨录音不保证一致;重叠语音的分离精度仍受限于max_speakers与音频质量;纯 CPU 上跑长音频大模型不现实。建议按这个顺序动手:
- 按"3 条命令跑通"一节完成环境验证;
- 拿一段 5 分钟双人录音做分离,核对
spk标签是否稳定; - 用参数速查表调一次
max_speakers和chunk_size,对比输出差异; - 需要长期跑服务时,再按硬件档位选 CPU Docker 或 GPU 后端正式部署。
更多训练与微调入口可看 examples/,安装问题查 docs/installation/。
【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考