mirror of
https://github.com/modelscope/FunASR.git
synced 2026-10-12 02:19:18 +00:00
docs: make multilingual README entrypoints task-oriented
Signed-off-by: zhifu gao <[email protected]>
This commit is contained in:
@@ -63,17 +63,16 @@ from funasr import AutoModel
|
||||
model = AutoModel(model="FunAudioLLM/Fun-ASR-Nano-2512", device="cuda")
|
||||
result = model.generate(input="https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav")
|
||||
print(result[0]["text"])
|
||||
# 欢迎大家来体验达摩院推出的语音识别模型。
|
||||
```
|
||||
|
||||
For the separate 31-language checkpoint, use
|
||||
[Fun-ASR-MLT-Nano-2512](https://huggingface.co/FunAudioLLM/Fun-ASR-MLT-Nano-2512).
|
||||
Language coverage is checkpoint-specific, so Nano and MLT-Nano should be treated as distinct model choices.
|
||||
|
||||
On CPU (or for five-language ASR plus emotion and audio-event tags), use
|
||||
**SenseVoiceSmall**. The pipeline below composes SenseVoiceSmall with FSMN-VAD
|
||||
and CAM++; diarization is provided by the separate CAM++ model, not by the
|
||||
SenseVoiceSmall checkpoint:
|
||||
For a CPU-first example with five-language ASR plus emotion and audio-event
|
||||
tags, use **SenseVoiceSmall**. The pipeline below combines it with FSMN-VAD and
|
||||
CAM++ for speaker-aware VAD segments; these are not native speaker outputs of
|
||||
the SenseVoiceSmall checkpoint.
|
||||
See the [SenseVoice paper](https://arxiv.org/abs/2407.04051),
|
||||
[Hugging Face checkpoint](https://huggingface.co/FunAudioLLM/SenseVoiceSmall),
|
||||
and [GGUF edge checkpoint](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GGUF).
|
||||
@@ -82,7 +81,7 @@ and [GGUF edge checkpoint](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GG
|
||||
from funasr import AutoModel
|
||||
from funasr.utils.postprocess_utils import rich_transcription_postprocess
|
||||
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cuda") # use device="cpu" if you don't have a GPU
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cpu")
|
||||
result = model.generate(
|
||||
input="https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav",
|
||||
batch_size_s=300,
|
||||
@@ -93,13 +92,15 @@ for seg in result[0]["sentence_info"]:
|
||||
print(f"[{seg['start']/1000:.1f}s] Speaker {seg['spk']}: {rich_transcription_postprocess(seg['sentence'])}")
|
||||
```
|
||||
|
||||
**Output** — structured text with speaker labels, timestamps, and punctuation:
|
||||
```
|
||||
[0.6s] Speaker 0: 欢迎大家来体验达摩院推出的语音识别模型
|
||||
```
|
||||
This prints each returned segment's start time in seconds, anonymous speaker
|
||||
index, and text with SenseVoice tags removed. Text and segment boundaries depend
|
||||
on the audio and checkpoint; no fixed transcript is asserted here.
|
||||
|
||||
One `AutoModel` pipeline call coordinates the configured ASR, VAD, and speaker
|
||||
models and returns the combined result.
|
||||
CAM++ extracts `spk_embedding` vectors. `AutoModel` clusters those embeddings
|
||||
and assigns speaker indices to VAD segments. Indices are local to a recording,
|
||||
not known-person identities. See the [SDK contract](./docs/python_api.md) for
|
||||
the component and result boundaries. Change to `device="cuda"` only after
|
||||
verifying a compatible GPU environment as described above.
|
||||
|
||||
### Scale & deploy the flagship
|
||||
|
||||
@@ -120,23 +121,22 @@ results = model.generate(["audio1.wav", "audio2.wav"], language="auto")
|
||||
|
||||
### Why FunASR?
|
||||
|
||||
Whisper is a single model; **FunASR is a toolkit** — you pick the right model
|
||||
per job: **Fun-ASR-Nano** (Chinese, English, Japanese, and Chinese dialects;
|
||||
GPU), **Fun-ASR-MLT-Nano** (31 languages), **SenseVoiceSmall** (five-language
|
||||
ASR plus emotion and audio events), and **Paraformer** (low-latency streaming).
|
||||
The table shows toolkit-level capabilities and names the model or pipeline that
|
||||
provides each one:
|
||||
FunASR is a toolkit: choose the task, checkpoint, and runtime separately.
|
||||
Support in one model or adapter does not imply support in every serving backend.
|
||||
|
||||
| | FunASR (toolkit) | Whisper | Cloud APIs |
|
||||
| Task | Checkpoint or pipeline | Runtime entrypoint | Important limitation |
|
||||
|---|---|---|---|
|
||||
| Top speed | **340x realtime** (Fun-ASR-Nano + vLLM) | 13x realtime | ~1x realtime |
|
||||
| Speaker ID | ✅ via VAD + CAM++ pipeline | ❌ Needs pyannote | ✅ Extra cost |
|
||||
| Emotion | ✅ via SenseVoice | ❌ | ❌ |
|
||||
| Languages | Checkpoint-specific (for example Qwen3-ASR 52, MLT-Nano 31, Nano zh/en/ja) | 57 | Varies |
|
||||
| Streaming | ✅ WebSocket (Paraformer) | ❌ | ✅ |
|
||||
| CPU viable | ✅ 17x realtime (SenseVoice) | ❌ Too slow | N/A |
|
||||
| Self-hosted | ✅ Yes (toolkit: MIT; model licenses vary) | ✅ MIT license | ❌ Cloud only |
|
||||
| Cost | Free | Free | $0.006/min+ |
|
||||
| File transcription with emotion/event tags | SenseVoiceSmall | Python `AutoModel`, CPU or GPU | Five-language checkpoint; tags do not identify speakers. |
|
||||
| LLM-based file transcription | Fun-ASR-Nano | `AutoModel`; split-engine `AutoModelVLLM` for the documented GPU path | Base Nano covers zh/en/ja and Chinese dialects/accents; timestamp support depends on checkpoint and path. |
|
||||
| Broader multilingual transcription | Fun-ASR-MLT-Nano | Python `AutoModel` | Separate 31-language checkpoint; do not transfer its coverage to base Nano. |
|
||||
| Chunked live transcription | Paraformer-zh-streaming | Streaming SDK or runtime WebSocket service | Use the streaming checkpoint and per-session cache, not an offline checkpoint. |
|
||||
| Speaker-aware file transcription | SenseVoiceSmall + FSMN-VAD + CAM++ | `AutoModel` with VAD and embedding clustering | Anonymous indices within a recording, not enrolled-speaker identification. |
|
||||
| Joint text, timestamps, and speakers | MOSS-Transcribe-Diarize, third-party OpenMOSS | FunASR adapter or upstream backend in the MOSS guide | Offline, recording-local anonymous labels; no external VAD/speaker pipeline for its unified path. |
|
||||
| Native CPU/edge transcription | Fun-ASR-Nano or SenseVoiceSmall GGUF | llama.cpp runtime | Requires matching converted weights; GGUF is not a Python `AutoModel` checkpoint. |
|
||||
|
||||
See the [Model Zoo](./model_zoo/readme.md) and [deployment matrix](./docs/deployment_matrix.md)
|
||||
for checkpoint, interface, and licensing boundaries. Benchmark on your own audio
|
||||
and hardware before choosing a runtime.
|
||||
|
||||
Trying FunASR for the first time? Use the [Colab quickstart](./examples/colab/) before setting up a local environment. Choosing a first model? Start with the [model selection guide](./docs/model_selection.md). Planning a switch from Whisper or a cloud ASR provider? Use the [migration guide](./docs/migration_from_whisper.md) and [benchmark example](./examples/migration/) to test representative audio, map features, and roll out safely.
|
||||
|
||||
@@ -162,12 +162,17 @@ Requirements: Python ≥ 3.8. Install PyTorch + torchaudio first ([pytorch.org](
|
||||
|
||||
## Model Zoo
|
||||
|
||||
This list includes third-party models. **OpenMOSS** publishes MOSS-Transcribe-Diarize;
|
||||
FunASR provides an adapter, not ownership of its weights. Its unified path is
|
||||
offline, with anonymous labels scoped to each recording, not realtime or
|
||||
known-person identification. Model licenses are separate from the toolkit's MIT license.
|
||||
|
||||
| Model | Task | Languages | Params | Links |
|
||||
|-------|------|-----------|--------|-------|
|
||||
| **Fun-ASR-Nano** | ASR | zh/en/ja + Chinese dialects and accents | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-2512) [GGUF](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-GGUF) |
|
||||
| **Fun-ASR-MLT-Nano** | ASR | 31 languages | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-MLT-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-MLT-Nano-2512) |
|
||||
| **SenseVoiceSmall** | ASR + emotion + events | zh/en/ja/ko/yue | 234M | [⭐](https://www.modelscope.cn/models/iic/SenseVoiceSmall) [🤗](https://huggingface.co/FunAudioLLM/SenseVoiceSmall) [GGUF](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GGUF) [paper](https://arxiv.org/abs/2407.04051) |
|
||||
| **MOSS-Transcribe-Diarize** | Offline ASR + timestamps + anonymous speakers | See official card | See official card | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [guide](./docs/moss_transcribe_diarize.md) |
|
||||
| **MOSS-Transcribe-Diarize** | Third-party OpenMOSS: offline ASR + timestamps + anonymous speakers | See official card | See official card | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [guide](./docs/moss_transcribe_diarize.md) |
|
||||
| **Paraformer-zh** | ASR + timestamps | zh/en | 220M | [⭐](https://www.modelscope.cn/models/iic/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/summary) [🤗](https://huggingface.co/funasr/paraformer-zh) |
|
||||
| Paraformer-zh-streaming | Streaming ASR | zh/en | 220M | [⭐](https://modelscope.cn/models/iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/summary) [🤗](https://huggingface.co/funasr/paraformer-zh-streaming) |
|
||||
| Qwen3-ASR | ASR, 52 languages | multilingual | 1.7B | [usage](examples/industrial_data_pretraining/qwen3_asr) |
|
||||
@@ -176,7 +181,7 @@ Requirements: Python ≥ 3.8. Install PyTorch + torchaudio first ([pytorch.org](
|
||||
| Whisper-large-v3-turbo | ASR + translation | multilingual | 809M | [usage](examples/industrial_data_pretraining/whisper) |
|
||||
| ct-punc | Punctuation | zh/en | 290M | [⭐](https://modelscope.cn/models/iic/punc_ct-transformer_cn-en-common-vocab471067-large/summary) [🤗](https://huggingface.co/funasr/ct-punc) |
|
||||
| fsmn-vad | VAD | zh/en | 0.4M | [⭐](https://modelscope.cn/models/iic/speech_fsmn_vad_zh-cn-16k-common-pytorch/summary) [🤗](https://huggingface.co/funasr/fsmn-vad) |
|
||||
| cam++ | Speaker diarization | — | 7.2M | [⭐](https://modelscope.cn/models/iic/speech_campplus_sv_zh-cn_16k-common/summary) [🤗](https://huggingface.co/funasr/campplus) |
|
||||
| cam++ | Speaker embeddings (pipeline component) | — | 7.2M | [⭐](https://modelscope.cn/models/iic/speech_campplus_sv_zh-cn_16k-common/summary) [🤗](https://huggingface.co/funasr/campplus) |
|
||||
| emotion2vec+large | Emotion recognition | — | 300M | [⭐](https://modelscope.cn/models/iic/emotion2vec_plus_large/summary) [🤗](https://huggingface.co/emotion2vec/emotion2vec_plus_large) |
|
||||
|
||||
---
|
||||
@@ -324,17 +329,16 @@ inference on physical Blackwell hardware.
|
||||
|
||||
## Benchmark
|
||||
|
||||
> 184 long-form audio files (192 min). [Full report →](https://modelscope.github.io/FunASR/benchmark.html) · [RTFx and reproducibility notes →](./docs/benchmark/rtf_reproducibility.md)
|
||||
The [historical benchmark report](https://modelscope.github.io/FunASR/benchmark.html)
|
||||
and [split-engine measurements](./docs/vllm_guide.md#benchmark) retain their
|
||||
original results. They are separate records, not universal speed rankings or
|
||||
production capacity guarantees.
|
||||
|
||||
| Model | Chinese CER ↓ | GPU Speed | CPU Speed | vs Whisper-large-v3 |
|
||||
|-------|------|-----------|-----------|-------------------|
|
||||
| **Fun-ASR-Nano** (vLLM) | **8.20%** | **340x** realtime | — | 🚀 **26x faster** |
|
||||
| **SenseVoice-Small** | **7.81%** | **170x** realtime | **17x** realtime | 🚀 **13x faster** |
|
||||
| **Paraformer-Large** | 10.18% | **120x** realtime | **15x** realtime | 🚀 **9x faster** |
|
||||
| Whisper-large-v3-turbo | 21.71% | 46x realtime | ❌ | 3.4x faster |
|
||||
| Whisper-large-v3 | 20.02% | 13x realtime | ❌ | baseline |
|
||||
|
||||
> **Key takeaway:** FunASR models run on CPU faster than Whisper runs on GPU.
|
||||
Use the [RTFx and reproducibility notes](./docs/benchmark/rtf_reproducibility.md)
|
||||
to compare checkpoint/revision, audio set, hardware, batching, warmup, timing
|
||||
scope, and CER/WER. Offline throughput is not streaming latency. The
|
||||
[migration benchmark example](./examples/migration/) helps measure your own
|
||||
recordings with the same evaluation scope.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+46
-37
@@ -31,26 +31,34 @@
|
||||
## クイックスタート
|
||||
|
||||
```bash
|
||||
pip install funasr
|
||||
python -m pip install torch torchaudio
|
||||
python -m pip install funasr
|
||||
```
|
||||
|
||||
以下は公開サンプルを使う CPU 向けの例です。GPU を使う場合は
|
||||
[インストールガイド](./docs/installation/installation.md) に従って互換性のある
|
||||
PyTorch/CUDA 環境を用意し、`torch.cuda.is_available()` を確認してから
|
||||
`device="cuda"` に変更してください。
|
||||
|
||||
```python
|
||||
from funasr import AutoModel
|
||||
from funasr.utils.postprocess_utils import rich_transcription_postprocess
|
||||
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cuda")
|
||||
result = model.generate(input="meeting.wav")
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cpu")
|
||||
result = model.generate(input="https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav")
|
||||
|
||||
for seg in result[0]["sentence_info"]:
|
||||
print(f"[{seg['start']/1000:.1f}s] 話者{seg['spk']}: {rich_transcription_postprocess(seg['sentence'])}")
|
||||
```
|
||||
|
||||
**出力** — 話者ラベル・タイムスタンプ・句読点付きの構造化テキスト:
|
||||
```
|
||||
[00:00.4 → 00:03.8] 話者0: Q3の計画について話し合いましょう。
|
||||
[00:04.2 → 00:07.1] 話者1: いいですね。3つのポイントがあります。
|
||||
[00:07.5 → 00:12.3] 話者0: どうぞ。あと30分あります。
|
||||
```
|
||||
実際に返された VAD 区間の開始時刻(秒)、匿名話者番号、SenseVoice タグを
|
||||
除いたテキストを表示します。テキストや区間は音声と checkpoint に依存し、
|
||||
ここでは固定の認識結果を示していません。
|
||||
|
||||
これは1回の `AutoModel` パイプライン呼び出しですが、SenseVoiceSmall、
|
||||
FSMN-VAD、CAM++という独立したモデルを組み合わせています。話者分離は
|
||||
SenseVoiceSmall自体ではなく、CAM++によって提供されます。
|
||||
CAM++ は `spk_embedding` ベクトルを抽出し、`AutoModel` がクラスタリングと
|
||||
VAD 区間への話者割り当てを行います。番号は録音内だけで有効で、既知の人物の
|
||||
識別や SenseVoiceSmall 単体の出力ではありません。
|
||||
詳細は [SDK 契約](./docs/python_api.md) を参照してください。
|
||||
|
||||
初めて使う場合は [Colab クイックスタート](./examples/colab/README_ja.md) から試せます。どのモデルを選ぶか迷う場合は [モデル選択ガイド](./docs/model_selection_ja.md) を参照してください。
|
||||
|
||||
@@ -60,22 +68,21 @@ SenseVoiceSmall自体ではなく、CAM++によって提供されます。
|
||||
|
||||
### なぜFunASRを選ぶのか?
|
||||
|
||||
Whisper は単一モデルですが、**FunASR はツールキット**です——用途に応じて
|
||||
**Fun-ASR-Nano**(中・英・日と中国語方言・地域アクセント、GPU)、
|
||||
**Fun-ASR-MLT-Nano**(31言語)、**SenseVoiceSmall**(5言語ASRと感情・
|
||||
音声イベント)、**Paraformer**(低遅延ストリーミング)を選べます。
|
||||
下の表はツールキット全体の機能と、それを提供するモデルまたはパイプラインを示します:
|
||||
FunASR はツールキットです。タスク、checkpoint、ランタイムを別々に選びます。
|
||||
あるモデルやアダプターの機能が、すべての配信バックエンドで使えるとは限りません。
|
||||
|
||||
| | FunASR(ツールキット) | Whisper | クラウドAPI |
|
||||
| タスク | Checkpoint またはパイプライン | ランタイムの入口 | 主な制約 |
|
||||
|---|---|---|---|
|
||||
| 最高速度 | **340倍リアルタイム**(Fun-ASR-Nano + vLLM) | 13倍リアルタイム | 〜1倍リアルタイム |
|
||||
| 話者認識 | ✅ VAD + CAM++パイプライン | ❌ pyannoteが必要 | ✅ 追加料金 |
|
||||
| 感情認識 | ✅ SenseVoice による | ❌ | ❌ |
|
||||
| 言語数 | チェックポイントごとに異なる(例:Qwen3-ASR 52、MLT-Nano 31、Nano 中/英/日) | 57 | サービスにより異なる |
|
||||
| ストリーミング | ✅ WebSocket(Paraformer) | ❌ | ✅ |
|
||||
| CPU対応 | ✅ 17倍リアルタイム(SenseVoice) | ❌ 遅すぎる | 該当なし |
|
||||
| セルフホスト | ✅ 対応(ツールキット: MIT、モデルごとに異なる) | ✅ MITライセンス | ❌ クラウドのみ |
|
||||
| コスト | 無料 | 無料 | $0.006/分〜 |
|
||||
| ファイル認識と感情・イベントタグ | SenseVoiceSmall | Python `AutoModel`、CPU または GPU | 5言語の checkpoint。タグは話者の身元を示しません。 |
|
||||
| LLM によるファイル認識 | Fun-ASR-Nano | `AutoModel`、または文書化された GPU 分離エンジン `AutoModelVLLM` | 基本 Nano は中・英・日と中国語方言・アクセント。timestamp は checkpoint と経路に依存します。 |
|
||||
| より多くの言語のファイル認識 | Fun-ASR-MLT-Nano | Python `AutoModel` | 独立した31言語 checkpoint。その対応言語を基本 Nano に当てはめないでください。 |
|
||||
| チャンク単位のライブ認識 | Paraformer-zh-streaming | ストリーミング SDK または runtime WebSocket | ストリーミング checkpoint とセッション別 cache が必要です。 |
|
||||
| 話者付きファイル認識 | SenseVoiceSmall + FSMN-VAD + CAM++ | `AutoModel` の VAD と埋め込みクラスタリング | 番号は録音内の匿名ラベルで、登録済み人物の識別ではありません。 |
|
||||
| テキスト・時刻・話者の同時生成 | 第三者 OpenMOSS の MOSS-Transcribe-Diarize | MOSS ガイドの FunASR adapter または上流バックエンド | オフライン、録音内の匿名ラベル。統合経路に外部 VAD/話者モデルは付けません。 |
|
||||
| ネイティブ CPU/エッジ認識 | Fun-ASR-Nano または SenseVoiceSmall GGUF | llama.cpp runtime | 対応する変換済み重みが必要。GGUF は Python `AutoModel` 用 checkpoint ではありません。 |
|
||||
|
||||
[Model Zoo](./model_zoo/readme.md) と [デプロイ方式](./docs/deployment_matrix_ja.md)
|
||||
でインターフェースとライセンスの制約を確認し、対象音声・ハードウェアで評価してください。
|
||||
|
||||
---
|
||||
|
||||
@@ -83,17 +90,14 @@ Whisper は単一モデルですが、**FunASR はツールキット**です—
|
||||
|
||||
## ベンチマーク
|
||||
|
||||
> 184件の長時間音声(計192分)。[詳細レポート →](https://modelscope.github.io/FunASR/benchmark.html)
|
||||
[過去の評価レポート](https://modelscope.github.io/FunASR/benchmark.html) と
|
||||
[分離エンジンの測定](./docs/vllm_guide.md#benchmark) に元の結果を残しています。
|
||||
別々の記録であり、一般的な速度順位や本番容量を保証するものではありません。
|
||||
|
||||
| モデル | 中国語 CER ↓ | GPU速度 | CPU速度 | Whisper-large-v3比 |
|
||||
|--------|------|---------|---------|-------------------|
|
||||
| **Fun-ASR-Nano**(vLLM) | **8.20%** | **340倍**リアルタイム | — | 🚀 **26倍高速** |
|
||||
| **SenseVoice-Small** | **7.81%** | **170倍**リアルタイム | **17倍**リアルタイム | 🚀 **13倍高速** |
|
||||
| **Paraformer-Large** | 10.18% | **120倍**リアルタイム | **15倍**リアルタイム | 🚀 **9倍高速** |
|
||||
| Whisper-large-v3-turbo | 21.71% | 46倍リアルタイム | ❌ | 3.4倍高速 |
|
||||
| Whisper-large-v3 | 20.02% | 13倍リアルタイム | ❌ | ベースライン |
|
||||
|
||||
> **ポイント:** FunASRのCPU速度は、WhisperのGPU速度より速い。
|
||||
[RTFx と再現性の説明](./docs/benchmark/rtf_reproducibility.md) に従い、
|
||||
checkpoint/revision、音声セット、ハードウェア、バッチ、ウォームアップ、計測範囲、
|
||||
CER/WER をそろえて比較してください。オフラインのスループットはストリーミングの
|
||||
遅延ではありません。[移行評価の例](./examples/migration/) で自分の録音を評価できます。
|
||||
|
||||
---
|
||||
|
||||
@@ -121,12 +125,17 @@ pip install funasr
|
||||
|
||||
## モデル一覧
|
||||
|
||||
第三者モデルも含みます。MOSS-Transcribe-Diarize の公開元は **OpenMOSS** で、
|
||||
FunASR はアダプターを提供します。統合経路はオフラインで、匿名話者ラベルは
|
||||
録音内だけで有効です。リアルタイム処理や既知の人物の識別ではありません。
|
||||
モデルのライセンスはツールキットの MIT ライセンスとは別に確認してください。
|
||||
|
||||
| モデル | タスク | 言語 | パラメータ | リンク |
|
||||
|--------|--------|------|-----------|--------|
|
||||
| **Fun-ASR-Nano** | 認識 | 中/英/日 + 中国語方言 | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-2512) [GGUF](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-GGUF) |
|
||||
| **Fun-ASR-MLT-Nano** | 認識 | 31言語 | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-MLT-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-MLT-Nano-2512) |
|
||||
| **SenseVoiceSmall** | 認識 + 感情 + イベント | 中/英/日/韓/粤 | 234M | [⭐](https://www.modelscope.cn/models/iic/SenseVoiceSmall) [🤗](https://huggingface.co/FunAudioLLM/SenseVoiceSmall) [GGUF](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GGUF) |
|
||||
| **MOSS-Transcribe-Diarize** | オフライン認識 + タイムスタンプ + 匿名話者 | 公式モデルカードを参照 | 公式モデルカードを参照 | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [ガイド](./docs/moss_transcribe_diarize.md) |
|
||||
| **MOSS-Transcribe-Diarize** | 第三者 OpenMOSS:オフライン認識 + タイムスタンプ + 匿名話者 | 公式モデルカードを参照 | 公式モデルカードを参照 | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [ガイド](./docs/moss_transcribe_diarize.md) |
|
||||
| **Paraformer-zh** | 認識 + タイムスタンプ | 中/英 | 220M | [⭐](https://www.modelscope.cn/models/iic/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/summary) [🤗](https://huggingface.co/funasr/paraformer-zh) |
|
||||
| Qwen3-ASR | 認識、52言語 | 多言語 | 1.7B | [使用法](examples/industrial_data_pretraining/qwen3_asr) |
|
||||
| GLM-ASR-Nano | 認識、17言語 | 多言語 | 1.5B | [使用法](examples/industrial_data_pretraining/glm_asr) |
|
||||
|
||||
+45
-37
@@ -31,26 +31,33 @@
|
||||
## 빠른 시작
|
||||
|
||||
```bash
|
||||
pip install funasr
|
||||
python -m pip install torch torchaudio
|
||||
python -m pip install funasr
|
||||
```
|
||||
|
||||
아래는 공개 샘플을 사용하는 CPU 우선 예제입니다. GPU를 사용하려면
|
||||
[설치 가이드](./docs/installation/installation.md)에 따라 호환되는 PyTorch/CUDA
|
||||
환경을 준비하고 `torch.cuda.is_available()`을 확인한 뒤 `device="cuda"`로 바꾸세요.
|
||||
|
||||
```python
|
||||
from funasr import AutoModel
|
||||
from funasr.utils.postprocess_utils import rich_transcription_postprocess
|
||||
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cuda")
|
||||
result = model.generate(input="meeting.wav")
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cpu")
|
||||
result = model.generate(input="https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav")
|
||||
|
||||
for seg in result[0]["sentence_info"]:
|
||||
print(f"[{seg['start']/1000:.1f}s] 화자{seg['spk']}: {rich_transcription_postprocess(seg['sentence'])}")
|
||||
```
|
||||
|
||||
**출력** — 화자 라벨, 타임스탬프, 구두점이 포함된 구조화된 텍스트:
|
||||
```
|
||||
[00:00.4 → 00:03.8] 화자0: Q3 계획에 대해 논의하겠습니다.
|
||||
[00:04.2 → 00:07.1] 화자1: 좋습니다. 세 가지 포인트가 있습니다.
|
||||
[00:07.5 → 00:12.3] 화자0: 말씀하세요. 30분 남았습니다.
|
||||
```
|
||||
실제로 반환된 VAD 구간의 시작 시각(초), 익명 화자 번호, SenseVoice 태그를 제거한
|
||||
텍스트를 출력합니다. 텍스트와 구간은 오디오와 checkpoint에 따라 달라지므로
|
||||
고정된 인식 결과를 제시하지 않습니다.
|
||||
|
||||
한 번의 `AutoModel` 파이프라인 호출이지만, SenseVoiceSmall, FSMN-VAD,
|
||||
CAM++라는 독립된 모델을 조합합니다. 화자 분리는 SenseVoiceSmall 자체가 아니라
|
||||
CAM++에서 제공합니다.
|
||||
CAM++는 `spk_embedding` 벡터를 추출하고, `AutoModel`이 클러스터링하여 VAD
|
||||
구간에 화자 번호를 할당합니다. 번호는 해당 녹음 안에서만 유효하며 알려진 인물의
|
||||
신원이나 SenseVoiceSmall 단독 출력이 아닙니다. 자세한 내용은
|
||||
[SDK 계약](./docs/python_api.md)을 참고하세요.
|
||||
|
||||
처음 사용한다면 [Colab 빠른 시작](./examples/colab/README_ko.md)으로 먼저 확인할 수 있습니다. 어떤 모델을 선택할지 고민된다면 [모델 선택 가이드](./docs/model_selection_ko.md)를 참고하세요.
|
||||
|
||||
@@ -60,22 +67,21 @@ CAM++에서 제공합니다.
|
||||
|
||||
### 왜 FunASR인가?
|
||||
|
||||
Whisper는 단일 모델이지만, **FunASR는 툴킷**입니다. 용도에 맞게
|
||||
**Fun-ASR-Nano**(중국어/영어/일본어 및 중국어 방언/지역 억양, GPU),
|
||||
**Fun-ASR-MLT-Nano**(31개 언어), **SenseVoiceSmall**(5개 언어 ASR와
|
||||
감정·오디오 이벤트), **Paraformer**(저지연 스트리밍)를 선택하세요.
|
||||
아래 표는 툴킷 전체의 기능과 이를 제공하는 모델 또는 파이프라인을 보여 줍니다:
|
||||
FunASR는 툴킷입니다. 작업, checkpoint, 런타임을 각각 선택해야 합니다.
|
||||
한 모델이나 어댑터가 지원하는 기능이 모든 서빙 백엔드에서 지원되는 것은 아닙니다.
|
||||
|
||||
| | FunASR(툴킷) | Whisper | 클라우드 API |
|
||||
| 작업 | Checkpoint 또는 파이프라인 | 런타임 진입점 | 주요 제한 |
|
||||
|---|---|---|---|
|
||||
| 최고 속도 | **340배 실시간**(Fun-ASR-Nano + vLLM) | 13배 실시간 | ~1배 실시간 |
|
||||
| 화자 인식 | ✅ VAD + CAM++ 파이프라인 | ❌ pyannote 필요 | ✅ 추가 비용 |
|
||||
| 감정 인식 | ✅ SenseVoice 제공 | ❌ | ❌ |
|
||||
| 언어 수 | 체크포인트별 상이(예: Qwen3-ASR 52, MLT-Nano 31, Nano 중/영/일) | 57개 | 서비스마다 다름 |
|
||||
| 스트리밍 | ✅ WebSocket(Paraformer) | ❌ | ✅ |
|
||||
| CPU 사용 | ✅ 17배 실시간(SenseVoice) | ❌ 너무 느림 | 해당 없음 |
|
||||
| 자체 호스팅 | ✅ 지원 (툴킷: MIT, 모델별 상이) | ✅ MIT 라이선스 | ❌ 클라우드만 |
|
||||
| 비용 | 무료 | 무료 | $0.006/분~ |
|
||||
| 파일 전사와 감정/이벤트 태그 | SenseVoiceSmall | Python `AutoModel`, CPU 또는 GPU | 5개 언어 checkpoint이며 태그는 화자 신원을 나타내지 않습니다. |
|
||||
| LLM 기반 파일 전사 | Fun-ASR-Nano | `AutoModel`, 또는 문서의 GPU 분리 엔진 `AutoModelVLLM` | 기본 Nano는 중/영/일 및 중국어 방언/억양을 지원하며 timestamp는 checkpoint와 경로에 따라 다릅니다. |
|
||||
| 더 많은 언어의 파일 전사 | Fun-ASR-MLT-Nano | Python `AutoModel` | 별도의 31개 언어 checkpoint이며 기본 Nano에 같은 범위를 적용하지 않습니다. |
|
||||
| 청크 단위 실시간 전사 | Paraformer-zh-streaming | 스트리밍 SDK 또는 runtime WebSocket | 스트리밍 checkpoint와 세션별 cache가 필요하며 오프라인 checkpoint로 대체할 수 없습니다. |
|
||||
| 화자별 파일 전사 | SenseVoiceSmall + FSMN-VAD + CAM++ | `AutoModel`의 VAD와 임베딩 클러스터링 | 녹음 안의 익명 번호이며 등록된 인물의 신원 식별이 아닙니다. |
|
||||
| 텍스트, 시각, 화자 공동 생성 | 제3자 OpenMOSS의 MOSS-Transcribe-Diarize | MOSS 가이드의 FunASR adapter 또는 업스트림 백엔드 | 오프라인, 녹음 내 익명 라벨이며 통합 경로에 외부 VAD/화자 모델을 붙이지 않습니다. |
|
||||
| 네이티브 CPU/엣지 전사 | Fun-ASR-Nano 또는 SenseVoiceSmall GGUF | llama.cpp runtime | 호환되는 변환 가중치가 필요하며 GGUF는 Python `AutoModel`용 checkpoint가 아닙니다. |
|
||||
|
||||
[Model Zoo](./model_zoo/readme.md)와 [배포 매트릭스](./docs/deployment_matrix_ko.md)에서
|
||||
인터페이스와 라이선스 제한을 확인하고 대상 오디오와 하드웨어로 평가하세요.
|
||||
|
||||
---
|
||||
|
||||
@@ -83,17 +89,14 @@ Whisper는 단일 모델이지만, **FunASR는 툴킷**입니다. 용도에 맞
|
||||
|
||||
## 벤치마크
|
||||
|
||||
> 184개 장시간 오디오(총 192분). [상세 보고서 →](https://modelscope.github.io/FunASR/benchmark.html)
|
||||
[기존 평가 보고서](https://modelscope.github.io/FunASR/benchmark.html)와
|
||||
[분리 엔진 측정](./docs/vllm_guide.md#benchmark)에 원래 결과를 보존합니다.
|
||||
서로 다른 기록이며 보편적인 속도 순위나 운영 용량을 보장하지 않습니다.
|
||||
|
||||
| 모델 | 중국어 CER ↓ | GPU 속도 | CPU 속도 | Whisper-large-v3 대비 |
|
||||
|------|------|----------|----------|---------------------|
|
||||
| **Fun-ASR-Nano**(vLLM) | **8.20%** | **340배** 실시간 | — | 🚀 **26배 빠름** |
|
||||
| **SenseVoice-Small** | **7.81%** | **170배** 실시간 | **17배** 실시간 | 🚀 **13배 빠름** |
|
||||
| **Paraformer-Large** | 10.18% | **120배** 실시간 | **15배** 실시간 | 🚀 **9배 빠름** |
|
||||
| Whisper-large-v3-turbo | 21.71% | 46배 실시간 | ❌ | 3.4배 빠름 |
|
||||
| Whisper-large-v3 | 20.02% | 13배 실시간 | ❌ | 기준선 |
|
||||
|
||||
> **핵심:** FunASR의 CPU 속도가 Whisper의 GPU 속도보다 빠릅니다.
|
||||
[RTFx와 재현성 설명](./docs/benchmark/rtf_reproducibility.md)에 따라
|
||||
checkpoint/revision, 오디오 집합, 하드웨어, 배치, 워밍업, 측정 범위, CER/WER를
|
||||
맞춰 비교하세요. 오프라인 처리량은 스트리밍 지연이 아닙니다.
|
||||
[마이그레이션 평가 예제](./examples/migration/)로 자신의 녹음을 측정할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
@@ -121,12 +124,17 @@ pip install funasr
|
||||
|
||||
## 모델 목록
|
||||
|
||||
제3자 모델도 포함합니다. MOSS-Transcribe-Diarize의 배포 주체는 **OpenMOSS**이며
|
||||
FunASR는 어댑터를 제공합니다. 통합 경로는 오프라인이고 익명 화자 라벨은 해당 녹음
|
||||
안에서만 유효합니다. 실시간 처리나 알려진 인물의 신원 식별이 아닙니다.
|
||||
모델 라이선스는 툴킷의 MIT 라이선스와 별도로 확인해야 합니다.
|
||||
|
||||
| 모델 | 작업 | 언어 | 파라미터 | 링크 |
|
||||
|------|------|------|---------|------|
|
||||
| **Fun-ASR-Nano** | 인식 | 중/영/일 + 중국어 방언 | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-2512) [GGUF](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-GGUF) |
|
||||
| **Fun-ASR-MLT-Nano** | 인식 | 31개 언어 | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-MLT-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-MLT-Nano-2512) |
|
||||
| **SenseVoiceSmall** | 인식 + 감정 + 이벤트 | 중/영/일/한/광둥어 | 234M | [⭐](https://www.modelscope.cn/models/iic/SenseVoiceSmall) [🤗](https://huggingface.co/FunAudioLLM/SenseVoiceSmall) [GGUF](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GGUF) |
|
||||
| **MOSS-Transcribe-Diarize** | 오프라인 인식 + 타임스탬프 + 익명 화자 | 공식 모델 카드 참조 | 공식 모델 카드 참조 | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [가이드](./docs/moss_transcribe_diarize.md) |
|
||||
| **MOSS-Transcribe-Diarize** | 제3자 OpenMOSS: 오프라인 인식 + 타임스탬프 + 익명 화자 | 공식 모델 카드 참조 | 공식 모델 카드 참조 | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [가이드](./docs/moss_transcribe_diarize.md) |
|
||||
| **Paraformer-zh** | 인식 + 타임스탬프 | 중/영 | 220M | [⭐](https://www.modelscope.cn/models/iic/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/summary) [🤗](https://huggingface.co/funasr/paraformer-zh) |
|
||||
| Qwen3-ASR | 인식, 52개 언어 | 다국어 | 1.7B | [사용법](examples/industrial_data_pretraining/qwen3_asr) |
|
||||
| GLM-ASR-Nano | 인식, 17개 언어 | 다국어 | 1.5B | [사용법](examples/industrial_data_pretraining/glm_asr) |
|
||||
|
||||
+35
-34
@@ -53,11 +53,13 @@ PY
|
||||
只有这里输出 `True` 时才使用 `device="cuda"`;否则请先使用
|
||||
`device="cpu"`,或重新安装匹配 CUDA 的 PyTorch wheel。
|
||||
|
||||
以下 SenseVoiceSmall 示例先使用 CPU,并组合 FSMN-VAD 与 CAM++。
|
||||
|
||||
```python
|
||||
from funasr import AutoModel
|
||||
from funasr.utils.postprocess_utils import rich_transcription_postprocess
|
||||
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cuda")
|
||||
model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cpu")
|
||||
result = model.generate(input="https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav")
|
||||
|
||||
# AutoModel pipeline 返回带说话人 id 和时间戳的 VAD 分段:
|
||||
@@ -65,14 +67,13 @@ for seg in result[0]["sentence_info"]:
|
||||
print(f"[{seg['start']/1000:.1f}s] 说话人{seg['spk']}: {rich_transcription_postprocess(seg['sentence'])}")
|
||||
```
|
||||
|
||||
**输出** — 带说话人标签、时间戳和标点的结构化文本:
|
||||
```
|
||||
[0.6s] 说话人0: 欢迎大家来体验达摩院推出的语音识别模型
|
||||
```
|
||||
代码打印实际返回的 VAD 分段起点(秒)、匿名说话人编号和去除 SenseVoice
|
||||
标签后的文本。文本与分段边界取决于音频和 checkpoint,这里不预设转写结果。
|
||||
|
||||
这是一次 `AutoModel` pipeline 调用,实际组合了 SenseVoiceSmall、FSMN-VAD
|
||||
和 CAM++ 三个独立模型;说话人分离由 CAM++ 提供,并非 SenseVoiceSmall
|
||||
checkpoint 的内置输出。
|
||||
CAM++ 提取 `spk_embedding` 说话人嵌入,`AutoModel` 再聚类并为 VAD 分段分配
|
||||
说话人编号;编号仅在当前录音内有效,不是已知人物身份,也不是 SenseVoiceSmall
|
||||
checkpoint 的内置输出。组件和返回字段见 [SDK 契约](./docs/python_api_zh.md)。
|
||||
需要 GPU 时,先按上文验证环境,再将 `device` 改为 `"cuda"`。
|
||||
SenseVoice 论文见 [arXiv:2407.04051](https://arxiv.org/abs/2407.04051),
|
||||
模型见 [Hugging Face checkpoint](https://huggingface.co/FunAudioLLM/SenseVoiceSmall),
|
||||
边缘部署可用 [GGUF checkpoint](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GGUF)。
|
||||
@@ -110,22 +111,21 @@ results = model.generate(["audio1.wav", "audio2.wav"], language="auto")
|
||||
|
||||
### 为什么选 FunASR?
|
||||
|
||||
Whisper 是单个模型,**FunASR 是一个工具箱**——按场景挑模型:
|
||||
**Fun-ASR-Nano**(中/英/日及中文方言,需 GPU)、
|
||||
**Fun-ASR-MLT-Nano**(31 语种)、**SenseVoiceSmall**(五语种 ASR,
|
||||
并返回情感与音频事件标签)、**Paraformer**(低延迟流式)。下表展示的是
|
||||
工具箱级能力,并标明由哪个模型或 pipeline 提供:
|
||||
FunASR 是工具箱,需要分别选择任务、checkpoint 和运行时。
|
||||
一个模型或适配器支持的能力,不代表所有服务后端都支持。
|
||||
|
||||
| | FunASR(工具箱) | Whisper | 云端 API |
|
||||
| 任务 | Checkpoint 或 pipeline | 运行时入口 | 主要边界 |
|
||||
|---|---|---|---|
|
||||
| 最高速度 | **340 倍实时**(Fun-ASR-Nano + vLLM) | 13 倍实时 | ~1 倍实时 |
|
||||
| 说话人识别 | ✅ 由 VAD + CAM++ pipeline 提供 | ❌ 需要 pyannote | ✅ 额外付费 |
|
||||
| 情感识别 | ✅ 由 SenseVoice 提供 | ❌ | ❌ |
|
||||
| 语言数 | 取决于 checkpoint(例如 Qwen3-ASR 52、MLT-Nano 31、Nano 中/英/日) | 57 | 因服务而异 |
|
||||
| 流式识别 | ✅ WebSocket(Paraformer) | ❌ | ✅ |
|
||||
| CPU 可用 | ✅ 17 倍实时(SenseVoice) | ❌ 太慢 | 不适用 |
|
||||
| 私有部署 | ✅ 支持(工具箱 MIT;模型协议各异) | ✅ MIT 开源 | ❌ 仅云端 |
|
||||
| 费用 | 免费 | 免费 | ¥0.04/分钟起 |
|
||||
| 文件转写及情感/事件标签 | SenseVoiceSmall | Python `AutoModel`,CPU 或 GPU | 五语种 checkpoint;标签不代表说话人身份。 |
|
||||
| LLM 文件转写 | Fun-ASR-Nano | `AutoModel`;文档指定的 GPU 拆分引擎 `AutoModelVLLM` | 基础 Nano 覆盖中/英/日及中文方言/口音;时间戳取决于 checkpoint 和路径。 |
|
||||
| 更多语种的文件转写 | Fun-ASR-MLT-Nano | Python `AutoModel` | 独立的 31 语种 checkpoint,不能把其覆盖范围归给基础 Nano。 |
|
||||
| 分块实时转写 | Paraformer-zh-streaming | 流式 SDK 或 runtime WebSocket 服务 | 使用流式 checkpoint 和会话独立 cache,不能替换为离线 checkpoint。 |
|
||||
| 带说话人的文件转写 | SenseVoiceSmall + FSMN-VAD + CAM++ | `AutoModel` 的 VAD 与嵌入聚类 | 编号仅在当前录音内有效,不是已注册人物身份识别。 |
|
||||
| 联合文本、时间戳与说话人 | 第三方 OpenMOSS 的 MOSS-Transcribe-Diarize | MOSS 指南中的 FunASR adapter 或上游后端 | 离线、录音内匿名标签;统一路径不外接 VAD/说话人 pipeline。 |
|
||||
| 原生 CPU/端侧转写 | Fun-ASR-Nano 或 SenseVoiceSmall GGUF | llama.cpp runtime | 需要匹配的转换权重,GGUF 不能作为 Python `AutoModel` checkpoint 加载。 |
|
||||
|
||||
Checkpoint、接口与协议边界见 [Model Zoo](./model_zoo/readme_zh.md) 和
|
||||
[部署矩阵](./docs/deployment_matrix_zh.md)。请用目标音频与硬件评测后再选运行时。
|
||||
|
||||
第一次试用 FunASR?可以先跑 [Colab 快速体验](./examples/colab/README_zh.md),再配置本地环境。还不确定先用哪个模型?先看 [模型选择指南](./docs/model_selection_zh.md)。计划从 Whisper 或云端 ASR 切换?请按 [迁移指南](./docs/migration_from_whisper_zh.md) 和 [评测示例](./examples/migration/) 用代表性音频评测、映射功能并安全上线。
|
||||
|
||||
@@ -135,17 +135,14 @@ Whisper 是单个模型,**FunASR 是一个工具箱**——按场景挑模型
|
||||
|
||||
## 性能评测
|
||||
|
||||
> 184 条长音频(共 192 分钟)。[完整报告 →](https://modelscope.github.io/FunASR/zh/benchmark.html)
|
||||
[历史评测报告](https://modelscope.github.io/FunASR/zh/benchmark.html) 与
|
||||
[拆分引擎测量](./docs/vllm_guide_zh.md#benchmark) 保留原始结果。
|
||||
两者是独立记录,不能合并成通用速度排名或生产容量承诺。
|
||||
|
||||
| 模型 | 中文 CER ↓ | GPU 速度 | CPU 速度 | 对比 Whisper-large-v3 |
|
||||
|------|------|----------|----------|---------------------|
|
||||
| **Fun-ASR-Nano**(vLLM) | **8.20%** | **340 倍**实时 | — | 🚀 **快 26 倍** |
|
||||
| **SenseVoice-Small** | **7.81%** | **170 倍**实时 | **17 倍**实时 | 🚀 **快 13 倍** |
|
||||
| **Paraformer-Large** | 10.18% | **120 倍**实时 | **15 倍**实时 | 🚀 **快 9 倍** |
|
||||
| Whisper-large-v3-turbo | 21.71% | 46 倍实时 | ❌ | 快 3.4 倍 |
|
||||
| Whisper-large-v3 | 20.02% | 13 倍实时 | ❌ | 基准 |
|
||||
|
||||
> **一句话:** FunASR 在 CPU 上的速度,比 Whisper 在 GPU 上还快。
|
||||
请按 [RTFx 与可复现评测说明](./docs/benchmark/rtf_reproducibility.md) 对齐
|
||||
checkpoint/revision、音频集、硬件、批量大小、预热、计时范围与 CER/WER。
|
||||
离线吞吐量不等于流式延迟;可使用 [迁移评测示例](./examples/migration/)
|
||||
以相同口径测量自己的录音。
|
||||
|
||||
---
|
||||
|
||||
@@ -181,12 +178,16 @@ pip install -e ./
|
||||
|
||||
## 模型列表
|
||||
|
||||
列表包含第三方模型。MOSS-Transcribe-Diarize 由 **OpenMOSS** 发布,FunASR
|
||||
提供适配器,并不拥有其权重。统一路径为离线处理,匿名说话人标签仅在当前录音
|
||||
内有效,不是实时流式或已知人物身份识别。模型协议与工具箱 MIT 协议分别适用。
|
||||
|
||||
| 模型 | 任务 | 语言 | 参数量 | 链接 |
|
||||
|------|------|------|--------|------|
|
||||
| **Fun-ASR-Nano** | 识别 | 中/英/日 + 中文方言 | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-2512) [GGUF](https://huggingface.co/FunAudioLLM/Fun-ASR-Nano-GGUF) |
|
||||
| **Fun-ASR-MLT-Nano** | 识别 | 31 种语言 | 800M | [⭐](https://www.modelscope.cn/models/FunAudioLLM/Fun-ASR-MLT-Nano-2512) [🤗](https://huggingface.co/FunAudioLLM/Fun-ASR-MLT-Nano-2512) |
|
||||
| **SenseVoiceSmall** | 识别 + 情感 + 事件 | 中/英/日/韩/粤 | 234M | [⭐](https://www.modelscope.cn/models/iic/SenseVoiceSmall) [🤗](https://huggingface.co/FunAudioLLM/SenseVoiceSmall) [GGUF](https://huggingface.co/FunAudioLLM/SenseVoiceSmall-GGUF) [论文](https://arxiv.org/abs/2407.04051) |
|
||||
| **MOSS-Transcribe-Diarize** | 离线识别 + 时间戳 + 匿名说话人 | 以官方模型卡为准 | 以官方模型卡为准 | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [指南](./docs/moss_transcribe_diarize_zh.md) |
|
||||
| **MOSS-Transcribe-Diarize** | 第三方 OpenMOSS:离线识别 + 时间戳 + 匿名说话人 | 以官方模型卡为准 | 以官方模型卡为准 | [🤗](https://huggingface.co/OpenMOSS-Team/MOSS-Transcribe-Diarize) [指南](./docs/moss_transcribe_diarize_zh.md) |
|
||||
| **Paraformer-zh** | 识别 + 时间戳 | 中/英 | 220M | [⭐](https://www.modelscope.cn/models/iic/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/summary) [🤗](https://huggingface.co/funasr/paraformer-zh) |
|
||||
| Paraformer-zh-streaming | 流式识别 | 中/英 | 220M | [⭐](https://modelscope.cn/models/iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/summary) [🤗](https://huggingface.co/funasr/paraformer-zh-streaming) |
|
||||
| Qwen3-ASR | 识别,52 种语言 | 多语言 | 1.7B | [使用](examples/industrial_data_pretraining/qwen3_asr) |
|
||||
@@ -195,7 +196,7 @@ pip install -e ./
|
||||
| Whisper-large-v3-turbo | 识别 + 翻译 | 多语言 | 809M | [使用](examples/industrial_data_pretraining/whisper) |
|
||||
| ct-punc | 标点恢复 | 中/英 | 290M | [⭐](https://modelscope.cn/models/iic/punc_ct-transformer_cn-en-common-vocab471067-large/summary) [🤗](https://huggingface.co/funasr/ct-punc) |
|
||||
| fsmn-vad | 语音检测 | 中/英 | 0.4M | [⭐](https://modelscope.cn/models/iic/speech_fsmn_vad_zh-cn-16k-common-pytorch/summary) [🤗](https://huggingface.co/funasr/fsmn-vad) |
|
||||
| cam++ | 说话人分离 | — | 7.2M | [⭐](https://modelscope.cn/models/iic/speech_campplus_sv_zh-cn_16k-common/summary) [🤗](https://huggingface.co/funasr/campplus) |
|
||||
| cam++ | 说话人嵌入(speaker embeddings,pipeline 组件) | — | 7.2M | [⭐](https://modelscope.cn/models/iic/speech_campplus_sv_zh-cn_16k-common/summary) [🤗](https://huggingface.co/funasr/campplus) |
|
||||
| emotion2vec+large | 情感识别 | — | 300M | [⭐](https://modelscope.cn/models/iic/emotion2vec_plus_large/summary) [🤗](https://huggingface.co/emotion2vec/emotion2vec_plus_large) |
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
"""README entrypoint contracts; parse examples without importing or running models."""
|
||||
|
||||
import ast
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
from urllib.parse import unquote, urlsplit
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from markdown import Markdown
|
||||
import pytest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
LANGUAGES = {
|
||||
"README.md": ("Why FunASR?", "Benchmark", "What's new", "Model Zoo", "offline", "anonymous", "recording"),
|
||||
"README_zh.md": ("为什么选 FunASR?", "性能评测", "最新动态", "模型列表", "离线", "匿名", "录音"),
|
||||
"README_ja.md": ("なぜFunASRを選ぶのか?", "ベンチマーク", "最新情報", "モデル一覧", "オフライン", "匿名", "録音"),
|
||||
"README_ko.md": ("왜 FunASR인가?", "벤치마크", "최신 소식", "모델 목록", "오프라인", "익명", "녹음"),
|
||||
}
|
||||
|
||||
|
||||
def read(name):
|
||||
return (ROOT / name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def fences(text):
|
||||
language = None
|
||||
lines = []
|
||||
for line in text.splitlines():
|
||||
if line.startswith("```"):
|
||||
if language is None:
|
||||
language, lines = line[3:].strip(), []
|
||||
else:
|
||||
yield language, "\n".join(lines) + "\n"
|
||||
language = None
|
||||
elif language is not None:
|
||||
lines.append(line)
|
||||
assert language is None, "Unclosed code fence"
|
||||
|
||||
|
||||
def render(text):
|
||||
def slugify(value, separator):
|
||||
return re.sub(r"[^\w\- ]", "", value.lower()).replace(" ", separator)
|
||||
|
||||
return BeautifulSoup(Markdown(
|
||||
extensions=["extra", "toc"],
|
||||
extension_configs={"toc": {"slugify": slugify}},
|
||||
).convert(text), "html.parser")
|
||||
|
||||
|
||||
def section(name, title):
|
||||
soup = render(read(name))
|
||||
heading = soup.find(re.compile(r"^h[1-6]$"), string=title)
|
||||
assert heading is not None, title
|
||||
nodes = []
|
||||
for node in heading.next_siblings:
|
||||
if node.name and re.fullmatch(r"h[1-6]", node.name) and node.name <= heading.name:
|
||||
break
|
||||
nodes.append(str(node))
|
||||
return BeautifulSoup("".join(nodes), "html.parser")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_task_table_names_checkpoint_runtime_and_boundaries(name):
|
||||
body = section(name, LANGUAGES[name][0])
|
||||
table = body.find("table")
|
||||
assert table is not None
|
||||
assert len(table.select("thead th")) == 4
|
||||
assert not any(word in table.get_text() for word in ("Whisper", "Cloud APIs", "$0.006", "¥0.04"))
|
||||
for checkpoint in ("SenseVoiceSmall", "Fun-ASR-Nano", "Fun-ASR-MLT-Nano", "Paraformer", "MOSS-Transcribe-Diarize", "llama.cpp"):
|
||||
assert checkpoint in table.get_text(), checkpoint
|
||||
assert "OpenMOSS" in table.get_text()
|
||||
assert "CPU" in table.get_text() and "WebSocket" in table.get_text()
|
||||
assert all(len(row.find_all("td")) == 4 for row in table.select("tbody tr"))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_benchmark_links_evidence_instead_of_generalizing_vendor_performance(name):
|
||||
body = section(name, LANGUAGES[name][1])
|
||||
assert not body.find("table"), "Keep historical numeric tables in their evidence reports"
|
||||
links = [a.get("href", "") for a in body.find_all("a")]
|
||||
assert any("docs/benchmark/rtf_reproducibility.md" in href for href in links)
|
||||
assert any("benchmark.html" in href for href in links)
|
||||
assert "Whisper" not in body.get_text(), "Do not promote a cross-hardware comparison into a blanket claim"
|
||||
assert not re.search(r"[$¥]\s*0\.\d+", read(name))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_first_sensevoice_example_is_cpu_and_prints_real_return_fields(name):
|
||||
examples = [code for language, code in fences(read(name))
|
||||
if language == "python" and "SenseVoiceSmall" in code]
|
||||
assert examples
|
||||
tree = ast.parse(examples[0])
|
||||
calls = [node for node in ast.walk(tree) if isinstance(node, ast.Call)]
|
||||
constructor = next(node for node in calls if isinstance(node.func, ast.Name) and node.func.id == "AutoModel")
|
||||
options = {kw.arg: ast.literal_eval(kw.value) for kw in constructor.keywords}
|
||||
assert options["device"] == "cpu"
|
||||
assert options["vad_model"] == "fsmn-vad" and options["spk_model"] == "cam++"
|
||||
generate = next(node for node in calls if isinstance(node.func, ast.Attribute) and node.func.attr == "generate")
|
||||
sample = next(ast.literal_eval(kw.value) for kw in generate.keywords if kw.arg == "input")
|
||||
assert sample.startswith("https://") and "asr_example_zh.wav" in sample
|
||||
assert "asr_example_zh.wav" in read("examples/industrial_data_pretraining/paraformer/demo.py")
|
||||
assert any(isinstance(node.func, ast.Name) and node.func.id == "print" for node in calls)
|
||||
fields = {node.slice.value for node in ast.walk(tree)
|
||||
if isinstance(node, ast.Subscript) and isinstance(node.slice, ast.Constant)}
|
||||
assert {"sentence_info", "start", "spk", "sentence"} <= fields
|
||||
assert "spk_embedding" in read(name), "Explain embeddings separately from pipeline diarization"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_model_zoo_retains_third_party_moss_and_recording_scope(name):
|
||||
body = section(name, LANGUAGES[name][3])
|
||||
moss = next(row for row in body.select("tr") if "MOSS-Transcribe-Diarize" in row.get_text())
|
||||
assert "OpenMOSS" in moss.get_text()
|
||||
for boundary in LANGUAGES[name][4:]:
|
||||
assert boundary in body.get_text().lower(), boundary
|
||||
assert any("docs/moss_transcribe_diarize" in a.get("href", "") for a in moss.find_all("a"))
|
||||
for row in body.select("tr"):
|
||||
if row.find("td") and row.find("td").get_text(strip=True) == "cam++":
|
||||
assert "embedding" in row.find_all("td")[1].get_text().lower()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_news_stays_three_items_and_keeps_release_history(name):
|
||||
body = section(name, LANGUAGES[name][2])
|
||||
assert len(body.select("li")) == 3
|
||||
assert any(a.get("href") == "https://github.com/modelscope/FunASR/releases" for a in body.find_all("a"))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_python_and_shell_examples_have_valid_syntax_without_execution(name):
|
||||
for language, code in fences(read(name)):
|
||||
if language == "python":
|
||||
compile(code, name, "exec")
|
||||
elif language in {"bash", "sh", "shell"}:
|
||||
result = subprocess.run(["bash", "-n"], input=code, text=True, capture_output=True)
|
||||
assert result.returncode == 0, result.stderr
|
||||
for embedded in re.findall(r"<<'PY'\n(.*?)\nPY", code, re.S):
|
||||
ast.parse(embedded)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", LANGUAGES)
|
||||
def test_relative_links_and_internal_navigation_resolve(name):
|
||||
soup = render(read(name))
|
||||
for link in soup.select("a[href]"):
|
||||
target = urlsplit(link["href"])
|
||||
if target.scheme or target.netloc:
|
||||
continue
|
||||
resolved = (ROOT / unquote(target.path)).resolve() if target.path else ROOT / name
|
||||
assert resolved.is_relative_to(ROOT)
|
||||
assert resolved.exists(), (name, link["href"])
|
||||
if target.fragment and resolved.suffix == ".md":
|
||||
destination = render(resolved.read_text(encoding="utf-8"))
|
||||
anchors = {node.get("id") for node in destination.select("[id]")}
|
||||
anchors.update(node.get("name") for node in destination.select("a[name]"))
|
||||
assert unquote(target.fragment) in anchors, (name, link["href"])
|
||||
|
||||
|
||||
def test_speaker_field_explanation_has_implementation_evidence():
|
||||
camp = ast.parse(read("funasr/models/campplus/model.py"))
|
||||
assert any(isinstance(node, ast.Constant) and node.value == "spk_embedding" for node in ast.walk(camp))
|
||||
auto = ast.parse(read("funasr/auto/auto_model.py"))
|
||||
strings = {node.value for node in ast.walk(auto) if isinstance(node, ast.Constant) and isinstance(node.value, str)}
|
||||
assert {"sentence_info", "start", "sentence"} <= strings
|
||||
assert any(isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == "distribute_spk" for node in ast.walk(auto))
|
||||
utility = ast.parse(read("funasr/models/campplus/utils.py"))
|
||||
distribute = next(node for node in utility.body if isinstance(node, ast.FunctionDef) and node.name == "distribute_spk")
|
||||
assert any(isinstance(node, ast.Constant) and node.value == "spk" for node in ast.walk(distribute))
|
||||
Reference in New Issue
Block a user