Downloads · 30 days
0
kkyyssyk/qiansai
qiansai is a machine learning model from kkyyssyk. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
基于 OpenAI Whisper 实现中文语音识别,配合 Helsinki-NLP(MarianMT)实现中译英翻译,模型均转换为 RKNN 格式,部署在 RK3588 NPU 上运行。
Downloads · 30 days
0
Access
Public
Updated Jul 11, 2026
Repo size
1.4 GB
Likes
0
Public
Click a slice to open those files.
.zip616 MB · 45%
From the Hugging Face model README
基于 OpenAI Whisper 实现中文语音识别,配合 Helsinki-NLP(MarianMT)实现中译英翻译,模型均转换为 RKNN 格式,部署在 RK3588 NPU 上运行。
.
├── export_onnx.py # 从 Whisper 官方模型导出 encoder/decoder 的 ONNX 文件
├── whisper_lite.py # 板端推理脚本:RKNNLite 加载 encoder/decoder,做语音识别
├── mic_whisper.py # PC 端 demo:录音 + Whisper 识别(openai-whisper 库,非板端)
├── whisper_encoder_base.onnx # Whisper Base 音频编码器(ONNX 原始版)
├── whisper_encoder_base.rknn # Whisper Base 音频编码器(RKNN 转换版,板端使用)
├── whisper_decoder_base.onnx # Whisper Base 文本解码器(ONNX 原始版)
├── whisper_decoder_base.rknn # Whisper Base 文本解码器(RKNN 转换版,板端使用)
└── Helsinki-NLP-onnx/ # Helsinki-NLP-onnx.zip 解压后
├── config.json # MarianMT 模型配置(d_model=512, 6层encoder/6层decoder)
├── generation_config.json # 生成参数(num_beams=6, max_length=512)
├── tokenizer_config.json # MarianTokenizer 配置,source_lang=zho, target_lang=eng
├── special_tokens_map.json # 特殊token映射(eos/pad/unk)
├── vocab.json # 词表
├── source.spm # 源语言(中文)sentencepiece 分词模型
├── target.spm # 目标语言(英文)sentencepiece 分词模型
├── model_fixed.onnx # 固定长度导出的翻译模型(ONNX 原始版)
└── model_fixed.rknn # 固定长度翻译模型(RKNN 转换版,板端使用)
python export_onnx.py --model_type base
生成 whisper_encoder_base.onnx 和 whisper_decoder_base.onnx。
使用 RKNN-Toolkit2 将上一步的 onnx 转换、量化为 .rknn(转换脚本不在本项目范围内,需另行编写)。
需要 rknnlite 运行环境,另外需准备:
mel_80_filters.txt(Mel 滤波器系数)vocab_zh.txt(中文词表)python3 whisper_lite.py \
--encoder_model_path whisper_encoder_base.rknn \
--decoder_model_path whisper_decoder_base.rknn \
--task zh \
--audio_path test_zh.wav
推理逻辑:音频 → log-mel 频谱(pad/trim 到固定帧数)→ encoder 编码 → decoder 自回归解码(起始 token 为 SOT + LANG + TRANSCRIBE + NO_TIMESTAMPS,逐 token 生成直到 EOT 或达到 MAX_NEW_TOKENS)→ 查词表得到文本。
python mic_whisper.py
用官方 openai-whisper 库直接录音识别,用于验证效果,不用于板端部署。
source_lang=zho, target_lang=eng)。model_fixed 中的"fixed"表示该模型使用固定输入长度导出——RKNN 转换要求静态 shape,推理前需将输入 pad/truncate 到该固定长度。source.spm / target.spm),不是简单的空格切词。source.spm 编码为 token id 序列,pad/truncate 到固定长度。model_fixed.rknn(RKNNLite)推理。target.spm 解码为英文文本。注意 config.json 中 decoder_start_token_id=65000、pad_token_id=65000 相同,需正确处理起始 token 与 padding 位置,避免与真实内容混淆。
| 用途 | 依赖 |
|---|---|
| 板端推理(Whisper + 翻译) | rknnlite |
| PC 端 Whisper demo | openai-whisper、sounddevice、numpy、scipy |
| 翻译分词/解码 | sentencepiece |
| 模型导出 | onnx、onnxsim、torch |
whisper_lite.py 中解码器自回归解码上限为 MAX_NEW_TOKENS = 128(另有版本用 224 固定长度,视导出配置而定),可按需调整。task 参数目前支持 zh / en,对应不同语言 token(LANG_ZH / LANG_EN)和词表文件(vocab_zh.txt 等)。Helsinki-NLP/opus-mt-en-zh)并重新转换 RKNN。export_onnx.py 及 config.json 中 _name_or_path 字段写死的本地路径(如 /root/...),按需替换为通用路径,避免暴露服务器目录结构。用 export_helsinki_onnx_fixed.py:
python export_helsinki_onnx_fixed.py
MarianMTModel + MarianTokenizer)FIXED_LEN = 64(1, 64) 的 dummy 输入:input_ids、attention_mask、decoder_input_ids(decoder_input_ids 全部填充为 decoder_start_token_id=65000)logits,opset_version=14model_fixed.onnx直接复用 RKNN Model Zoo 官方 whisper 例程自带的通用转换脚本 convert.py(对任意 onnx 模型通用,不是专门为 NLP 写的):
python3 rknn_model_zoo-main/examples/whisper/python/convert.py model_fixed.onnx rk3588
convert.py 核心逻辑(无需量化,走 fp):
from rknn.api import RKNN
rknn = RKNN(verbose=False)
rknn.config(target_platform='rk3588')
rknn.load_onnx(model='model_fixed.onnx')
rknn.build(do_quantization=False) # 默认不量化
rknn.export_rknn('model_fixed.rknn')
rknn.release()
转换过程中会出现 channel is too large, may produce thousands of regtask, fallback to cpu 和 Unkown op target: 0 之类的 E 级提示,属于部分算子自动 fallback 到 CPU 计算,不是致命错误,最终仍会生成完整可用的 model_fixed.rknn(约 216MB)。
translate_lite.py)板子上用 RKNNLite + MarianTokenizer(而不是 sentencepiece 原始接口)做实际推理:
from rknnlite.api import RKNNLite
from transformers import MarianTokenizer
FIXED_LEN = 64
tokenizer = MarianTokenizer.from_pretrained(MODEL_DIR, local_files_only=True)
rknn = RKNNLite()
rknn.load_rknn(f"{MODEL_DIR}/model_fixed.rknn")
rknn.init_runtime()
def translate(text):
inputs = tokenizer([text], return_tensors="np", padding="max_length",
truncation=True, max_length=FIXED_LEN)
input_ids = inputs["input_ids"].astype(np.int64)
attention_mask = inputs["attention_mask"].astype(np.int64)
decoder_input_ids = np.full((1, FIXED_LEN), 65000, dtype=np.int64) # decoder_start_token
outputs = rknn.inference(inputs=[input_ids, attention_mask, decoder_input_ids])
logits = outputs[0]
token_ids = []
for i in range(logits.shape[1]):
tid = int(np.argmax(logits[0, i, :]))
if tid == 0: # eos/pad
break
token_ids.append(tid)
return tokenizer.decode(token_ids, skip_special_tokens=True)
注意:当前这版 translate_lite.py 是逐句一次性推理,不是真正的自回归解码(decoder_input_ids 全程固定为起始 token,没有把上一步生成的 token 喂回去再生成下一个),属于简化版验证脚本,翻译质量可能不如标准自回归生成,后续如果需要提升翻译效果,可以考虑改成逐 token 循环喂入的自回归方式。