Skip to content

HaujetZhao/Qwen3-ASR-GGUF

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Qwen3-ASR GGUF

Qwen3-ASR 模型转换为可本地高效运行的混合格式,实现快速、准确的离线语音识别

主要依赖 llama.cpp 加速 LLM Decoder。

Qwen3-ASR 0.6B 与 Qwen3-ASR 1.7B 以及 Qwen3-ForceAligner 0.6B 均可用,

核心特性

  • 纯本地运行 - 无需网络,数据不外传
  • 速度快 - 混合推理架构 (ONNX Encoder + GGUF Decoder)
  • GPU 加速 - 支持 Vulkan / DirectML
  • 流式输出 - 无限时长的音频文件,流式转录
  • 字幕输出 - ForceAligner 对齐字级时间戳,输出 SRT/JSON 格式
  • 上下文增强 - 可提供上下文信息,提升准确率

性能表现

1.7B 在 RTX 5050 笔记本上的实测数据(50秒中文音频):

(fun) PS D:\qwen3-asr> python .\transcribe.py .\test.mp3 -y
╭─────── Qwen3-ASR 配置选项 ───────╮
│  模型目录    D:\qwen3-asr\model  │
│  编码精度    int4                │
│  加速设备    DML:ON | Vulkan:ON  │
│  时间戳对齐  启用                │
│  语言设定    自动识别            │
╰──────────────────────────────────╯
--- [QwenASR] 初始化引擎 (DML: True) ---
--- [QwenASR] 辅助进程已就绪 ---
--- [QwenASR] 引擎初始化耗时: 3.61 秒 ---

开始处理: test.mp3

...
你怎么看待两个月之前的判断?
当初的判断不变,
美国对于委内瑞拉的突袭性质依然是政治投机,
不能算是地面战争。
入侵的美国军队总数是一两百,
站在委内瑞拉领土上的时间不超过一个小时,
算是。


📊 性能统计:
  🔹 RTF (实时率) : 0.052 (越小越快)
  🔹 音频时长    : 50.20 秒
  🔹 总处理耗时  : 2.59 秒
  🔹 编码等待    : 0.21 秒
  🔹 对齐总时    : 0.83 秒 (分段异步对齐)
  🔹 LLM 预填充  : 0.420 秒 (1742 tokens, 4149.1 tokens/s)
  🔹 LLM 生成    : 1.670 秒 (191 tokens, 114.4 tokens/s)
✅ 已保存文本文件: test.txt
✅ 已生成字幕文件: test.srt
✅ 已导出时间戳: test.json

CPU 的速度:

> python .\transcribe.py --no-dml --no-vulkan .\test.mp3 -y
╭──────── Qwen3-ASR 配置选项 ────────╮
│  模型目录    D:\qwen3-asr\model    │
│  编码精度    int4                  │
│  加速设备    DML:OFF | Vulkan:OFF  │
│  时间戳对齐  启用                  │
│  语言设定    自动识别              │
╰────────────────────────────────────╯
--- [QwenASR] 初始化引擎 (DML: False) ---
--- [QwenASR] 辅助进程已就绪 ---
--- [QwenASR] 引擎初始化耗时: 2.75 秒 ---

开始处理: test.mp3

...
你怎么看待两个月之前的判断?
当初的判断不变,
美国对于委内瑞拉的突袭性质依然是政治投机,
不能算是地面战争。
入侵的美国军队总数是一两百,
站在委内瑞拉领土上的时间不超过一个小时,
算是。


📊 性能统计:
  🔹 RTF (实时率) : 0.390 (越小越快)
  🔹 音频时长    : 50.20 秒
  🔹 总处理耗时  : 19.60 秒
  🔹 编码等待    : 0.80 秒
  🔹 对齐总时    : 7.90 秒 (分段异步对齐)
  🔹 LLM 预填充  : 10.742 秒 (1741 tokens, 162.1 tokens/s)
  🔹 LLM 生成    : 7.009 秒 (190 tokens, 27.1 tokens/s)   
✅ 已保存文本文件: test.txt
✅ 已生成字幕文件: test.srt
✅ 已导出时间戳: test.json

显存占用

以 1.7B ASR 和 0.6B Aligner 载入为例,Encoder int4 量化,Decoder q4_k 量化。

开启 DML 时:

  • ASR Encoder 占用显存 473MB
  • Aligner Encoder 占用显存 420MB

开启 Vulkan 时:

  • ASR Decoder 模型占用显存 1064MB,上下文占用显存 228 MB,推理占用 304MB,总共 1.6GB
  • Aligner Decoder 模型占用显存 372MB,上下文占用显存 228 MB,推理占用 299MB,总共 0.9GB

所以开启 DML 需备足 900M 显存,开启 Vulkan 需备足 2.5G 显存。

快速开始

1. 安装依赖

pip install onnxruntime-directml pydub numpy scipy gguf srt

转换格式还需要:

pip install torch transformers==4.57.6

pydub 需要系统安装 ffmpeg

依赖可能写得不是那么全,缺啥就装啥呗,没有需要自己编译的

llama.cpp Releases 下载预编译二进制,将 DLL 放入 qwen_asr_gguf/bin/

平台 下载文件
Windows llama-bXXXX-bin-win-vulkan-x64.zip

2. 下载模型

2.1 下载模型

Models Release 下载已经转换好的模型打包文件,下载后解压到 model 文件夹。

ASR 模型有 0.6B 和 1.7B 的,后者精度更高,但慢些。

Aligner 模型是 0.6B 的。

为节约显存,打包的模型:

  • Encoder 全部 int4 量化,与 fp16 输出的数值余弦相似度 96%
  • Decoder 全部 q4_k 量化,比 fp16 输出的困惑度仅增加 8.7%

对于语音识别,量化带来的精度差异小到可以忽略。

如果执意要用其它精度(fp32、fp16、int8)可以自行手动导出。

2.2 手动导出

下载原始模型:

pip install modelscope
modelscope download --model Qwen/Qwen3-ASR-0.6B
modelscope download --model Qwen/Qwen3-ForcedAligner-0.6B

配置 export_config.py,定义官方模型路径、导出路径:

from pathlib import Path
model_home = Path('~/.cache/modelscope/hub/models/Qwen').expanduser()

# [源模型路径] 官方下载好的 SafeTensors 模型文件夹
ASR_MODEL_DIR =  model_home / 'Qwen3-ASR-0.6B'
ALIGNER_MODEL_DIR =  model_home / 'Qwen3-ForcedAligner-0.6B'

# [导出目标路径] 转换后的 ONNX, GGUF 和权重汇总目录
EXPORT_DIR = r'./model'

导出模型:

# === 1. ASR 模型导出流程 ===
python 01-Export-ASR-Encoder-Frontend.py     # 导出 Encoder 前段 (CNN)
python 02-Export_ASR-Encoder-Backend.py      # 导出 Encoder 后段 (Transformer)
python 03-Optimize-ASR-Encoder.py            # 优化 ONNX 模型
python 04-Quantize-ASR-Encoder.py            # 编码器量化 (FP16/INT8/INT4)
python 05-Export-ASR-Decoder-HF.py           # 提取 Decoder 权重
python 06-Convert-ASR-Decoder-GGUF.py        # 转为 GGUF 格式 (FP16)
python 07-Quantize-ASR-Decoder-GGUF.py       # GGUF 二次量化 (Q4_K)

# === 2. Aligner 模型导出流程 ===
python 11-Export-Aligner-Encoder-Frontend.py
python 12-Export-Aligner-Encoder-Backend.py
python 13-Optimize-Aligner-Encoder.py
python 14-Quantize-Aligner-Encoder.py
python 15-Export-Aligner-Decoder-HF.py
python 16-Convert-Aligner-Decoder-GGUF.py
python 17-Quantize-Aligner-Decoder-GGUF.py

3. 转录测试

推荐使用 transcribe.py 命令行工具进行转录,支持丰富的参数配置:

# 基本用法
python transcribe.py test.mp3

# 添加参数,如禁用 dml
python transcribe.py test.mp3 --prec int4 --no-dml --no-vulkan --n-ctx 4096

也可以参考 21-Run-ASR.py 在 Python 代码中调用:

python 21-Run-ASR.py

部分代码解析:

# 配置引擎
config = ASREngineConfig(
    model_dir="model", 
    use_dml = True, 
    encoder_frontend_fn = "qwen3_asr_encoder_frontend.int4.onnx",
    encoder_backend_fn = "qwen3_asr_encoder_backend.int4.onnx",
    enable_aligner = True, 
    align_config = AlignerConfig(
        use_dml=True, 
        model_dir="model", 
        encoder_frontend_fn = "qwen3_aligner_encoder_frontend.int4.onnx",
        encoder_backend_fn = "qwen3_aligner_encoder_backend.int4.onnx"
    )
)

# 初始化引擎
engine = QwenASREngine(config=config)

# 执行转录
res = engine.transcribe(
    audio_file=audio_path,  
    context=context,
    language="Chinese",   # 强制指定语言 (如 'Chinese', 'English', None)
    start_second=0,       # 从何处开始读音频
    duration=None         # 读取多长音频,None 表示全部读取
)

项目采用纯同步顺序执行架构,得益于 Encoder 在开启 DirectML 后的极速表现(30s 音频仅需约 0.04s),现已移除复杂的多进程异步流水线,简化为:

graph TD
    A[音频输入] --> B[QwenASREngine]
    B -- 音频切片 --> C[QwenAudioEncoder]
    C --> D[ONNX Encoder]
    D -- 固定形状 Padding/Masking --> D
    D --> E[音频特征 Embedding]
    E --> F[llama.cpp GGUF Decoder]
    F --> G[转录文本]
    G -- 启用对齐时 --> H[QwenForcedAligner]
    H --> I[字级时间戳]
    I --> B
Loading
  • 同步执行: 编码 -> LLM 推理 -> 对齐 顺序完成,代码更简洁,RTF 依然保持领先。
  • DML 形状固定优化: 推理时将音频填充(Padding)到固定长度(如 40s),并配合 Attention Mask。这解决了 DirectML 在处理动态形状时频繁分配显存导致的性能抖动,显著提升了推理速度。

项目结构

├── 01-Export-ASR-Encoder-Frontend.py        # 导出 ASR 编码器前段 (CNN)
├── 02-Export_ASR-Encoder-Backend.py         # 导出 ASR 编码器后段 (Transformer)
├── 03-Optimize-ASR-Encoder.py               # 优化 ASR 编码器 (融合常量、折叠算子)
├── 04-Quantize-ASR-Encoder.py               # ASR 编码器量化 (INT8/FP16/INT4)
├── 05-Export-ASR-Decoder-HF.py              # 提取 ASR 解码器权重
├── 06-Convert-ASR-Decoder-GGUF.py           # ASR 解码器转为 GGUF 格式 (FP16)
├── 07-Quantize-ASR-Decoder-GGUF.py          # ASR 解码器 GGUF 量化 (Q4_K)
├── 11-Export-Aligner-Encoder-Frontend.py    # 导出对齐编码器前段
├── 12-Export-Aligner-Encoder-Backend.py     # 导出对齐编码器后段
├── 13-Optimize-Aligner-Encoder.py           # 优化对齐编码器
├── 14-Quantize-Aligner-Encoder.py           # 对齐编码器量化 (INT8/FP16/INT4)
├── 15-Export-Aligner-Decoder-HF.py          # 提取对齐解码器权重
├── 16-Convert-Aligner-Decoder-GGUF.py       # 将对齐解码器转换为 GGUF
├── 17-Quantize-Aligner-Decoder-GGUF.py      # 对齐解码器 GGUF 量化
├── 18-Run-Aligner.py                        # Aligner 对齐 API 示例脚本
├── 21-Run-ASR.py                            # ASR 转录 API 示例脚本
├── transcribe.py                            # 命令行转录工具 (功能最全)
└── qwen_asr_gguf/
    └── inference/
        ├── asr.py                  # ASR 核心引擎逻辑
        ├── aligner.py              # 强行对齐逻辑
        ├── encoder.py              # 音频特征提取逻辑 (ONNX 封装)
        ├── llama.py                # llama.cpp Python 绑定
        ├── exporters.py            # SRT/JSON/TXT 导出工具
        └── chinese_itn.py          # 中文数字规整 (ITN)

常见问题

Q: 输出全是乱码或「!!!!」怎么办?

Intel 集显的 FP16 计算可能溢出,设置环境变量禁用:

os.environ["GGML_VK_DISABLE_F16"] = "1"

致谢

About

将 Qwen3-ASR 的 LLM 部分导出为 GGUF,用 llama.cpp 进行加速推理。后者支持 Vulkan 和 Cuda 加速。

Resources

Stars

196 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors