---
title: sherpa-onnx-sense-voice-small
canonical_url: "https://www.modelscope.cn/models/xiaowangge/sherpa-onnx-sense-voice-small"
md_url: "https://www.modelscope.cn/models/xiaowangge/sherpa-onnx-sense-voice-small.md"
repository: xiaowangge/sherpa-onnx-sense-voice-small
chinese_name: sherpa-onnx-sense-voice-small
last_updated: 2026-03-31
license: "Apache License 2.0"
pipeline_tag: auto-speech-recognition
tasks:
  - auto-speech-recognition
  - emotion-recognition
base_model:
  - iic/SenseVoiceSmall
base_model_relation: quantized
library_name:
  - onnx
  - pytorch
frameworks:
  - Pytorch
language:
  - zh
  - en
downloads: 3599
stars: 43
---

# sherpa-onnx-sense-voice-small

> sherpa-onnx-sense-voice-small - xiaowangge 在 ModelScope 开源的模型。从 modelscope 网站 iic/SenseVoiceSmall 模型转换而来。 参考 https://github.com/k2-fsa/sherpa-onnx/blob/master/scripts/sense-voice/export-onnx.py 脚本，完成 onnx 模型导出。

xiaowangge/sherpa-onnx-sense-voice-small 是 ModelScope 魔搭社区上的auto-speech-recognition、emotion-recognition模型，采用 Apache License 2.0 许可，基于 iic/SenseVoiceSmall 构建。

- **Repository**: xiaowangge/sherpa-onnx-sense-voice-small
- **License**: Apache License 2.0
- **Tasks**: auto-speech-recognition, emotion-recognition
- **Base model**: iic/SenseVoiceSmall
- **Downloads**: 3599
- **Stars**: 43
- **Last updated**: 2026-03-31

Source: https://www.modelscope.cn/models/xiaowangge/sherpa-onnx-sense-voice-small

---

### 转换说明

- 从 modelscope 网站 `iic/SenseVoiceSmall` 模型转换而来。
- 参考 `https://github.com/k2-fsa/sherpa-onnx/blob/master/scripts/sense-voice/export-onnx.py` 脚本，完成 `onnx` 模型导出。

### 下载模型

#### SDK 下载

```bash
# 安装 ModelScope
pip install modelscope
```

```python
# SDK 模型下载
from modelscope import snapshot_download
model_dir = snapshot_download('xiaowangge/sherpa-onnx-sense-voice-small')
```

#### Git 下载

```
# Git模型下载
git clone https://www.modelscope.cn/xiaowangge/sherpa-onnx-sense-voice-small.git
```

### 本地应用

> 默认为 `cpu` 推理，`gpu` 加速推理需要安装 `sherpa-onnx==1.12.32+cuda` 或 `sherpa-onnx==1.12.32+cuda12`，需要和本地 `cuda/cudnn` 版本匹配。

#### 环境

> 推荐使用虚拟环境进行包管理，基础环境要求： python >= 3.12。
> `gpu` 推理时执行 `pip install sherpa-onnx==1.12.32+cuda -f https://k2-fsa.github.io/sherpa/onnx/cuda.html`。

```
coloredlogs==15.0.1
fastapi==0.135.1
numpy==2.4.1
sherpa_onnx==1.12.32
soundfile==0.13.1
uvicorn==0.42.0
pydub==0.25.1
websockets==16.0
fireredvad==0.0.2
```

#### 程序

- `http` 和 `websocket` 服务器请查看目录下的 `http_ws_server.py` 文件。
- `websocket` 测试客户端请查看目录下的 `ws_client.py` 文件。

##### VAD 模型

###### FireRedVAD

> 这里提供一份使用 `FireRedTeam/FireRedVAD` 流式识别语音片段，结合 `sherpa-onnx-sense-voice-small` 生成音频文件字幕的示例代码，该 `VAD` 识别效果较好。

- 代码
```python
def generate_srt_file():
  sample_rate = 16000
  read_duration_s = 30
  read_frames = int(sample_rate * read_duration_s)
  max_audio_buffer_size = int(sample_rate * read_duration_s)

  # stt model
  stt_model_path = "xiaowangge/sherpa-onnx-sense-voice-small"
  stt_model = f"{stt_model_path}/model.onnx"
  stt_tokens = f"{stt_model_path}/tokens.txt"
  recognizer = sherpa_onnx.OfflineRecognizer.from_sense_voice(
    model=stt_model,
    tokens=stt_tokens,
    provider="cpu",
    num_threads=max(2, os.cpu_count() // 2),
    use_itn=True,
    sample_rate=sample_rate,
    debug=False
  )
  # vad model
  vad_config = FireRedStreamVadConfig(use_gpu=False, smooth_window_size=5, speech_threshold=0.3, pad_start_frame=5,
                                      min_speech_frame=50, max_speech_frame=2000, min_silence_frame=30,
                                      chunk_max_frame=30000)
  vad = FireRedStreamVad.from_pretrained("FireRedVAD/Stream-VAD", vad_config)

  # generate config
  wave_file = wave.open("morning_scene.wav", "rb")
  audio_buffer = np.array([], dtype=np.int16)
  segments = []
  start_time = None
  start_sample_offset = 0
  start_run_time = time.time()
  while True:
    audio_data = wave_file.readframes(read_frames)
    if len(audio_data) == 0:
      print("Read end")
      break
    audio_data = np.frombuffer(audio_data, dtype=np.int16)
    audio_buffer = np.concatenate((audio_buffer, audio_data))
    frame_results = vad.detect_chunk(audio_data)
    for fr in frame_results:
      if fr.is_speech_start:
        start_time = (fr.speech_start_frame - 1) / FRAME_PER_SECONDS
      elif fr.is_speech_end:
        end_time = (fr.speech_end_frame - 1) / FRAME_PER_SECONDS
        # slice audio buffer
        start_sample = max(int(sample_rate * start_time) - start_sample_offset, 0)
        end_sample = int(sample_rate * end_time) - start_sample_offset
        audio_segment = audio_buffer[start_sample:end_sample]
        # recognize
        stream = recognizer.create_stream()
        stream.accept_waveform(sample_rate, audio_segment)
        recognizer.decode_stream(stream)
        result = stream.result
        print(f"Recognize, start: {start_time:.2f}, end: {end_time:.2f}, text: {result.text}")
        segments.append(Segment(start_time, end_time, result.text))
        start_time = None

    # silence
    if start_time is None and len(audio_buffer) > max_audio_buffer_size:
      trim_size = len(audio_buffer) - max_audio_buffer_size
      audio_buffer = audio_buffer[trim_size:]
      start_sample_offset += trim_size

  wave_file.close()

  # statis time
  cost_time = time.time() - start_run_time
  duration = wave_file.getnframes() / wave_file.getframerate()
  print(f"Total run time: {cost_time:.3f}s, rtf: {cost_time / duration:.6f}")
  srt_file = "test.srt"
  with open(srt_file, "w", encoding="utf-8") as f:
    for i, s in enumerate(segments):
      f.write(f"{i + 1}\n{s}\n\n")
```

- 结果 
```
1
0:00:00,150 --> 0:00:02,210
清晨的阳光透过薄雾。

2
0:00:02,220 --> 0:00:04,650
在湖面撒下细碎的金斑。

3
0:00:04,910 --> 0:00:08,040
岸边的垂柳将绿丝绦垂进水里。

4
0:00:08,050 --> 0:00:12,260
引得几条小鱼，不时探出脑袋，搅碎满池倒影。

```

#### 发送请求

```bash
curl --request POST \
  --url http://localhost:7998/v1/recognize \
  --header 'Authorization: Bearer 3e0c6966-0edf-4c37-8f77-80d4cc370a0d' \
  --header 'content-type: multipart/form-data' \
  --form 'file=@morning_scene.wav'
```

#### 接收响应

> `timestamps` 和  `tokens` 对象由于输出太多，这里省略。

```json
{
	"code": 200,
	"msg": "success",
	"data": {
		"id": "978b4e58-433f-4ac7-98de-55211bae85ea",
		"lang": "zh",
		"emotion": "NEUTRAL",
		"text": "清晨的阳光透过薄雾，在湖面洒下细碎的金斑，岸边的垂柳将绿丝绦垂进水里，引得几条小鱼，不时探出脑袋，搅碎满池倒影。",
		"timestamps": [
			0.17999999225139618,
			0.29999998211860657
		],
		"tokens": [
			"清",
			"晨"],
		"metadata": {
			"format": "wav",
			"sample_rate": 16000,
			"channels": 1,
			"duration": 12.504,
			"file_name": "20bae8e3-74dd-4ca3-ba4a-a20b16a7662c.wav",
			"file_size": 50444
		}
	}
}
```

#### 特性

 - 支持推理 **全量模型** 和 **量化模型**。
 - 支持 **多核 CPU 加速** 推理，Windows 系统 4C 8G 机器 10 个字以内推理耗时：全量（100ms），量化（60ms）。
 - 支持非实时识别，自动重采样为 **16 khz**，**http** 服务提供 **短语音识别（30s 内）**。
 - 结合 **sliero-vad** 支持实时切分识别，通过 **websocket** 实现，分为 **start**、**normal** 和 **stop** 类型，通信协议暂时采用简单的 **json+base64（二进制）**。
 - 新增 **config.json** 配置文件，支持配置 **stt** 和 **vad** 模型参数。

 #### 模型目录结构

```
|__ ai-models
|  |__ sherpa-onnx-sense-voice-small
|     |__ silero-vad vad 模型
|         |__ model.onnx 全量版本
          |__ model_fp16.onnx fp16 版本
|     |__ export_onnx.py 转换脚本
|     |__ config.json 配置文件
|     |__ http_ws_server.py http 和 websocket 服务器
|     |__ ws_client.py websocket客户端
|     |__ morning_scene.wav 测试音频
|     |__ tokens.txt 词汇表
|     |__ model.onnx 全量模型
|     |__ model_q8.onnx q8 量化模型
```

### 常见问题

 1. 接口应用只是一个简单的示例服务，需要自行测试。
 2. 如有相关疑问，请在讨论区提出。
 3. 默认 `API KEY` 会在应用启动时输出至日志文件或控制台。
