一å¥è¯ä»‹ç»ï¼šFunASR 是阿里巴巴达摩院开æºçš„端到端è¯éŸ³è¯†åˆ«å·¥å…·åŒ…,集æˆäº† Paraformerã€SenseVoice ç‰ SOTA æ¨¡åž‹ï¼Œæ”¯æŒ ASRã€VADã€æ ‡ç‚¹æ¢å¤ã€æƒ…感识别ã€éŸ³é¢‘事件检测ç‰å¤šä»»åŠ¡ï¼Œæ˜¯è¿žæŽ¥å¦æœ¯ç ”究与工业应用的桥æ¢ã€‚
FunASR(Fundamental End-to-End Speech Recognition Toolkit)是由阿里巴巴达摩院开æºçš„端到端è¯éŸ³è¯†åˆ«å·¥å…·åŒ…。它于 2023 å¹´æ£å¼å¼€æºï¼Œç›®æ ‡æ˜¯åœ¨è¯éŸ³è¯†åˆ«çš„妿œ¯ç ”究和工业应用之间架起一座桥æ¢ã€‚
| 维度 | 说明 |
|---|---|
| å¼€æºæ€§è´¨ | 完全开æºï¼ŒApache 2.0 åè®® |
| å¼€å‘团队 | 阿里巴巴达摩院 |
| æ¨¡åž‹ç”Ÿæ€ | ModelScope + Hugging Face åŒå¹³å°åˆ†å‘ |
| æ•°æ®è§„模 | æ•°ä¸‡å°æ—¶å·¥ä¸šçº§æ ‡æ³¨æ•°æ®è®ç»ƒ |
| 社区活跃度 | GitHub 高星项目,æŒç»æ›´æ–° |
┌─────────────────────────────────────────────────────────â”
│ FunASR 功能矩阵 │
├─────────────┬─────────────┬─────────────┬───────────────┤
│ è¯éŸ³è¯†åˆ« │ è¯éŸ³ç«¯ç‚¹æ£€æµ‹ │ æ ‡ç‚¹æ¢å¤ │ è¯è¨€æ¨¡åž‹ │
│ (ASR) │ (VAD) │ (Punc) │ (LM) │
├─────────────┼─────────────┼─────────────┼───────────────┤
│ 说è¯äººéªŒè¯ │ 说è¯äººåˆ†ç¦» │ 情感识别 │ 音频事件检测 │
│ (SV) │ (SD) │ (SER) │ (AED) │
├─────────────┴─────────────┴─────────────┴───────────────┤
│ 多人对è¯è¯éŸ³è¯†åˆ« (Multi-talker ASR) │
└─────────────────────────────────────────────────────────┘
FunASR 采用模å—化设计ç†å¿µï¼Œé€šè¿‡ç»Ÿä¸€çš„ AutoModel æŽ¥å£æ•´åˆå¤šç§è¯éŸ³å¤„ç†ä»»åŠ¡ï¼š
输入音频
│
â–¼
┌─────────────â”
│ VAD é¢„å¤„ç† â”‚ ↠è¯éŸ³ç«¯ç‚¹æ£€æµ‹ï¼Œé•¿éŸ³é¢‘切分
│ (å¯é€‰) │
└──────┬──────┘
│
â–¼
┌─────────────â”
│ ç‰¹å¾æå– â”‚ ↠梅尔频谱图 / FBank
│ (Encoder) │
└──────┬──────┘
│
â–¼
┌─────────────â”
│ æ ¸å¿ƒæ¨¡åž‹ │ ↠Paraformer / SenseVoice / Whisper
│ (ASR模型) │
└──────┬──────┘
│
â–¼
┌─────────────â”
│ åŽå¤„ç† â”‚ â† æ ‡ç‚¹æ¢å¤ã€ITNã€çƒè¯å¢žå¼º
│ (å¯é€‰) │
└──────┬──────┘
│
â–¼
输出文本
Paraformer(Parallel Transformer)是 FunASR çš„æ——èˆ°æ¨¡åž‹ï¼Œå…¶æ ¸å¿ƒåˆ›æ–°æ˜¯è¿žç»é›†æˆæ»¤æ³¢ï¼ˆContinuous Integration Filtering, CIF)机制。
ä¼ ç»Ÿè‡ªå›žå½’æ¨¡åž‹çš„é—®é¢˜ï¼š
ä¼ ç»Ÿ AR 模型:
音频 → [é€å¸§è§£ç ] → "今" → "天" → "天" → "æ°”" → ... (串行,慢)
Paraformer NAR 模型:
音频 → [CIF预测器] → 长度预测 → [并行解ç ] → "今天天气很好" (一次性,快)
# CIF é¢„æµ‹å™¨æ ¸å¿ƒé€»è¾‘ï¼ˆç®€åŒ–ç‰ˆï¼‰
def cif_predictor(encoder_output):
# 1. 上下文建模:1Då·ç§¯æ•获局部è¯éŸ³ç‰¹å¾
context = conv1d(encoder_output)
# 2. 生æˆå¸§çº§é‡è¦æ€§æƒé‡ α
alphas = sigmoid(output_layer(context))
# 3. 累积 α å€¼ï¼Œè¶…è¿‡é˜ˆå€¼æ—¶ç”Ÿæˆ token
tokens = []
accumulated = 0
for alpha in alphas:
accumulated += alpha
if accumulated >= threshold:
tokens.append(current_frame_features)
accumulated = 0
return tokens, len(tokens) # 预测的 token åºåˆ—和长度
CIF 优势:
| 模型 | Aishell1 CER | 推ç†é€Ÿåº¦ (RTF) | 傿•°é‡ |
|---|---|---|---|
| Transformer | 5.8% | 0.82 | 180M |
| Conformer | 3.4% | 0.56 | 190M |
| Paraformer | 1.94% | 0.12 | 220M |
RTF(Real Time Factor)= æŽ¨ç†æ—¶é—´/音频时长,越å°é€Ÿåº¦è¶Šå¿«
SenseVoice 是 FunASR 推出的新一代è¯éŸ³åŸºç¡€æ¨¡åž‹ï¼Œé‡‡ç”¨å¤šä»»åŠ¡å¦ä¹ 框架:
SenseVoice Small(éžè‡ªå›žå½’,轻é‡çº§ï¼‰ï¼š
输入音频 → Feature Extractor → Task Embedder → 并行输出
↓
┌──────┼──────â”
LID SER AED/ASR
SenseVoice Large(自回归,更强大):
音频输入 → SAN-M Encoder → Transformer Decoder → 自回归生æˆåºåˆ—
输出示例:
SOS → LID:zh → SER:happy → AED:bgm → ASR:阿 → AED:/bgm → ASR:里 → ASR:巴 → happy → EOS
| 任务 | 说明 | 输出示例 |
|---|---|---|
| ASR | è¯éŸ³è¯†åˆ« | "阿里巴巴" |
| LID | è¯ç§è¯†åˆ« | [zh]䏿–‡ã€[en]英文ã€[yue]粤è¯ã€[ja]æ—¥è¯ã€[ko]éŸ©è¯ |
| SER | 情感识别 | [happy]开心ã€[angry]生气ã€[sad]难过ã€[neutral]ä¸ç«‹ |
| AED | 音频事件检测 | [bgm]背景音ä¹ã€[applause]掌声ã€[laughter]笑声ã€[cough]咳嗽 |
| ITN | 逆文本æ£åˆ™åŒ– | "二零二四年" → "2024å¹´" |
| 模型 | 任务 | è¯è¨€ | 傿•°é‡ | 特点 |
|---|---|---|---|---|
| SenseVoiceSmall | ASR+LID+SER+AED | 多è¯è¨€ | 330M | â 多任务ç†è§£ |
| paraformer-zh | ASR | 䏿–‡ | 220M | éžå®žæ—¶ï¼Œé«˜ç²¾åº¦ |
| paraformer-zh-streaming | ASR | 䏿–‡ | 220M | 实时æµå¼è¯†åˆ« |
| paraformer-en | ASR | 英文 | 220M | 英è¯ä¸“用优化 |
| conformer-en | ASR | 英文 | 220M | Conformer架构 |
| ct-punc | æ ‡ç‚¹æ¢å¤ | ä¸è‹±æ–‡ | 290M | 上下文感知 |
| fsmn-vad | VAD | 多è¯è¨€ | 0.4M | 实时端点检测 |
| fsmn-kws | è¯éŸ³å”¤é†’ | 䏿–‡ | 0.7M | 实时唤醒 |
| cam++ | 说è¯äººéªŒè¯ | 多è¯è¨€ | 7.2M | 深度说è¯äººç‰¹å¾ |
| Whisper-large-v3 | ASR | 多è¯è¨€ | 1550M | OpenAI 模型 |
| Qwen-Audio | 多模æ€å¤§æ¨¡åž‹ | 多è¯è¨€ | 8B | éŸ³é¢‘æ–‡æœ¬å¯¹é½ |
| emotion2vec+ | 情感识别 | 多è¯è¨€ | 300M | 4ç§æƒ…感类别 |
from funasr import AutoModel
# åŠ è½½æ¨¡åž‹
model = AutoModel(
model="paraformer-zh",
vad_model="fsmn-vad", # è¯éŸ³ç«¯ç‚¹æ£€æµ‹
punc_model="ct-punc", # æ ‡ç‚¹æ¢å¤
# spk_model="cam++" # 说è¯äººåˆ†ç¦»ï¼ˆå¯é€‰ï¼‰
)
# 推ç†
res = model.generate(
input="asr_example_zh.wav",
batch_size_s=300,
hotword='锿' # çƒè¯å¢žå¼º
)
print(res)
è¾“å‡ºæ ¼å¼ï¼š
[{
"key": "asr_example_zh",
"text": "é”ææ˜¯ä¸€ä¸ªå¼€æºçš„æ¨¡åž‹å³æœåС平å°ã€‚",
"timestamp": [[0, 800], [800, 1200], ...], // å—级别时间戳
"confidence": 0.95
}]
from funasr import AutoModel
from funasr.utils.postprocess_utils import rich_transcription_postprocess
model = AutoModel(
model="iic/SenseVoiceSmall",
vad_model="fsmn-vad",
vad_kwargs={"max_single_segment_time": 30000},
device="cuda:0",
)
res = model.generate(
input="example.mp3",
cache={},
language="auto", # 自动è¯è¨€æ£€æµ‹
use_itn=True, # å¯ç”¨é€†æ–‡æœ¬å½’一化
batch_size_s=60,
merge_vad=True,
merge_length_s=15,
)
# 富文本åŽå¤„ç†
text = rich_transcription_postprocess(res[0]["text"])
print(text)
输出示例:
<|zh|><|happy|><|bgm|>阿里巴巴是一家科技公å¸<|/bgm|>
from funasr import AutoModel
# æµå¼é…ç½®
chunk_size = [0, 10, 5] # [0, 10, 5] = 600ms 延迟
encoder_chunk_look_back = 4
decoder_chunk_look_back = 1
model = AutoModel(model="paraformer-zh-streaming")
# 模拟æµå¼è¾“å…¥
import soundfile
speech, sample_rate = soundfile.read("test.wav")
chunk_stride = chunk_size[1] * 960 # 600ms = 960 é‡‡æ ·ç‚¹ (16kHz)
cache = {}
total_chunk_num = int(len(speech) / chunk_stride) + 1
for i in range(total_chunk_num):
speech_chunk = speech[i*chunk_stride:(i+1)*chunk_stride]
is_final = (i == total_chunk_num - 1)
res = model.generate(
input=speech_chunk,
cache=cache,
is_final=is_final,
chunk_size=chunk_size,
encoder_chunk_look_back=encoder_chunk_look_back,
decoder_chunk_look_back=decoder_chunk_look_back
)
print(f"Chunk {i}: {res}")
æµå¼å»¶è¿Ÿè¯´æ˜Žï¼š
chunk_size = [0, 10, 5]:上å±å®žæ—¶å‡ºå—粒度为 10×60=600ms,未æ¥ä¿¡æ¯ä¸º 5×60=300msis_final=True 强制输出最åŽä¸€ä¸ªå—æ–¹å¼ä¸€ï¼špip 安装(推è)
pip install funasr
# 如需使用工业预è®ç»ƒæ¨¡åž‹ï¼Œé¢å¤–安装
pip install -U modelscope huggingface_hub
æ–¹å¼äºŒï¼šæºç 安装
git clone https://github.com/alibaba/FunASR.git
cd FunASR
pip install -e ./
ä¾èµ–è¦æ±‚:
命令行方å¼ï¼š
funasr ++model=paraformer-zh \
++vad_model="fsmn-vad" \
++punc_model="ct-punc" \
++input=asr_example_zh.wav
Python API æ–¹å¼ï¼š
from funasr import AutoModel
# ä¸€é”®åŠ è½½ï¼Œè‡ªåŠ¨ä¸‹è½½æ¨¡åž‹
model = AutoModel(model="paraformer-zh")
res = model.generate(input="test.wav")
print(res[0]["text"])
from funasr import AutoModel
# 长音频需è¦å¼€å¯ VAD 自动切分
model = AutoModel(
model="paraformer-zh",
vad_model="fsmn-vad",
vad_kwargs={"max_single_segment_time": 30000}, # 最大30秒一段
punc_model="ct-punc",
)
# 支æŒä»»æ„时长音频
res = model.generate(
input="long_meeting_recording.wav",
batch_size_s=300, # åŠ¨æ€ batch,总时长 300s
)
# 输出带时间戳的完整文本
for item in res:
print(f"[{item['timestamp'][0][0]}ms] {item['text']}")
import pyaudio
from funasr import AutoModel
# åˆå§‹åŒ–æµå¼æ¨¡åž‹
model = AutoModel(model="paraformer-zh-streaming")
chunk_size = [0, 10, 5] # 600ms 延迟
# é…置音频æµ
p = pyaudio.PyAudio()
stream = p.open(
format=pyaudio.paInt16,
channels=1,
rate=16000,
input=True,
frames_per_buffer=9600 # 600ms @ 16kHz
)
cache = {}
print("开始实时转录...")
try:
while True:
# 读å–音频å—
data = stream.read(9600)
speech_chunk = np.frombuffer(data, dtype=np.int16)
# æµå¼æŽ¨ç†
res = model.generate(
input=speech_chunk,
cache=cache,
is_final=False,
chunk_size=chunk_size
)
if res[0]["text"]:
print(res[0]["text"], end="", flush=True)
except KeyboardInterrupt:
print("\nåœæ¢è½¬å½•")
stream.stop_stream()
stream.close()
p.terminate()
from funasr import AutoModel
model = AutoModel(model="iic/SenseVoiceSmall")
res = model.generate(
input="customer_service_call.wav",
language="auto",
)
text = res[0]["text"]
# è§£æžæƒ…æ„Ÿæ ‡ç¾
if "<|happy|>" in text:
emotion = "开心"
elif "<|angry|>" in text:
emotion = "生气"
elif "<|sad|>" in text:
emotion = "难过"
else:
emotion = "ä¸ç«‹"
print(f"识别结果:{text}")
print(f"情感:{emotion}")
| éƒ¨ç½²æ–¹å¼ | å¹³å° | 性能特点 | 适用场景 |
|---|---|---|---|
| Python SDK | CPU/GPU | çµæ´»æ˜“用 | 开呿µ‹è¯• |
| ONNX Runtime | è·¨å¹³å° | é«˜æ€§èƒ½æŽ¨ç† | 生产环境 |
| TensorRT | NVIDIA GPU | æžè‡´æ€§èƒ½ | 高并å‘场景 |
| 移动端 | Android/iOS | è½»é‡çº§ | 移动应用 |
| Web æœåŠ¡ | HTTP/WebSocket | 远程调用 | 云æœåŠ¡ |
# 䏿–‡ç¦»çº¿æ–‡ä»¶è½¬å†™æœåŠ¡ï¼ˆCPU)
docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.5
# 䏿–‡å®žæ—¶è¯éŸ³å¬å†™æœåŠ¡
docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-online-cpu-0.1.12
# å¯åЍæœåŠ¡
docker run -p 10095:10095 -it --privileged=true \
-v $PWD/funasr-runtime-resources:/workspace/models \
registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.5
# INT8 é‡åŒ–,推ç†é€Ÿåº¦æå‡ 2.3 å€ï¼Œç²¾åº¦æŸå¤± < 0.3%
from funasr_onnx import Paraformer
model = Paraformer(
model_dir,
batch_size=1,
quantize=True # å¯ç”¨é‡åŒ–
)
# æ ¹æ® GPU 显å˜è‡ªåŠ¨è°ƒæ•´ batch size
model.generate(
input="test.wav",
batch_size_s=60, # batch 总时长 60s,而éžå›ºå®šæ ·æœ¬æ•°
)
# æå‡ç‰¹å®šè¯æ±‡è¯†åˆ«å‡†ç¡®çއ
model.generate(
input="tech_conference.wav",
hotword='大è¯è¨€æ¨¡åž‹ 人工智能 深度å¦ä¹ Transformer'
)
# 䏿–‡ç¦»çº¿æ–‡ä»¶è½¬å†™æœåŠ¡ GPU 版本支æŒåŠ¨æ€ batch
# 长音频测试集上å•线 RTF=0.0076ï¼Œå¤šçº¿åŠ é€Ÿæ¯” 1200+
| 场景 | æŽ¨èæ¨¡åž‹ | 关键特性 |
|---|---|---|
| 会议转录 | paraformer-zh + vad + punc | é•¿éŸ³é¢‘åˆ‡åˆ†ã€æ ‡ç‚¹æ¢å¤ |
| 实时å—幕 | paraformer-zh-streaming | 低延迟æµå¼è¾“出 |
| 客æœè´¨æ£€ | SenseVoiceSmall | 情感识别ã€äº‹ä»¶æ£€æµ‹ |
| è¯éŸ³åŠ©æ‰‹ | fsmn-kws + paraformer | å”¤é†’è¯ + 识别 |
| 多è¯è¨€ç¿»è¯‘ | Whisper-large-v3 | 99 ç§è¯è¨€æ”¯æŒ |
| 声纹识别 | cam++ | 说è¯äººç¡®è®¤/分割 |
| å†…å®¹å®¡æ ¸ | SenseVoiceSmall | 音频事件检测 |
| 智能座舱 | SenseVoiceSmall | 多任务一体化 |
需求:
model = AutoModel(
model="paraformer-zh",
vad_model="fsmn-vad",
punc_model="ct-punc",
spk_model="cam++", # 说è¯äººåˆ†ç¦»
)
res = model.generate(
input="meeting_2h.wav",
batch_size_s=300,
)
# è¾“å‡ºæ ¼å¼ï¼š
# [å‘言人A] 10:05 我们需è¦è®¨è®ºä¸‹å£åº¦çš„ç›®æ ‡
# [å‘言人B] 10:07 我认为应该é‡ç‚¹å…³æ³¨ç”¨æˆ·ä½“验
需求:
model = AutoModel(model="iic/SenseVoiceSmall")
res = model.generate(
input=audio_stream,
language="auto",
)
text = res[0]["text"]
# 情感分æž
if "<|angry|>" in text or "<|sad|>" in text:
alert_manager() # 通知主管
# å…³é”®è¯æ£€æµ‹
keywords = ["投诉", "退款", "䏿»¡æ„", "举报"]
if any(kw in text for kw in keywords):
escalate_ticket() # å‡çº§å·¥å•
| 维度 | FunASR | Whisper |
|---|---|---|
| å¼€å‘团队 | 阿里巴巴达摩院 | OpenAI |
| 䏿–‡æ•ˆæžœ | âââââ ä¸“ä¸ºä¸æ–‡ä¼˜åŒ– | ââââ 通用模型 |
| 速度 | SenseVoice 15å€äºŽ Whisper-Large | 较慢 |
| 功能丰富度 | ASR+VAD+Punc+SER+AED+... | 仅 ASR+翻译 |
| 部署便利 | 一键 Docker,完整æœåС链 | 需自行æå»º |
| çƒè¯å¢žå¼º | ✅ æ”¯æŒ | âŒ ä¸æ”¯æŒ |
| å¼€æºåè®® | Apache 2.0 | MIT |
| 工具 | 特点 | 适用场景 |
|---|---|---|
| FunASR | 功能全é¢ã€å·¥ä¸šçº§ã€æŒç»æ›´æ–° | ä¼ä¸šåº”用ã€ç ”ç©¶ |
| PaddleSpeech | 百度出å“,Paddle ç”Ÿæ€ | Paddle 用户 |
| WeNet | è½»é‡ã€é«˜æ•ˆ | 边缘部署 |
| Kaldi | ä¼ ç»Ÿ ASR 框架 | 妿œ¯ç ”ç©¶ |
# 1. 安装
pip install funasr modelscope
# 2. 5 行代ç 上手
from funasr import AutoModel
model = AutoModel(model="paraformer-zh")
res = model.generate(input="test.wav")
print(res[0]["text"])
本文基于 FunASR 官方文档ã€GitHub 仓库和社区资料整ç†ï¼Œæ—¨åœ¨å¸®åЩ开å‘者全é¢äº†è§£è¿™ä¸€å¼ºå¤§çš„å¼€æºè¯éŸ³è¯†åˆ«å·¥å…·ç®±ã€‚
#FunASR #è¯éŸ³è¯†åˆ« #ASR #阿里巴巴 #达摩院 #å¼€æº #AI #Paraformer #SenseVoice #教程
还没有人回å¤