YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

Whisper 语音识别 + Helsinki-NLP 中英翻译(RK3588)

基于 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 转换版,板端使用)

一、Whisper 语音识别

1. 导出模型(PC 端)

python export_onnx.py --model_type base

生成 whisper_encoder_base.onnx 和 whisper_decoder_base.onnx。

2. 转换为 RKNN

使用 RKNN-Toolkit2 将上一步的 onnx 转换、量化为 .rknn(转换脚本不在本项目范围内,需另行编写)。

3. 板端推理

需要 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)→ 查词表得到文本。

4. PC 端快速测试(不涉及 RKNN)

python mic_whisper.py

用官方 openai-whisper 库直接录音识别,用于验证效果,不用于板端部署。

二、Helsinki-NLP 中译英翻译

模型说明

  • 语言方向固定为 中 → 英(source_lang=zho, target_lang=eng)。
  • model_fixed 中的"fixed"表示该模型使用固定输入长度导出——RKNN 转换要求静态 shape,推理前需将输入 pad/truncate 到该固定长度。
  • 分词使用 sentencepiece(source.spm / target.spm),不是简单的空格切词。

推理流程

  1. 中文文本 → 用 source.spm 编码为 token id 序列,pad/truncate 到固定长度。
  2. token 序列送入 model_fixed.rknn(RKNNLite)推理。
  3. 输出 token id 序列 → 用 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 等)。
  • 如需支持英译中或其他语言对,需重新从 Hugging Face 导出对应的 Helsinki-NLP 模型(如 Helsinki-NLP/opus-mt-en-zh)并重新转换 RKNN。
  • 分享/上传前建议检查 export_onnx.py 及 config.json 中 _name_or_path 字段写死的本地路径(如 /root/...),按需替换为通用路径,避免暴露服务器目录结构。

Helsinki-NLP 转 RKNN 的完整流程(补充)

1. PyTorch → ONNX(PC/WSL 端)

用 export_helsinki_onnx_fixed.py:

python export_helsinki_onnx_fixed.py
  • 加载本地 MarianMT 模型(MarianMTModel + MarianTokenizer)
  • 固定序列长度 FIXED_LEN = 64
  • 构造三个 (1, 64) 的 dummy 输入:input_ids、attention_mask、decoder_input_ids(decoder_input_ids 全部填充为 decoder_start_token_id=65000)
  • 对整个 model 一次性导出(不分离 encoder/decoder),输出名为 logits,opset_version=14
  • 生成 model_fixed.onnx

2. ONNX → RKNN

直接复用 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)。

3. 板端推理(对应 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 循环喂入的自回归方式。

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support