news 2026/10/4 10:57:31

rknn_model_zoo 实战:在 Rockchip NPU 上部署 OpenAI Whisper 语音识别(RKNN 转换、Python/C++ Demo 全流程)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
rknn_model_zoo 实战:在 Rockchip NPU 上部署 OpenAI Whisper 语音识别(RKNN 转换、Python/C++ Demo 全流程)
  • 示例工程
  • 人工智能
  • 嵌入式
  • 边缘计算
  • 计算机视觉
  • 模型优化

【免费下载链接】rknn_model_zoo

项目地址:https://gitcode.com/gh_mirrors/rk/rknn_model_zoo
点击查看免费下载

导读

本文以 rknn_model_zoo 仓库中的 examples/whisper/README.md 为主线,完整讲解如何将 OpenAI 的开源语音识别模型 Whisper(encoder + decoder 结构)从 ONNX 转换为 RKNN 模型,并在 RK3562、RK3566、RK3568、RK3576、RK3588、RV1126B 等 Rockchip NPU 平台上运行。读完本文,你将掌握 Whisper 的 20 秒/30 秒输入模型导出、RKNN 模型转换参数、Python 端到端推理脚本用法,以及 Android/Linux 上 C++ Demo 的编译、推送与运行方法。

1. 示例背景:Whisper 是什么

Whisper 是 OpenAI 发布的一个通用语音识别(ASR)模型,基于大规模多语种音频数据集训练而成,同时具备多语种语音识别、语音翻译、语种识别等多种能力。本示例使用的模型源自 OpenAI 官方 whisper 开源项目。

在 rknn_model_zoo 中,Whisper 示例采用经典的Encoder-Decoder 双模型结构,将 Whisper 拆分为两个独立的 ONNX 子模型再分别转换为 RKNN:

  • whisper_encoder_base_20s.onnx:编码器,负责把 20 秒音频对应的 log-mel 频谱特征编码为高层语义特征;
  • whisper_decoder_base_20s.onnx:解码器,负责基于编码输出与 token 序列逐字自回归地生成识别文本。

仓库中该示例的完整目录结构如下:

examples/whisper/ ├── cpp/ # C++ 端(rknpu2 推理实现 + 预处理/后处理) ├── model/ # 模型下载脚本、mel 滤波器、词表与测试音频 ├── python/ # convert.py / export_onnx.py / whisper.py ├── README.md # 本文主体文档 └── export_onnx.md # ONNX 导出指南

2. 当前支持平台

本示例支持的 NPU 平台包括:RK3562、RK3566、RK3568、RK3576、RK3588、RV1126B。在后续所有转换与运行命令中,<TARGET_PLATFORM>均需从上述平台中选择。

3. 预训练模型获取

3.1 直接下载已导出的 ONNX 模型

示例默认提供base规模、20 秒输入长度的预导出 ONNX 模型:

  • whisper_encoder_base_20s.onnx
  • whisper_decoder_base_20s.onnx

在 examples/whisper/model/download_model.sh 中可以看到下载方式,进入 model 目录执行脚本即可:

cd model ./download_model.sh

脚本本质是两条wget命令,分别下载 encoder 与 decoder 两个 ONNX 文件到当前目录。

3.2 自行导出 ONNX 模型(详见 export_onnx.md)

若需要使用不同模型规模(tiny/base/medium)或不同输入时长,请参考仓库内的 examples/whisper/export_onnx.md 指南自行导出。

3.2.1 导出 20 秒输入长度的模型

第一步,安装与 OpenAI 官方版本对齐的依赖并修改安装包源码(需安装openai-whisper==20231117):

pip install openai-whisper==20231117 # 1. 修改 whisper/audio.py(例如 ~/python3.8/site-packages/whisper/audio.py)中的 CHUNK_LENGTH CHUNK_LENGTH = 30 -->> CHUNK_LENGTH = 20 # 2. 修改 whisper/model.py 中的 positional_embedding 相关代码 assert x.shape[1:] == self.positional_embedding.shape, "incorrect audio shape" -->> # assert x.shape[1:] == self.positional_embedding.shape, "incorrect audio shape" x = (x + self.positional_embedding).to(x.dtype) -->> x = (x + self.positional_embedding[-x.shape[1]:,:]).to(x.dtype)

第二步,执行导出脚本:

cd python python export_onnx.py --model_type <MODEL_TYPE> --n_mels <N_MELS(optional)> # 例如: python export_onnx.py --model_type base --n_mels 80

参数说明:

  • <MODEL_TYPE>:指定模型规模,如tiny、base、medium;
  • <N_MELS>(可选):指定 mel 滤波器数量,如80、128,默认80。

注意:small与large规模的模型当前尚不支持导出。

3.2.2 导出原始 30 秒输入长度的模型

若不修改源码,保持默认CHUNK_LENGTH = 30,直接运行导出脚本即可得到 30 秒输入的模型:

pip install openai-whisper==20231117 cd python python export_onnx.py --model_type <MODEL_TYPE> --n_mels <N_MELS(optional)>

从 examples/whisper/python/export_onnx.py 的源码可以看到导出流程:先whisper.load_model(model_type)加载官方模型,再用torch.onnx.export分别导出 encoder(输入名x,输出名out)与 decoder(输入名tokens、audio,输出名out),opset 固定为 12,最后通过onnxsim.simplify对两个模型做简化,产物分别保存为../model/whisper_encoder_{type}.onnx与../model/whisper_decoder_{type}.onnx。

4. 转换为 RKNN 模型

4.1 转换命令

进入python目录,使用 examples/whisper/python/convert.py 将 ONNX 模型转换为 RKNN 模型:

cd python python convert.py <onnx_model> <TARGET_PLATFORM> <dtype(optional)> <output_rknn_path(optional)> # 例如: python convert.py ../model/whisper_encoder_base_20s.onnx rk3588 # 输出模型将保存在 ../model/whisper_encoder_base_20s.rknn python convert.py ../model/whisper_decoder_base_20s.onnx rk3588 # 输出模型将保存在 ../model/whisper_decoder_base_20s.rknn

4.2 参数说明

  • <onnx_model>:指定 ONNX 模型路径;
  • <TARGET_PLATFORM>:指定 NPU 平台名称,可选范围见第 2 节支持平台列表;
  • <dtype>(可选):取值为i8或fp。i8表示执行 INT8 量化,fp表示不量化(浮点),默认fp;
  • <output_rknn_path>(可选):指定 RKNN 模型保存路径,默认保存在与 ONNX 模型相同的目录(源码中即model_path.replace('.onnx', '.rknn'))。

4.3 转换流程的源码级解析

从 convert.py 可以看到转换的完整调用链:RKNN(verbose=False)创建工具对象 →rknn.config(target_platform=platform)配置目标平台 →rknn.load_onnx(model=model_path)加载 ONNX →rknn.build(do_quantization=do_quant)构建 RKNN 模型(do_quant由 dtype 是否为i8/u8决定)→rknn.export_rknn(output_path)导出 →rknn.release()释放资源。整个过程与 rknn-toolkit2 的标准工作流一致。

值得说明的是:虽然 README 的 dtype 说明只写了i8/fp,但 convert.py 的参数校验同时接受u8(与i8一样触发量化),使用时应以实际源码为准。由于 Whisper 为生成式模型,示例默认关闭量化(DEFAULT_QUANT = False)以保证识别精度,浮点模型对 NPU 显存与带宽的占用也更大,部署时需结合板卡资源评估。

5. Python Demo 推理

5.1 用法

在python目录下运行 examples/whisper/python/whisper.py:

cd python # 使用 ONNX 模型推理(CPU) python whisper.py --encoder_model_path <onnx_model> --decoder_model_path <onnx_model> --task <TASK> --audio_path <AUDIO_PATH> # 例如: python whisper.py --encoder_model_path ../model/whisper_encoder_base_20s.onnx --decoder_model_path ../model/whisper_decoder_base_20s.onnx --task en --audio_path ../model/test_en.wav # 使用 RKNN 模型推理(NPU) python whisper.py --encoder_model_path <rknn_model> --decoder_model_path <rknn_model> --task <TASK> --audio_path <AUDIO_PATH> --target <TARGET_PLATFORM> # 例如: python whisper.py --encoder_model_path ../model/whisper_encoder_base_20s.rknn --decoder_model_path ../model/whisper_decoder_base_20s.rknn --task en --audio_path ../model/test_en.wav --target rk3588

5.2 参数说明

  • <TARGET_PLATFORM>:指定 NPU 平台名称,范围见支持平台列表(命令行默认值为rk3588);
  • <onnx_model / rknn_model>:指定模型路径,脚本会根据文件后缀(.rknn或.onnx)自动选择推理后端;
  • <TASK>:指定识别任务,如en(英语识别)、zh(中文识别)。目前仅支持这两种,其他取值会打印提示并退出;
  • <AUDIO_PATH>:指定音频文件路径。

5.3 推理流程的源码级解析

whisper.py 的核心处理链路如下:

  1. 音频读取与预处理:soundfile读取音频后,ensure_channels将多声道转为单声道(对通道取均值),ensure_sample_rate用scipy.signal.resample将任意采样率统一重采样到 16000 Hz;
  2. log-mel 频谱计算:log_mel_spectrogram使用torch.stft(N_FFT=400、HOP_LENGTH=160、hann 窗)计算短时傅里叶变换,再与 examples/whisper/model/mel_80_filters.txt 中的 80 维 mel 滤波器做矩阵乘法,最后做log10归一化(clamp 到 1e-10,裁剪到最大值减 8,再平移缩放到 (0,1) 区间);
  3. 填充/裁剪:pad_or_trim将 mel 特征统一对齐到N_MELS × MAX_LENGTH(20 秒 × 100 帧),超出部分截断、不足部分补零;
  4. Encoder 推理:run_encoder根据模型类型调用rknn.inference或onnxruntime.run;
  5. Decoder 自回归解码:run_decoder以[sot, task_code, no_timestamps, ...]作为起始 token 序列(如50258为 sot、50259/50260分别为 en/zh 任务码、50364为 timestamp 起点、50257为 eot 结束符),循环调用_decode取out_decoder[0, -1].argmax()得到下一个 token,对照 examples/whisper/model/vocab_en.txt 或 examples/whisper/model/vocab_zh.txt 词表拼出文本,直到命中结束符为止;中文任务(task_code=50260)还需要对结果做 base64 解码(base64_decode)才能得到可读汉字;
  6. 资源释放:release_model对 RKNN 模型调用release(),对 ONNX 会话直接del。

6. Android Demo

6.1 编译构建

回到 rknn_model_zoo 根目录,设置 Android NDK 路径后调用仓库顶层的构建脚本:

# 回到 rknn_model_zoo 根目录 cd ../../ export ANDROID_NDK_PATH=<android_ndk_path> ./build-android.sh -t <TARGET_PLATFORM> -a <ARCH> -d whisper # 例如 ./build-android.sh -t rk3588 -a arm64-v8a -d whisper

参数说明:

  • <android_ndk_path>:指定 Android NDK 路径;
  • <TARGET_PLATFORM>:指定 NPU 平台名称(见支持平台列表);
  • <ARCH>:指定设备系统架构,可通过以下命令查询:
# 查询架构,日志中应显示 ['arm64-v8a' 或 'armeabi-v7a'] adb shell cat /proc/version

6.2 推送 demo 文件到设备

设备通过 USB 连接后,将构建产物推送到设备:

adb root adb remount adb push install/<TARGET_PLATFORM>_android_<ARCH>/rknn_whisper_demo/ /data/

6.3 运行 demo

adb shell cd /data/rknn_whisper_demo export LD_LIBRARY_PATH=./lib ./rknn_whisper_demo model/whisper_encoder_base_20s.rknn model/whisper_decoder_base_20s.rknn en model/test_en.wav

程序接收 5 个命令行参数:<encoder_path> <decoder_path> <task> <audio_path>(第 0 个为可执行文件名本身),对应上面的 encoder 模型、decoder 模型、任务类型(en/zh)与音频路径。

7. Linux Demo

Linux 编译工具链推荐使用gcc-linaro-6.3.1(aarch64)/gcc-arm-8.3(armhf)/armhf-uclibcgnueabihf(armhf for RV1106/RV1103 系列)。使用其他版本可能遇到 C demo 编译失败的问题。详细的编译环境搭建请参考 docs/Compilation_Environment_Setup_Guide.md。

7.1 编译构建

# 回到 rknn_model_zoo 根目录 cd ../../ # 若编译时找不到 GCC_COMPILER,请手动设置其路径 (可选) export GCC_COMPILER=<GCC_COMPILER_PATH> ./build-linux.sh -t <TARGET_PLATFORM> -a <ARCH> -d whisper # 例如 ./build-linux.sh -t rk3588 -a aarch64 -d whisper

参数说明:

  • <GCC_COMPILER_PATH>:GCC_COMPILER 路径;
  • <TARGET_PLATFORM>:NPU 平台名称(见支持平台列表);
  • <ARCH>:设备系统架构,查询方式:
# 查询架构,对于 Linux,日志中应显示 ['aarch64' 或 'armhf'] adb shell cat /proc/version

7.2 推送 demo 文件到设备

  • 若设备通过 USB 连接,直接推送:
adb push install/<TARGET_PLATFORM>_linux_<ARCH>/rknn_whisper_demo/ /data/
  • 对于其他开发板,使用scp或其他方式将install/<TARGET_PLATFORM>_linux_<ARCH>/rknn_whisper_demo/下的所有文件拷贝到设备/data目录。

7.3 运行 demo

adb shell cd /data/rknn_whisper_demo export LD_LIBRARY_PATH=./lib ./rknn_whisper_demo model/whisper_encoder_base_20s.rknn model/whisper_decoder_base_20s.rknn en model/test_en.wav

8. C++ 端实现原理(源码级解析)

C++ demo 的主体在 examples/whisper/cpp/main.cc 与 examples/whisper/cpp/process.cc 中,整体流程与 Python 版一一对应:

  1. 音频读取:read_audio读取音频;双声道时convert_channels转单声道;采样率非 16000 时resample_audio重采样(相关工具函数位于 utils/audio_utils.c);
  2. 预加载资源:read_mel_filters读取 examples/whisper/model/mel_80_filters.txt,read_vocab按"index token"格式解析词表;
  3. 模型初始化:init_whisper_model依次对 encoder、decoder 调用rknn_init、rknn_query(RKNN_QUERY_IN_OUT_NUM)、rknn_query(RKNN_QUERY_INPUT_ATTR / OUTPUT_ATTR)并打印各张量的维度、格式、类型与量化参数(见 examples/whisper/cpp/rknpu2/whisper.cc);
  4. 音频预处理:audio_preprocess用 Hann 窗 + FFTW3 计算 STFT,再与 mel 滤波器做矩阵乘法(ENABLE_NEON开启时使用 ARM NEON 指令集加速,否则回退到 OpenCVgemm),最后clamp_and_log_max做与 Python 版一致的 log 归一化;
  5. 推理与解码:inference_whisper_model在 NPU 上执行 encoder 推理,随后以自回归方式逐 token 执行 decoder 推理(argmax选取最大概率 token),按词表拼接文本,中文任务同样做 base64 解码;
  6. 性能统计:程序结束时会打印Real Time Factor (RTF),即推理耗时与音频时长的比值(音频时长按CHUNK_LENGTH20 秒封顶),用于评估实时性(见 main.cc)。

8.1 关键宏定义:更换模型时必须同步修改

examples/whisper/cpp/process.h 中集中定义了与模型强耦合的常量,更换模型规模或输入长度时必须同步调整:

#define VOCAB_NUM 51865 #define MAX_TOKENS 12 #define SAMPLE_RATE 16000 #define N_FFT 400 #define HOP_LENGTH 160 #define CHUNK_LENGTH 20 #define MAX_AUDIO_LENGTH CHUNK_LENGTH * SAMPLE_RATE // 20 秒 × 16000 #define N_MELS 80 #define MELS_FILTERS_SIZE 201 // N_FFT / 2 + 1 #define ENCODER_INPUT_SIZE CHUNK_LENGTH * 100 #define ENCODER_OUTPUT_SIZE CHUNK_LENGTH * 50 * 512 // 384/512/1024 分别对应 tiny/base/medium #define DECODER_INPUT_SIZE ENCODER_OUTPUT_SIZE

根据 export_onnx.md 中的 Special Notes:

  • CHUNK_LENGTH需根据模型的输入时长(20 秒或 30 秒)修改,Python 版whisper.py中的CHUNK_LENGTH同理;
  • ENCODER_OUTPUT_SIZE需根据模型规模修改:tiny/base/medium分别对应384/512/1024。

9. 预期结果

运行 demo 后,程序会打印识别出的文本。英文任务(TASK_FOR_EN)与中文任务(TASK_FOR_ZH)的参考输出如下:

# TASK_FOR_EN Whisper output: Mr. Quilter is the apostle of the middle classes, and we are glad to welcome his gospel. # TASK_FOR_ZH Whisper output: 对我做了介绍,我想说的是大家如果对我的研究感兴趣

注意:不同平台、不同版本的工具链与驱动可能导致结果略有差异。

10. 常见问题与注意事项

  • 模型与代码常量不匹配:无论是 Python 还是 C++ demo,CHUNK_LENGTH(输入时长)与ENCODER_OUTPUT_SIZE(模型规模对应的编码维度)必须与实际导出的 ONNX/RKNN 模型一致,否则推理会失败或输出错误结果;
  • 量化精度风险:示例默认以浮点(fp)方式转换。若希望压缩模型体积、提升 NPU 推理速度而使用i8量化,需自行评估识别精度下降是否可接受;
  • 中文解码依赖 base64:中文识别的原始输出是 base64 编码的文本,Python 与 C++ demo 均已内置base64_decode处理,直接使用示例代码即可;
  • 音频要求:demo 会自动处理采样率与声道数,但为保证识别效果,建议输入清晰、无背景噪音的 16 kHz 单声道语音。

11. 总结

通过本文可以完整走通一条 Whisper 在 Rockchip NPU 上的部署链路:从官方 whisper 模型导出 20 秒/30 秒 ONNX 子模型(encoder/decoder),经 rknn-toolkit2 的config → load_onnx → build → export_rknn转换为 RKNN 模型,再到 Python 端到端推理、Android/Linux 上的 C++ Demo 编译运行。核心要点是理解 Whisper 的编码器-解码器结构在 NPU 上的拆分方式,以及输入时长、模型规模与代码常量的对齐关系。仓库内 examples/whisper/README.md 与 examples/whisper/export_onnx.md 是后续查阅的一手资料,源码 examples/whisper/python/whisper.py 与 examples/whisper/cpp/process.cc 则是调试与二次开发的最佳参考。

  • 示例工程
  • 人工智能
  • 嵌入式
  • 边缘计算
  • 计算机视觉
  • 模型优化

【免费下载链接】rknn_model_zoo

项目地址:https://gitcode.com/gh_mirrors/rk/rknn_model_zoo
点击查看免费下载

相关推荐

上一篇:AI NovelGenerator:如何用AI创作完整的长篇小说?
下一篇:如何理解Revit软件授权机制与开源替代方案的技术实现

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 10:51:37

TouchDesigner三维渲染实战:从节点搭建到GLSL与实例化

做实时视觉这几年&#xff0c;TouchDesigner 几乎成了我工作流里绕不开的工具。很多朋友第一次打开它&#xff0c;看见满屏节点第一反应是“这跟三维软件长得完全不一样”&#xff0c;但真正上手做一次三维渲染项目后就会明白&#xff0c;这种节点式的实时环境&#xff0c;恰恰…

作者头像 李华
网站建设 2026/10/4 10:49:16

本地部署AI助手全指南:Ollama+Qwen2.5从零配置到优化

落地一台完全属于你自己的AI助手&#xff0c;说起来挺玄乎&#xff0c;但实际操作下来&#xff0c;其实就是“模型运行环境 模型文件 对话界面”三个东西的组合。前阵子这套本地搭建方案又火了一轮&#xff0c;因为免费、数据不出本机、还能按需定制&#xff0c;很多人花半小…

作者头像 李华
网站建设 2026/10/4 10:43:15

RouteScope:网络路径探测与可视化实战

RouteScope 这个名字最初只是我电脑里一个不起眼的工具脚本名&#xff0c;意思是“把路由路径放进观测视野里”。后来它慢慢变成了我处理网络故障时最先打开的东西&#xff1a;一条命令&#xff0c;把从本机到目标 IP 之间每一跳的设备、延迟、丢包和 AS 归属全部拉出来&#x…

作者头像 李华