# Qwen3-ASR-ncnn (wen3-ASR-ncnn) 纯 C++ 端到端的 **Qwen3-ASR** 语音识别推理实现,基于 [ncnn](https://github.com/Tencent/ncnn) 框架。 无需 Python、无需 ffmpeg,直接从「音频文件」得到识别文本,跨平台(Windows / Linux)编译运行。 > 本仓库的 ncnn 权重由 [Qwen/Qwen3-ASR](https://huggingface.co/Qwen/Qwen3-ASR)(0.6B)经 pnnx 转换而来,推理结果与 PyTorch 原版逐字一致。 ## 特性 - **端到端纯 C++**:音频解码(MP3/WAV)→ Whisper Mel 前端 → 音频塔 → LLM 自回归解码,一条命令出结果。 - **零外部依赖**:MP3 用单文件 `dr_mp3.h` 解码;重采样(Kaiser 窗 sinc)、梅尔谱、分词器(byte-level BPE)全部自实现,不依赖 ffmpeg / torch。 - **多语言**:模型自动检测语言并生成对应文本(中文 / 日语 / 英文等),UTF-8 输出,终端与文件均正确显示。 - **数值对齐**:音频塔余弦相似度 ≈ 1.0,解码器逐层 ≈ 1.0,端到端文本与官方一致。 ## 模型文件结构 ``` assets/qwen3_asr_0.6b/ ├── text_embed.ncnn.bin / .param # 文本 embedding ├── lm_head.ncnn.bin / .param # 输出层 ├── decoder_norm.ncnn.bin / .param # 最终 RMSNorm ├── decoder_00..27_{pre,o,mlp}.ncnn.* # 28 层 LLM 解码器(pre=RMSNorm+QKV+RoPE+GQA+o_proj; o=attn out; mlp=MLP) ├── audio_conv*.ncnn.* # 音频塔卷积(3×Conv2d + conv_out) ├── audio_post.ncnn.* # 音频塔后投影(proj1 gelu + proj2) ├── audio_00..17_{pre,o,mlp}.ncnn.* # 18 层音频编码器 ├── vocab.txt / merges.txt # byte-level BPE 词表 ├── special_tokens.txt # 特殊 token(本仓库为空,特殊 id 由代码处理) ├── hann_window.bin # [400] STFT 窗 └── mel_filters.bin # [128,201] 梅尔滤波器 ``` ## 构建 需要:C++17 编译器(GCC / Clang / MSVC)、CMake ≥ 3.18、ncnn(开启 `NCNN_AVX2` 与 `NCNN_OPENMP` 收益明显)。 ```bash git clone Qwen3-ASR-ncnn cd Qwen3-ASR-ncnn cmake -B build_fast -DCMAKE_BUILD_TYPE=Release \ -Dncnn_DIR=/build/install/lib/cmake/ncnn cmake --build build_fast --target asr_main_stream -j # 产物:build_fast/asr_stream.exe (Windows)或 build_fast/asr_stream (Linux) ``` ## 推理 ```bash # 直接喂音频(mp3 / wav / ...),自动 C++ 解码 -> mel -> 识别 asr_stream [max_new=256] # 示例 asr_stream assets/qwen3_asr_0.6b test.mp3 512 ``` - `max_new`:最多生成的新 token 数(即输出长度上限,不是音频长度)。 - 程序会自动把控制台切到 UTF-8,并把最终结果额外写入 `asr_result.txt`(带 BOM),记事本 / VS Code 打开必定正确显示。 - 若终端仍乱码,运行前执行 `chcp 65001`(Windows)或使用 Windows Terminal。 ## 性能提示 - **瓶颈在 prefill**:长音频(如 2 分钟)的 prefill 阶段约占总耗时 90%(串行逐 token 喂入)。 单步 decode ≈ 200ms/token(10 物理核 AVX2+OMP)。后续可优化为 batch prefill。 - **线程数**:ncnn 默认用满逻辑核;本项目外层并行已去除,建议 `net.opt.num_threads` 设为**物理核数**(而非超线程数)。 ## 许可 模型权重来自 [Qwen/Qwen3-ASR](https://huggingface.co/Qwen/Qwen3-ASR),遵循其原始许可(Apache 2.0)。 本仓库的转换与推理代码以 Apache 2.0 发布。 ## 致谢 - [Qwen3-ASR](https://huggingface.co/Qwen/Qwen3-ASR) — 阿里巴巴通义千问团队 - [ncnn](https://github.com/Tencent/ncnn) — 腾讯开源高性能推理框架