FunASR Python SDK 实战指南:基于 AutoModel 的语音识别、VAD、标点与说话人分离
【免费下载链接】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 是开源的语音识别工具包,funasr.AutoModel是其 Python SDK 的核心统一入口:一次构造即可完成模型下载、组件装配与推理调用,覆盖离线识别、VAD 语音活动检测、标点恢复、句子时间戳、批量转录、热词偏置乃至说话人分离等常见语音任务。本文以仓库 examples/README.md 为主线,结合 AutoModel 源码 与各示例程序,从第一个转录开始逐步深入,读完你将掌握 AutoModel 的完整参数语义、VAD/标点/说话人分离管线的正确用法、批量输入与热词纠正的实战细节,并能独立完成训练、导出与自定义模型的注册与排查。
适用范围说明:本文讲解的是
funasr.AutoModel工具包路径。若你只需要 Fun-ASR-Nano 的原生转录能力,可参考 Transformers 5.17.0 原生集成指南,它直接加载独立的-hf权重而无需 FunASR 工具包。两条路径的依赖、参数与输出契约各不相同,不要混用。模型选择、语言支持、依赖与模型卡信息请以 Model Zoo 为准,而不是一份通用的能力清单;尚未配置本地环境的读者可先跑 Colab 快速开始。
1. 环境准备与第一个转录
FunASR 使用 MIT 许可,但每个模型权重拥有独立的许可协议:请记录完整的模型 ID 与 revision,并遵守对应模型卡。仅当模型卡明确链接到 FunASR 模型许可协议 时才适用该协议。第三方集成仍属于第三方模型,例如 MOSS-Transcribe-Diarize 来自 OpenMOSS,并非 FunASR 训练的权重。
安装 SDK 并准备好匹配的 PyTorch/torchaudio 环境后,先阅读 安装与环境验证,然后运行下面的 Python 代码块。首次运行需要联网以下载模型和示例 WAV,并需要足够的磁盘与内存空间。以下代码基于仓库的 Paraformer 示例 改写:
from funasr import AutoModel audio = "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav" model = AutoModel( model="paraformer-zh", hub="ms", device="cpu", ncpu=4, disable_update=True, trust_remote_code=False, ) results = model.generate(input=audio) for item in results: print(item.get("key"), item.get("text", "")) print("Model directory:", model.model_path)要转录你自己的录音,把audio替换为本地 WAV 路径即可。建议从短的单声道录音开始,采样率与所选模型匹配(本例为 16 kHz)。文件解码依赖已安装的音频后端,一个可读的 WAV 比任意媒体容器更适合作为第一步验证。若输入是 NumPy 波形数组,由于没有采样率头信息,必须用fs=sample_rate显式传入真实采样率,音频加载器 正是这样使用的——不要只改波形数据的"名义采样率"。
输入形式的底层支持
从 prepare_data_iterator 的实现可以看到,input参数实际支持多种形式,这为后续批量处理打下了基础:
- 字符串路径(本地 WAV/MP3 等);
http://或https://开头的 URL(自动下载);- 文件列表(
.scp、.txt、.json、.jsonl、.text扩展名); - Python
list/tuple(批量输入或多种模态组合); bytes原始音频字节(经load_bytes加载);- 原始文本(供标点模型使用)。
另外两点值得注意:disable_update=True只跳过 SDK 启动时的版本检查(version_checker);如果使用断网环境,请参照离线清单预先准备完整的本地模型目录与本地输入文件。后续所有代码块在同一个 Python 会话中复用第一个块创建的AutoModel、audio和model。
2. 理解参数与结果
AutoModel(...)负责构造主模型与可选的管线组件,model.generate(input=..., **options)执行推理。底层实现可参考 AutoModel、hub 别名映射 以及所选模型的inference()实现。
核心参数表
| 参数 | 作用域与含义 |
|---|---|
model、hub | 模型 ID/别名或本地目录;hub默认 ModelScope(ms),可用hf使用 Hugging Face。别名可能解析到不同的 hub 仓库。 |
device、ncpu | 起步阶段显式使用cpu;只有在验证了 PyTorch 构建与模型支持后才选择加速器。加载器有 CPU 回退路径;ncpu控制 PyTorch CPU 线程数。 |
vad_model、punc_model、spk_model | 可选、独立加载的模型。通过vad_kwargs、punc_kwargs、spk_kwargs配置。并非所有 ASR 后端都自动支持它们。 |
batch_size | 普通(非 VAD)路径下每个解码批次的输入数量;后端自身的限制仍然适用。 |
batch_size_s | VAD 分段批处理的时长预算(秒),基于补齐后的段长计算,而不是文件数量。当前 CPU VAD 路径逐段解码。 |
batch_size_threshold_s | VAD 批处理启发式使用的段时长阈值(秒);不是输入时长上限,也不是通用的内存上限。 |
output_dir | 可选的后端输出目录。返回的 Python 结果仍然可用;文件与格式取决于模型。 |
构造阶段的底层行为
阅读 AutoModel.build_model 可以看到构造阶段完成的完整链路:从 hub 下载模型文件 → 解析config.yaml确定模型类、tokenizer、frontend → 通过注册表实例化组件 → 从model.pt加载预训练权重。其中几个细节值得了解:
- 设备自动回退:当指定的
cuda/xpu/mps/npu不可用或ngpu=0时,会自动回退到 CPU 并把batch_size强制设为 1(见 L557-L567)。 - CPU 线程控制:
ncpu默认值为 4,会通过torch.set_num_threads(ncpu)生效(L46-L53、L569-L572)。 - 别名解析:
paraformer-zh等短别名在 name_maps_from_hub.py 中映射到完整模型 ID,且ms与hf两个 hub 的映射可能不同。
generate() 的返回结构
generate()返回字典列表,通常每个输入录音对应一个字典。在依赖可选字段之前,先检查返回键:
for item in results: print(sorted(item.keys())) print(item.get("text", "")) print(item.get("timestamp", []))对 Paraformer 路径而言,当检查点提供timestamp时,它包含字符/词/词元的[start_ms, end_ms]区间对。不要假设标点或文本归一化之后每个展示字符都对应一个区间对。其他后端可能返回不同 schema 的timestamps,请遵循对应后端的指南。静音输入可能产生空文本/空时间戳,而非有意义的转录。
从 generate() 源码看,它内部按是否配置vad_model自动路由:无 VAD 时走inference()(单句识别,可选叠加标点模型),有 VAD 时走inference_with_vad()(长音频分段识别)。两种路径结束后都会统一执行apply_postprocess_hotwords_to_results,即第 5 节要讲的热词后处理。
3. 添加 VAD、标点与句子时间戳
3.1 独立使用 VAD
VAD 检测语音区间,但不做转录。下面的独立调用使用同一段音频:
vad = AutoModel(model="fsmn-vad", device="cpu", disable_update=True) vad_results = vad.generate(input=audio) for item in vad_results: print(item["key"], item["value"])value是相对录音起始点的[start_ms, end_ms]语音区间列表。空列表表示未检测到任何语音段。可对照 FSMN VAD 示例。fsmn-vad别名解析为iic/speech_fsmn_vad_zh-cn-16k-common-pytorch(见 别名映射)。
3.2 VAD + 标点 + 句子时间戳的分段识别
pipeline = AutoModel( model="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc", vad_kwargs={"max_single_segment_time": 30000}, device="cpu", disable_update=True, trust_remote_code=False, ) segmented_results = pipeline.generate( input=audio, batch_size_s=60, batch_size_threshold_s=30, sentence_timestamp=True, ) for item in segmented_results: print(item.get("text", "")) for sentence in item.get("sentence_info", []): print(sentence.get("start"), sentence.get("end"), sentence.get("text", ""))单位约定要格外注意:max_single_segment_time单位是毫秒,而batch_size_s与batch_size_threshold_s单位是秒。分段有助于处理较长文件,但并不保证无限时长或内存有界:音频加载阶段和每个模型仍会消耗资源。内存紧张时,改用更短的录音/分段与更小的支持批次,然后重新测量。
从 inference_with_vad 的实现看,完整的管线分为五步(见 L861-L866 的文档注释):
- VAD:把音频切成语音区间;
- ASR:按段长排序后分批识别(排序是为了高效批处理);
- 时间戳合并:把每段的时间戳与 VAD 偏移量叠加;
- 标点:若配置
punc_model,对合并文本添加标点; - 说话人分离:若配置
spk_model,对说话人嵌入做聚类并打标签。
底层细节包括:batch_size_s默认 300 秒、batch_size_threshold_s默认 60 秒(L899-L900);当设备为 CPU 时batch_size被置 0,即逐段解码(L935-L936)。这解释了文档中"当前 CPU VAD 路径逐段解码"的结论。此外,当标点时间戳无法与词对齐时(punc_alignment_failed),句子边界会回退到 VAD 段(L1218-L1222),因此拿到sentence_info后应检查实际返回的数据,而不是假设每个句子都精确对齐。
3.3 说话人分离(Diarization)
构造同样的管线并配置spk_model="cam++"(若所选组件支持),然后遍历每个输入的item.get("sentence_info", []),读取sentence.get("spk")。不要从外层结果列表直接读spk。聚类标签并不等同于经过核实的真实身份。参考 SenseVoice 说话人示例。
从源码看,说话人分离有两个模式(L505-L508):默认punc_segment(按标点句切分)与vad_segment(按 VAD 段切分);当缺少标点模型或时间戳不可用时,会自动回退到vad_segment(L1130-L1156)。说话人嵌入经过 ClusterBackend 聚类后写入sentence_info,若开启return_spk_center=True还会额外返回每个说话人的spk_embedding_center质心(L1143-L1150)。cam++别名解析为iic/speech_campplus_sv_zh-cn_16k-common。
4. 批量处理多个录音
下面的代码刻意重复同一示例音频,以演示列表输入而不需要额外文件。请把列表项替换为本地 WAV 路径:
batch_results = model.generate(input=[audio, audio], batch_size=1) for index, item in enumerate(batch_results): print(index, item.get("key"), item.get("text", ""))只有所选模型支持且内存允许时,才提高batch_size。文件列表(如wav.scp)同样受支持:每行一个utterance_id path,路径相对于进程工作目录解析,每个录音使用唯一 ID。如果需要模型写出的工件再设置output_dir;仅接收返回的列表并不需要它。参考 数据清单示例,其格式如下:
BAC009S0764W0121 https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/BAC009S0764W0121.wav asr_example_cn_en https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_cn_en.wav注意:独立的文件批处理与单条话语的流式分块(见第 6 节)是两回事,不要混淆。
5. 热词(Hotwords)与语言边界
5.1 模型级热词偏置(context biasing)
本仓库中 ModelScope 的paraformer-zh别名解析为 SeACo Paraformer 模型(见 name_maps_from_hub.py 中的speech_seaco_paraformer_large_asr_nat-zh-cn-16k-common-vocab8404-pytorch),其实现接受单个hotword,值为空格分隔的字符串:
biased_results = model.generate(input=audio, hotword="魔搭 达摩院") print([item.get("text", "") for item in biased_results])这是模型级的语义上下文偏置(semantic context biasing),不是保证插入词或确定性替换。请核实解析到的模型,并与无热词基线对比效果。底层实现见 SeACo 模型(其文档注释明确指出它"将 Paraformer 的非自回归架构与语义上下文偏置结合以提升热词识别"),配套示例见 contextual Paraformer 示例:
model = AutoModel(model="iic/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404") res = model.generate( input="https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav", hotword="达摩院 魔搭", )5.2 文本级热词后处理(postprocess)
在本仓库源码中,文本后处理是另一个独立的操作,作用于解码后的最终文本:
corrected_results = model.generate( input=audio, postprocess_hotwords={"科大迅飞": "科大讯飞"}, return_postprocess_hotword_matches=True, ) for item in corrected_results: print(item.get("text", ""), item.get("postprocess_hotword_matches", []))显式映射会替换匹配到的输出文本。postprocess_hotword_file还支持每行一个目标词,或wrong=>right形式的映射。模糊匹配额外需要pypinyin与rapidfuzz;纯显式映射则不需要。
postprocess_hotwords.py 是这一功能的完整实现,几个关键点:
- 两种桶:显式映射(
explicit_map)与模糊目标(fuzzy_targets)。显式替换按长度降序贪心进行;模糊匹配先把文本与目标转成拼音键(lazy_pinyin),再用rapidfuzz.ratio打分,默认阈值postprocess_hotword_threshold=0.85,可配置范围为[0.0, 1.0](L176-L241)。 - 文件格式:支持
#注释;显式分隔符为=>、->、→(L82-L103)。 - 保留时间戳:替换文本时会保留原有
timestamp,而不是重新对齐修正后的文本(L277-L279)。因此在制作字幕或做对齐声明之前,务必人工复核替换结果。 - 匹配详情:开启
return_postprocess_hotword_matches=True后,每个匹配项会返回original、replacement、score、start、end字段(见 HotwordMatch)。
上述行为均有 test_postprocess_hotwords.py 测试佐证:例如{"科大迅飞": "科大讯飞"}被视为显式映射,而["科大讯飞"]属于模糊目标;文件解析同样支持注释与wrong=>right混合写法。
5.3 热词与语言参数的边界
hotword、hotwords、language不是可以互换的通用 SDK 选项。例如 Fun-ASR-Nano 示例 读取复数形式的hotwords和模型专属的语言提示。修改语言提示并不会把单语种检查点变成多语种模型。请使用 Model Zoo 与对应检查点的精确指南,确认支持的语言、可接受的提示值、流式能力、对齐能力与依赖版本;不要在模型家族之间照搬语言数量或安装锁定。
6. 按具体工作流继续深入
- 流式识别:Paraformer 流式示例。每个流保持独立的
cache={},最后一个分块设置is_final=True。对于 16 kHz 下的[0, 10, 5]块,600 ms 对应9600 个采样点,而不是 960;分块时长并不等于端到端延迟保证。流式 VAD 可能返回[start, -1]、[-1, end]、完整区间或空区间,单位均为毫秒。 - 标点与对齐:CT-Transformer 标点示例 与 时间戳预测示例。对齐需要对应的文本输入,并不等同于 ASR。
- 其他模型家族:SenseVoice、Fun-ASR-Nano 与 第三方 OpenMOSS 集成。更多条目可通过 Model Zoo 发现。
- CLI 与服务化:CLI 参考、运行时总览 与 Docker 部署。注意 Python 选项并不代表服务端请求 schema 与之完全相同。
7. 模型训练、导出与自定义模型注册
7.1 训练与测试
使用 Paraformer 训练配方、finetune.sh 与 训练数据示例。启动前务必检查数据集路径、标签对齐、模型许可、GPU 分配与输出目录。训练不是安装冒烟测试。对于训练好的权重,检查 infer_from_local.sh:配置、tokenizer/frontend 资产与检查点路径必须一致。同时保持验证数据与训练数据分离。
7.2 模型导出与测试
遵循模型的 Paraformer 导出示例 与 ONNX Runtime 指南。导出支持与额外依赖是模型/后端相关的。从源码看,AutoModel.export 会对模型与配置做深拷贝,隔离 ONNX 算子 monkey-patching 与deep_update/del的引用污染,原模型在导出后仍可使用。但导出成功并不等于输出等价:部署前务必用有代表性的输入测试导出产物,并与原模型对比。
7.3 注册自定义模型
使用模型注册教程与一个真实实现,例如 SenseVoice 模型。仅完成注册并不保证generate()契约可用:模型的推理结果必须与其将使用的下游组件匹配。
7.4 故障排查
失败时回到 troubleshooting,并附带解释器/包版本、解析后的模型 ID/revision、输入格式与最小可复现样例。不要包含私有音频或凭据。
【免费下载链接】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),仅供参考