【语音识别】--- FunASR 项目详解与 Fun-ASR-Nano 实战
做过语音识别的同学应该都有这个感受:想跑通一个 ASR pipeline,从模型选型到 VAD 切分到标点恢复,每个环节都要折腾不同的库,环境配置能把人逼疯。FunASR 这个项目做的事情说白了就是把这些环节打包成一套端到端的工具链,让你用几行 Python 就能跑通完整的语音识别流程。
本文从 FunASR 的架构讲起,重点实操 Fun-ASR-Nano 模型,最后给出一个可以直接抄的 demo。如果你后续需要把模型部署到边缘设备或追求更低延迟,可以看本系列第二篇 sherpa-onnx 加速部署。
一、FunASR 是什么
FunASR 是阿里达摩院开源的端到端语音识别工具包,底层基于 PyTorch 和 ModelScope。它不只是一个 ASR 模型------而是一整套涵盖了语音活动检测(VAD)、语音识别(ASR)、标点恢复(Punctuation)、说话人验证(Speaker Verification)、说话人分离(Diarization)的完整 pipeline。
核心能力一览
| 能力 | 模型 | 说明 |
|---|---|---|
| 语音识别 | Paraformer-zh / Fun-ASR-Nano | 支持中英文,Paraformer 是非自回归模型,速度快 |
| 语音活动检测 | FSMN-VAD | 把长音频切成有语音的片段,避免识别无声段 |
| 标点恢复 | CT-Punc | 自动给识别结果加标点 |
| 说话人验证 | CAM++ | 判断两段音频是不是同一个人说的 |
| 说话人分离 | --- | 区分多人对话中谁说了什么 |
实际项目中,最常见的组合是 VAD + ASR + 标点恢复 ,FunASR 把这三步封装成了一个 AutoModel 调用。
二、环境搭建
2.1 安装 FunASR
bash
pip install -U funasr
如果你要用 GPU 推理,确保 CUDA 环境已经就绪。FunASR 依赖 PyTorch,建议先装好对应 CUDA 版本的 PyTorch 再装 FunASR。
bash
# 示例:CUDA 11.8 对应的 PyTorch
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
2.2 版本说明
本文以 FunASR 1.2.x 为例。如果你用的是其他版本,可以通过 pip show funasr 确认。
2.3 模型下载
FunASR 的模型托管在 ModelScope 和 Hugging Face 上,首次调用时会自动下载。也可以提前手动下载:
bash
# 从 ModelScope 下载(国内推荐)
pip install modelscope
modelscope download --model FunAudioLLM/Fun-ASR-Nano-2512
# 从 Hugging Face 下载
pip install huggingface_hub
huggingface-cli download FunAudioLLM/Fun-ASR-Nano-2512
三、FunASR 的 AutoModel 机制
FunASR 的核心入口是 AutoModel,它做的事情类似 Hugging Face 的 AutoModel------你给一个模型名或路径,它自动加载对应的模型结构和权重。
python
from funasr import AutoModel
model = AutoModel(model="paraformer-zh")
这行代码背后的流程:
- 从 ModelScope/HF 拉取
paraformer-zh的配置和权重 - 根据配置构建模型结构
- 加载权重到指定设备
当你同时指定 vad_model 和 punc_model 时,AutoModel 会自动组装 pipeline:先 VAD 切分 → 再逐段 ASR → 最后标点恢复。这个设计很聪明,把最常用的组合固化下来了。
四、Fun-ASR-Nano 模型详解
Fun-ASR-Nano 是 FunAudioLLM 系列中的轻量级 ASR 模型,2024 年底发布。它的定位是在保持较高识别精度的前提下,模型体量更小、推理更快。
4.1 模型变体
| 模型 ID | 语言支持 | 说明 |
|---|---|---|
FunAudioLLM/Fun-ASR-Nano-2512 |
中文、英文、日文 | 基础版,适合大多数场景 |
FunAudioLLM/Fun-ASR-MLT-Nano-2512 |
30+ 语言 | 多语言版,覆盖粤语、韩文、泰语、阿拉伯语等 |
4.2 核心特性
- 热词增强(Hotword Boosting):可以指定一些关键词,让模型在识别时更倾向于输出这些词。比如你在转写一篇关于"量子计算"的录音,把"量子""纠缠""叠加"加到热词里,识别率会明显提升。
- 逆文本正则化(ITN):自动把"一二三"转成"123","百分之五十"转成"50%"。
- 多语言识别 :通过
language参数切换。
五、实战:Fun-ASR-Nano 语音识别 Demo
下面给一个完整的可运行 demo,覆盖从加载模型到输出结果的全流程。
5.1 最简版本:三行代码跑通
python
from funasr import AutoModel
model = AutoModel(model="FunAudioLLM/Fun-ASR-Nano-2512",
trust_remote_code=True,
device="cuda:0")
res = model.generate(input="your_audio.mp3", cache={})
print(res[0]["text"])
5.2 完整版本:VAD + 热词 + ITN
这个版本更适合实际项目使用,处理长音频时不会 OOM,而且支持热词和正则化。
python
import torch
from funasr import AutoModel
# 自动选择设备
device = "cuda:0" if torch.cuda.is_available() else "cpu"
# 加载模型 + VAD
model = AutoModel(
model="FunAudioLLM/Fun-ASR-Nano-2512",
trust_remote_code=True,
vad_model="fsmn-vad",
vad_kwargs={"max_single_segment_time": 30000}, # VAD 切分最大 30 秒
device=device,
hub="ms", # 从 ModelScope 下载,改成 "hf" 用 Hugging Face
)
# 推理
res = model.generate(
input=["audio.mp3"],
cache={},
batch_size=1,
hotwords=["开放时间", "发布会"], # 热词增强
language="中文",
itn=True, # 逆文本正则化
)
text = res[0]["text"]
print(text)
5.3 带标点恢复的版本
如果你需要识别结果自带标点,加上 punc_model:
python
model = AutoModel(
model="FunAudioLLM/Fun-ASR-Nano-2512",
trust_remote_code=True,
vad_model="fsmn-vad",
vad_kwargs={"max_single_segment_time": 30000},
punc_model="ct-punc",
device="cuda:0",
)
res = model.generate(input=["long_audio.mp3"], cache={}, batch_size_s=300)
print(res[0]["text"])
# 输出带标点:大家好,欢迎来到今天的发布会。我们即将开放全新的接口。
5.4 从 ModelScope 模型路径直接加载
如果你已经把模型下载到本地,可以直接指定路径:
python
model = AutoModel(
model="/path/to/Fun-ASR-Nano-2512",
trust_remote_code=True,
remote_code="./model.py",
vad_model="fsmn-vad",
vad_kwargs={"max_single_segment_time": 30000},
device="cuda:0",
)
本章小结
| 参数 | 作用 | 建议值 |
|---|---|---|
vad_model |
语音活动检测 | "fsmn-vad"(长音频必加) |
vad_kwargs.max_single_segment_time |
VAD 切分最大时长(ms) | 30000~60000 |
punc_model |
标点恢复 | "ct-punc" |
hotwords |
热词列表 | 根据场景自定义 |
language |
识别语言 | "中文" / "英文" / "日文" |
itn |
逆文本正则化 | True |
batch_size_s |
动态 batch 总时长(s) | 300(OOM 时调小) |
六、长音频处理与 OOM 避坑
处理长音频(比如一小时的会议录音)是 FunASR 最容易踩坑的地方。官方给了一套三阶段调参方案,实际用下来确实有效:
第一阶段:调 batch_size_s
python
res = model.generate(input=["long.mp3"], batch_size_s=100) # 默认 300,OOM 就往下调
第二阶段:调 batch_size_threshold_s
python
res = model.generate(input=["long.mp3"], batch_size_s=300, batch_size_threshold_s=30)
这个参数的作用是:VAD 切出来的片段如果超过这个阈值,强制 batch_size=1。
第三阶段:调 max_single_segment_time
python
vad_kwargs={"max_single_segment_time": 15000} # 从 30000 降到 15000
把 VAD 切得更碎。这是我们团队处理两小时会议录音时最终用的方案------前两阶段搞不定的时候,切碎 VAD 是最后的杀手锏。
七、命令行用法
不想写 Python?FunASR 也支持命令行直接调用:
bash
# 基础用法
funasr ++model=paraformer-zh ++input=audio.wav
# 完整 pipeline
funasr ++model=paraformer-zh ++vad_model="fsmn-vad" ++punc_model="ct-punc" ++input=audio.wav
不过实际项目中还是推荐 Python API,灵活度高很多。
八、常见问题排查
Q1:首次运行很慢 / 卡在下载
模型文件比较大(Fun-ASR-Nano 约 1~2GB),首次需要下载。如果网络不好,可以提前用 modelscope download 或 huggingface-cli download 手动下载到本地。
Q2:CUDA out of memory
按第六节的方案调参。另外一个常见原因是 GPU 显存被其他进程占了,用 nvidia-smi 检查一下。
Q3:识别结果没有标点
你漏了 punc_model="ct-punc"。FunASR 的 ASR 模型本身不输出标点,标点恢复是独立的步骤。
Q4:trust_remote_code=True 是什么意思
Fun-ASR-Nano 的模型代码不在 FunASR 主仓库里,需要从远程加载。这个参数相当于 Hugging Face 的同名参数,允许执行模型仓库里的自定义代码。如果你是从可信来源(ModelScope/HF 官方仓库)下载的模型,放心用。
九、总结
FunASR 的核心价值在于把 VAD、ASR、标点恢复这些环节打包成了一个统一的 API,省去了自己拼接 pipeline 的麻烦。Fun-ASR-Nano 作为轻量级模型,在中文场景下精度和速度都不错,适合大多数非实时场景。
需要记住的几件事:
- 长音频必加 VAD :
vad_model="fsmn-vad"不是可选项,是必选项。 - 热词能救场 :专有名词、人名、行业术语加到
hotwords里,识别率提升明显。 - OOM 三板斧 :调
batch_size_s→ 调batch_size_threshold_s→ 调max_single_segment_time。 - 模型从 ModelScope 下载更快 :国内环境下
hub="ms"比 Hugging Face 快得多。
验证清单
- ⭐ FunASR 安装成功:
python -c "import funasr; print(funasr.__version__)" - 模型下载完成:首次
AutoModel()调用不报错 - 最简 demo 跑通:三行代码识别一段测试音频
- VAD + 标点 pipeline 跑通:长音频输出带标点的文本
- 热词功能验证:指定热词后识别结果包含热词
参考资源
- FunASR GitHub:https://github.com/modelscope/funasr
- Fun-ASR-Nano 模型:https://modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512
- FunASR 官方文档:https://github.com/modelscope/funasr/blob/main/README_zh.md
如果你训练好了模型,下一步自然是部署上线。如果你的场景需要低延迟、边缘部署或者不想依赖 PyTorch 运行时,可以看 第二篇:sherpa-onnx 加速部署------它能把 FunASR 的模型导出成 ONNX 格式,用 ONNX Runtime 跑推理,速度快很多。