
基于OpenHarmony5.0.0\4.1的开发者手机ASR实现方案
一、什么是ASR 自动语音识别(Automatic Speech Recognition,简称 ASR)是一种将人类语音转换为文本的技术。其目标是让计算机“听懂”人类的语言。 二、OpenHarmony如何实现ASR 本项目参考开源项目https://github.com/k2-fsa/sherpa-onnx实现。通过三方推理框架onnx运行时运行推理模型
一、什么是ASR
- 自动语音识别(Automatic Speech Recognition,简称 ASR)是一种将人类语音转换为文本的技术。其目标是让计算机“听懂”人类的语言。
二、OpenHarmony如何实现ASR
本项目参考开源项目https://github.com/k2-fsa/sherpa-onnx实现。通过三方推理框架onnx运行时运行推理模型获取输出,最后在应用侧将模型输出在屏幕上显示
sherpa-onnx 是由 Next-gen Kaldi 团队开发的一个开源项目,旨在提供高效的离线语音识别和语音合成解决方案。它支持多种平台,包括 Android、iOS、Raspberry Pi 等,能够在没有网络连接的情况下进行实时语音处理。该项目依赖于 ONNX Runtime 框架,提供从语音到文本(ASR)、文本到语音(TTS)以及语音活动检测(VAD)等功能,适用于各类嵌入式系统和移动设备。
源项目是基于HarmonyOS开发,OH4.1支持不友好,会闪退,所以笔者进行了兼容性适配,目前在开发者手机4.1/5.0都能运行。
项目流程图介绍
三、项目实操
3.1、环境准备
设备环境:开发者手机二代(版本:B710或B613)、开发者手机一代(B613)
开发环境:DevEco Studio 4.1 Release(构建版本:4.1.0.400)
SDK版本:4.1.9.2 Release full sdk
源码地址:https://gitee.com/MIKECODE/lavalphone_asr_demo.git
- 选用低版本DevEco和低版本SDK是为了构建兼容OH4.1的hap包
3.2、修改代码
首先使用git clone https://gitee.com/MIKECODE/lavalphone_asr_demo.git 获取代码并用DevEco4.1打开项目文件。
- 源项目缺少神经网络模型和签名。缺少签名无法安装,缺少神经网络模型会闪退。
3.2.1、获取神经网络模型
获取方式一:
- 直接从release版本(https://gitee.com/MIKECODE/lavalphone_asr_demo/releases/tag/release )中下载两个rar包并解压
- 解压后将hap包改后缀为zip,继续解压
- 复制\v1.0.0_com.laval.asr.zip\resources\rawfile\sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20文件夹到项目的的rawfile目录
获取方式二:
- 从https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 下载并解压
- 将sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20放到项目的的rawfile目录
文件目录为如下结构即设置完成
└───entry
└───src
└───main
├───ets
└───resources
├───base
├───en_US
│───zh_CN
└───rawfile
└───sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20 //onnx神经网络模型文件
3.2.2、项目签名
- 打开项目结构(快捷键Ctrl+Alt+Shift+S)
- 勾选自动签名并确定,等待同步完成
3.3、运行代码
- 确保以上步骤完成,用数据线连接设备和pc,点击run,应用即可安装至设备。
麦克风识别页-模型加载中 | 麦克风识别页-模型加载完成 | 麦克风识别页-实时推理 | 麦克风识别页-停止推理 |
---|---|---|---|
文件识别页-模型加载完成 | 文件识别页-选择文件 | 文件识别页-推理中 | 文件识别页-推理完成 |
---|---|---|---|
使用说明
- 首先打开应用,等待模型初始化。
- 页面默认停留在麦克风识别页,点击Start,开始实时语音识别
- 点击Stop停止语音识别
- 再点击Save recorded audio,可以选择文件保存路径,文件名以.wav结尾。
- 点击下方From file,切换到从文件识别页,点击Select .wav file (16kHz),
- 选择需要进行语音识别的wav格式音频文件,点击右上角的确认
- 会返回页面并进行推理
- 等待推理完成,
四、自定义神经网络模型如何修改
下载支持的模型,支持的模型不止这些,原作者只列出了这些,可以自行尝试,下载地址https://github.com/k2-fsa/sherpa-onnx/releases/tag/asr-models
function getModelConfig(type: number): OnlineModelConfig { const modelConfig = new OnlineModelConfig(); switch (type) { case 0: { const modelDir = 'sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer'; break; } case 1: { const modelDir = 'sherpa-onnx-lstm-zh-2023-02-20'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-11-avg-1.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-11-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-11-avg-1.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'lstm'; break; } case 2: { const modelDir = 'sherpa-onnx-lstm-en-2023-02-17'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'lstm'; break; } case 3: { const modelDir = 'icefall-asr-zipformer-streaming-wenetspeech-20230615'; modelConfig.transducer.encoder = `${modelDir}/exp/encoder-epoch-12-avg-4-chunk-16-left-128.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/exp/decoder-epoch-12-avg-4-chunk-16-left-128.onnx`; modelConfig.transducer.joiner = `${modelDir}/exp/joiner-epoch-12-avg-4-chunk-16-left-128.onnx`; modelConfig.tokens = `${modelDir}/data/lang_char/tokens.txt`; modelConfig.modelType = 'zipformer2'; break; } case 4: { const modelDir = 'icefall-asr-zipformer-streaming-wenetspeech-20230615'; modelConfig.transducer.encoder = `${modelDir}/exp/encoder-epoch-12-avg-4-chunk-16-left-128.onnx`; modelConfig.transducer.decoder = `${modelDir}/exp/decoder-epoch-12-avg-4-chunk-16-left-128.onnx`; modelConfig.transducer.joiner = `${modelDir}/exp/joiner-epoch-12-avg-4-chunk-16-left-128.onnx`; modelConfig.tokens = `${modelDir}/data/lang_char/tokens.txt`; modelConfig.modelType = 'zipformer2'; break; } case 5: { const modelDir = 'sherpa-onnx-streaming-paraformer-bilingual-zh-en'; modelConfig.paraformer.encoder = `${modelDir}/encoder.int8.onnx`; modelConfig.paraformer.decoder = `${modelDir}/decoder.int8.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'paraformer'; break; } case 6: { const modelDir = 'sherpa-onnx-streaming-zipformer-en-2023-06-26'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1-chunk-16-left-128.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1-chunk-16-left-128.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1-chunk-16-left-128.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer2'; break; } case 7: { const modelDir = 'sherpa-onnx-streaming-zipformer-fr-2023-04-14'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-29-avg-9-with-averaged-model.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-29-avg-9-with-averaged-model.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-29-avg-9-with-averaged-model.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer'; break; } case 8: { const modelDir = 'sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1.int8.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer'; break; } case 9: { const modelDir = 'sherpa-onnx-streaming-zipformer-zh-14M-2023-02-23' modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1.int8.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer'; break; } case 10: { const modelDir = 'sherpa-onnx-streaming-zipformer-en-20M-2023-02-17'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1.int8.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer'; break; } case 14: { const modelDir = 'sherpa-onnx-streaming-zipformer-korean-2024-06-16'; modelConfig.transducer.encoder = `${modelDir}/encoder-epoch-99-avg-1.int8.onnx`; modelConfig.transducer.decoder = `${modelDir}/decoder-epoch-99-avg-1.onnx`; modelConfig.transducer.joiner = `${modelDir}/joiner-epoch-99-avg-1.int8.onnx`; modelConfig.tokens = `${modelDir}/tokens.txt`; modelConfig.modelType = 'zipformer'; break; } default: { console.log(`Please specify a supported type. Given type ${type}`); } } return modelConfig; }
将下载的模型解压移动至项目的的rawfile目录
修改StreamingAsrWorker.ets的174行。将type修改为实际下载的模型的数值,此处以8为例。
确保以上步骤完成,用数据线连接设备和pc,点击run,应用即可安装至设备。
五、其他
本项目开源地址:https://gitee.com/MIKECODE/lavalphone_asr_demo
本项目release版本已经上传开发者手机分发中心,可以直接下载体验。

更多推荐
所有评论(0)