Fangjun Kuang
Committed by GitHub

Add CI to build HAPs for HarmonyOS (#1578)

  1 +name: hap-vad-asr
  2 +
  3 +on:
  4 + push:
  5 + branches:
  6 + - hap
  7 + - hap-ci
  8 +
  9 + workflow_dispatch:
  10 +
  11 +concurrency:
  12 + group: hap-vad-asr-${{ github.ref }}
  13 + cancel-in-progress: true
  14 +
  15 +permissions:
  16 + contents: write
  17 +
  18 +jobs:
  19 + hap_vad_asr:
  20 + if: github.repository_owner == 'csukuangfj' || github.repository_owner == 'k2-fsa'
  21 + runs-on: ${{ matrix.os }}
  22 + name: Haps for vad asr ${{ matrix.index }}/${{ matrix.total }}
  23 + strategy:
  24 + fail-fast: false
  25 + matrix:
  26 + os: [ubuntu-latest]
  27 + total: ["10"]
  28 + index: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
  29 +
  30 + steps:
  31 + - uses: actions/checkout@v4
  32 + with:
  33 + fetch-depth: 0
  34 +
  35 + # https://github.com/actions/setup-java
  36 + - uses: actions/setup-java@v4
  37 + with:
  38 + distribution: 'temurin' # See 'Supported distributions' for available options
  39 + java-version: '17' # it requires jdk 17 to sigh the hap
  40 +
  41 + - name: Show java version
  42 + shell: bash
  43 + run: |
  44 + which java
  45 + java --version
  46 +
  47 + - name: cache-toolchain
  48 + id: cache-toolchain-ohos
  49 + uses: actions/cache@v4
  50 + with:
  51 + path: command-line-tools
  52 + key: commandline-tools-linux-x64-5.0.5.200.zip
  53 +
  54 + - name: Download toolchain
  55 + if: steps.cache-toolchain-ohos.outputs.cache-hit != 'true'
  56 + shell: bash
  57 + run: |
  58 + curl -SL -O https://huggingface.co/csukuangfj/harmonyos-commandline-tools/resolve/main/commandline-tools-linux-x64-5.0.5.200.zip
  59 + unzip commandline-tools-linux-x64-5.0.5.200.zip
  60 + rm commandline-tools-linux-x64-5.0.5.200.zip
  61 +
  62 + - name: Set environment variable
  63 + shell: bash
  64 + run: |
  65 + echo "$GITHUB_WORKSPACE/command-line-tools/sdk/default/openharmony/native/build-tools/cmake/bin" >> "$GITHUB_PATH"
  66 + which cmake
  67 +
  68 + cmake --version
  69 +
  70 + - name: Install Python dependencies
  71 + shell: bash
  72 + run: |
  73 + python3 -m pip install --upgrade pip jinja2
  74 +
  75 + - name: Generate build script
  76 + shell: bash
  77 + run: |
  78 + cd scripts/hap
  79 +
  80 + total=${{ matrix.total }}
  81 + index=${{ matrix.index }}
  82 +
  83 + ./generate-vad-asr-hap-script.py --total $total --index $index
  84 + ls -lh
  85 +
  86 + chmod +x build-hap-vad-asr.sh
  87 + mv -v ./build-hap-vad-asr.sh ../..
  88 +
  89 + - name: Generate secrets
  90 + shell: bash
  91 + run: |
  92 + echo "${{ secrets.HAP_SHERPA_ONNX_CER }}" > /tmp/sherpa_onnx.cer
  93 + shasum -a 256 /tmp/sherpa_onnx.cer
  94 + ls -lh /tmp/sherpa_onnx.cer
  95 +
  96 + # macos
  97 + # base64 -i sherpa_onnx_profileRelease.p7b -o sherpa_onnx_profileRelease.p7b.base64
  98 + #
  99 + # linux
  100 + # base64 -w 0 sherpa_onnx_profileRelease.p7b > sherpa_onnx_profileRelease.p7b.base64
  101 + #
  102 + # cat sherpa_onnx_profileRelease.p7b.base64 | base64 --decode > sherpa_onnx_profileRelease.p7b
  103 + #
  104 + echo "${{ secrets.HAP_SHERPA_ONNX_PROFILE }}" | base64 --decode > /tmp/sherpa_onnx_profileRelease.p7b
  105 + echo "${{ secrets.HAP_SHERPA_ONNX_KEY_STORE }}" > ./sherpa_onnx_ohos_key.p12.base64
  106 + echo "${{ secrets.HAP_SHERPA_ONNX_KEY_STORE }}" | base64 --decode > /tmp/sherpa_onnx_ohos_key.p12
  107 +
  108 + ls -l /tmp/sherpa_onnx_profileRelease.p7b
  109 + ls -l /tmp/sherpa_onnx_ohos_key.p12
  110 +
  111 + ls -lh ./sherpa_onnx_ohos_key.p12.base64
  112 + shasum -a 256 ./sherpa_onnx_ohos_key.p12.base64
  113 + wc ./sherpa_onnx_ohos_key.p12.base64
  114 + rm ./sherpa_onnx_ohos_key.p12.base64
  115 +
  116 + shasum -a 256 /tmp/sherpa_onnx_profileRelease.p7b
  117 + shasum -a 256 /tmp/sherpa_onnx_ohos_key.p12
  118 +
  119 + - name: build HAP
  120 + env:
  121 + HAP_KEY_ALIAS: ${{ secrets.HAP_KEY_ALIAS }}
  122 + HAP_KEY_PWD: ${{ secrets.HAP_KEY_PWD }}
  123 + HAP_KEY_STORE_PWD: ${{ secrets.HAP_KEY_STORE_PWD }}
  124 + shell: bash
  125 + run: |
  126 + export COMMANDLINE_TOOLS_DIR=$GITHUB_WORKSPACE/command-line-tools
  127 + ./build-hap-vad-asr.sh
  128 +
  129 + # remove secrets
  130 + rm /tmp/sherpa_onnx.cer
  131 + rm /tmp/sherpa_onnx_profileRelease.p7b
  132 + rm /tmp/sherpa_onnx_ohos_key.p12
  133 +
  134 + - name: Display HAPs
  135 + shell: bash
  136 + run: |
  137 + ls -lh ./haps/
  138 + du -h -d1 .
  139 +
  140 + - name: Publish to huggingface
  141 + env:
  142 + HF_TOKEN: ${{ secrets.HF_TOKEN }}
  143 + uses: nick-fields/retry@v3
  144 + with:
  145 + max_attempts: 20
  146 + timeout_seconds: 200
  147 + shell: bash
  148 + command: |
  149 + git config --global user.email "csukuangfj@gmail.com"
  150 + git config --global user.name "Fangjun Kuang"
  151 +
  152 + rm -rf huggingface
  153 + export GIT_LFS_SKIP_SMUDGE=1
  154 + export GIT_CLONE_PROTECTION_ACTIVE=false
  155 +
  156 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
  157 + echo "SHERPA_ONNX_VERSION $SHERPA_ONNX_VERSION"
  158 +
  159 + git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-harmony-os huggingface
  160 + cd huggingface
  161 + du -h -d1 .
  162 + git fetch
  163 + git pull
  164 + git merge -m "merge remote" --ff origin main
  165 +
  166 + d=hap/vad-asr/$SHERPA_ONNX_VERSION
  167 + mkdir -p $d
  168 + cp -v ../haps/*.hap $d/
  169 + git status
  170 + git lfs track "*.hap"
  171 + git add .
  172 + git commit -m "add more HAPs"
  173 + git push https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-harmony-os main
  1 +{
  2 + "meta": {
  3 + "stableOrder": true
  4 + },
  5 + "lockfileVersion": 3,
  6 + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
  7 + "specifiers": {
  8 + "libsherpa_onnx.so@../oh_modules/.ohpm/sherpa_onnx@1.10.32/oh_modules/sherpa_onnx/src/main/cpp/types/libsherpa_onnx": "libsherpa_onnx.so@../oh_modules/.ohpm/sherpa_onnx@1.10.32/oh_modules/sherpa_onnx/src/main/cpp/types/libsherpa_onnx",
  9 + "sherpa_onnx@1.10.32": "sherpa_onnx@1.10.32"
  10 + },
  11 + "packages": {
  12 + "libsherpa_onnx.so@../oh_modules/.ohpm/sherpa_onnx@1.10.32/oh_modules/sherpa_onnx/src/main/cpp/types/libsherpa_onnx": {
  13 + "name": "libsherpa_onnx.so",
  14 + "version": "1.0.0",
  15 + "resolved": "../oh_modules/.ohpm/sherpa_onnx@1.10.32/oh_modules/sherpa_onnx/src/main/cpp/types/libsherpa_onnx",
  16 + "registryType": "local"
  17 + },
  18 + "sherpa_onnx@1.10.32": {
  19 + "name": "sherpa_onnx",
  20 + "version": "1.10.32",
  21 + "integrity": "sha512-yHYmWoeqhrunOqGr9gxPJJH/8+rdwcKFOW6onYByVObQVpbqypslg301IjGm9xpnc5bJEkO3S9sra2zQTpPA/w==",
  22 + "resolved": "https://ohpm.openharmony.cn/ohpm/sherpa_onnx/-/sherpa_onnx-1.10.32.har",
  23 + "registryType": "ohpm",
  24 + "dependencies": {
  25 + "libsherpa_onnx.so": "file:./src/main/cpp/types/libsherpa_onnx"
  26 + }
  27 + }
  28 + }
  29 +}
@@ -5,6 +5,9 @@ @@ -5,6 +5,9 @@
5 "main": "", 5 "main": "",
6 "author": "", 6 "author": "",
7 "license": "", 7 "license": "",
8 - "dependencies": {} 8 + "dependencies": {
  9 + // please see https://ohpm.openharmony.cn/#/cn/detail/sherpa_onnx
  10 + "sherpa_onnx": "1.10.32",
  11 + }
9 } 12 }
10 13
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 import { OfflineModelConfig } from 'sherpa_onnx'; 4 import { OfflineModelConfig } from 'sherpa_onnx';
5 5
6 export function getOfflineModelConfig(type: number): OfflineModelConfig { 6 export function getOfflineModelConfig(type: number): OfflineModelConfig {
7 - const c = new OfflineModelConfig(); 7 + const c: OfflineModelConfig = new OfflineModelConfig();
8 switch (type) { 8 switch (type) {
9 case 0: { 9 case 0: {
10 const modelDir = 'sherpa-onnx-paraformer-zh-2023-09-14' 10 const modelDir = 'sherpa-onnx-paraformer-zh-2023-09-14'
@@ -2,8 +2,11 @@ import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit @@ -2,8 +2,11 @@ import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit
2 import { 2 import {
3 OfflineRecognizer, 3 OfflineRecognizer,
4 OfflineRecognizerConfig, 4 OfflineRecognizerConfig,
  5 + OfflineStream,
  6 + OnlineRecognizerResult,
5 readWaveFromBinary, 7 readWaveFromBinary,
6 SileroVadConfig, 8 SileroVadConfig,
  9 + SpeechSegment,
7 Vad, 10 Vad,
8 VadConfig, 11 VadConfig,
9 } from 'sherpa_onnx'; 12 } from 'sherpa_onnx';
@@ -18,7 +21,7 @@ let vad: Vad; // vad for decoding files @@ -18,7 +21,7 @@ let vad: Vad; // vad for decoding files
18 21
19 function initVad(context: Context): Vad { 22 function initVad(context: Context): Vad {
20 let mgr = context.resourceManager; 23 let mgr = context.resourceManager;
21 - const config = new VadConfig( 24 + const config: VadConfig = new VadConfig(
22 new SileroVadConfig( 25 new SileroVadConfig(
23 'silero_vad.onnx', 26 'silero_vad.onnx',
24 0.5, 27 0.5,
@@ -37,7 +40,7 @@ function initVad(context: Context): Vad { @@ -37,7 +40,7 @@ function initVad(context: Context): Vad {
37 40
38 function initNonStreamingAsr(context: Context): OfflineRecognizer { 41 function initNonStreamingAsr(context: Context): OfflineRecognizer {
39 let mgr = context.resourceManager; 42 let mgr = context.resourceManager;
40 - const config = new OfflineRecognizerConfig(); 43 + const config: OfflineRecognizerConfig = new OfflineRecognizerConfig();
41 44
42 // Note that you can switch to a new model by changing type 45 // Note that you can switch to a new model by changing type
43 // 46 //
@@ -61,7 +64,13 @@ function initNonStreamingAsr(context: Context): OfflineRecognizer { @@ -61,7 +64,13 @@ function initNonStreamingAsr(context: Context): OfflineRecognizer {
61 const type = 2; 64 const type = 2;
62 config.modelConfig = getOfflineModelConfig(type); 65 config.modelConfig = getOfflineModelConfig(type);
63 config.modelConfig.debug = true; 66 config.modelConfig.debug = true;
64 - return new OfflineRecognizer(config, mgr) 67 + config.ruleFsts = '';
  68 + return new OfflineRecognizer(config, mgr);
  69 +}
  70 +
  71 +interface Wave {
  72 + samples: Float32Array;
  73 + sampleRate: number;
65 } 74 }
66 75
67 function decode(filename: string): string { 76 function decode(filename: string): string {
@@ -71,44 +80,44 @@ function decode(filename: string): string { @@ -71,44 +80,44 @@ function decode(filename: string): string {
71 const stat = fileIo.statSync(fp.fd); 80 const stat = fileIo.statSync(fp.fd);
72 const arrayBuffer = new ArrayBuffer(stat.size); 81 const arrayBuffer = new ArrayBuffer(stat.size);
73 fileIo.readSync(fp.fd, arrayBuffer); 82 fileIo.readSync(fp.fd, arrayBuffer);
74 - const data = new Uint8Array(arrayBuffer); 83 + const data: Uint8Array = new Uint8Array(arrayBuffer);
75 84
76 - const wave = readWaveFromBinary(data); 85 + const wave: Wave = readWaveFromBinary(data);
77 86
78 console.log(`sample rate ${wave.sampleRate}`); 87 console.log(`sample rate ${wave.sampleRate}`);
79 console.log(`samples length ${wave.samples.length}`); 88 console.log(`samples length ${wave.samples.length}`);
80 const resultList: string[] = []; 89 const resultList: string[] = [];
81 90
82 - const windowSize = vad.config.sileroVad.windowSize; 91 + const windowSize: number = vad.config.sileroVad.windowSize;
83 for (let i = 0; i < wave.samples.length; i += windowSize) { 92 for (let i = 0; i < wave.samples.length; i += windowSize) {
84 - const thisWindow = wave.samples.subarray(i, i + windowSize) 93 + const thisWindow: Float32Array = wave.samples.subarray(i, i + windowSize)
85 vad.acceptWaveform(thisWindow); 94 vad.acceptWaveform(thisWindow);
86 if (i + windowSize >= wave.samples.length) { 95 if (i + windowSize >= wave.samples.length) {
87 vad.flush(); 96 vad.flush();
88 } 97 }
89 while (!vad.isEmpty()) { 98 while (!vad.isEmpty()) {
90 - const segment = vad.front();  
91 - const _startTime = (segment.start / wave.sampleRate);  
92 - const _endTime = _startTime + segment.samples.length / wave.sampleRate; 99 + const segment: SpeechSegment = vad.front();
  100 + const _startTime: number = (segment.start / wave.sampleRate);
  101 + const _endTime: number = _startTime + segment.samples.length / wave.sampleRate;
93 102
94 if (_endTime - _startTime < 0.2) { 103 if (_endTime - _startTime < 0.2) {
95 vad.pop(); 104 vad.pop();
96 continue; 105 continue;
97 } 106 }
98 107
99 - const startTime = _startTime.toFixed(2);  
100 - const endTime = _endTime.toFixed(2); 108 + const startTime: string = _startTime.toFixed(2);
  109 + const endTime: string = _endTime.toFixed(2);
101 110
102 - const progress = (segment.start + segment.samples.length) / wave.samples.length * 100; 111 + const progress: number = (segment.start + segment.samples.length) / wave.samples.length * 100;
103 112
104 workerPort.postMessage({ 'msgType': 'non-streaming-asr-vad-decode-progress', progress }); 113 workerPort.postMessage({ 'msgType': 'non-streaming-asr-vad-decode-progress', progress });
105 114
106 - const stream = recognizer.createStream(); 115 + const stream: OfflineStream = recognizer.createStream();
107 stream.acceptWaveform({ samples: segment.samples, sampleRate: wave.sampleRate }); 116 stream.acceptWaveform({ samples: segment.samples, sampleRate: wave.sampleRate });
108 recognizer.decode(stream); 117 recognizer.decode(stream);
109 - const result = recognizer.getResult(stream); 118 + const result: OnlineRecognizerResult = recognizer.getResult(stream);
110 119
111 - const text = `${startTime} -- ${endTime} ${result.text}` 120 + const text: string = `${startTime} -- ${endTime} ${result.text}`
112 resultList.push(text); 121 resultList.push(text);
113 console.log(`partial result ${text}`); 122 console.log(`partial result ${text}`);
114 123
@@ -2,11 +2,6 @@ @@ -2,11 +2,6 @@
2 "modelVersion": "5.0.0", 2 "modelVersion": "5.0.0",
3 "description": "Please describe the basic information.", 3 "description": "Please describe the basic information.",
4 "dependencies": { 4 "dependencies": {
5 -  
6 - // You can download sherpa_onnx-v1.10.32.har  
7 - // from  
8 - // https://huggingface.co/csukuangfj/sherpa-onnx-harmony-os/tree/main/har  
9 - "sherpa_onnx": "file:./entry/sherpa_onnx-v1.10.32.har"  
10 }, 5 },
11 "devDependencies": { 6 "devDependencies": {
12 "@ohos/hypium": "1.0.19" 7 "@ohos/hypium": "1.0.19"
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 import argparse 3 import argparse
4 from dataclasses import dataclass 4 from dataclasses import dataclass
  5 +from pathlib import Path
5 6
6 import jinja2 7 import jinja2
7 8
@@ -34,6 +35,7 @@ class Model: @@ -34,6 +35,7 @@ class Model:
34 35
35 # e.g., zh, en, zh_en 36 # e.g., zh, en, zh_en
36 lang: str 37 lang: str
  38 + lang2: str
37 39
38 # e.g., whisper, paraformer, zipformer 40 # e.g., whisper, paraformer, zipformer
39 short_name: str = "" 41 short_name: str = ""
@@ -51,6 +53,7 @@ def get_models(): @@ -51,6 +53,7 @@ def get_models():
51 model_name="sherpa-onnx-whisper-tiny.en", 53 model_name="sherpa-onnx-whisper-tiny.en",
52 idx=2, 54 idx=2,
53 lang="en", 55 lang="en",
  56 + lang2="English",
54 short_name="whisper_tiny", 57 short_name="whisper_tiny",
55 cmd=""" 58 cmd="""
56 pushd $model_name 59 pushd $model_name
@@ -71,6 +74,7 @@ def get_models(): @@ -71,6 +74,7 @@ def get_models():
71 model_name="sherpa-onnx-paraformer-zh-2023-09-14", 74 model_name="sherpa-onnx-paraformer-zh-2023-09-14",
72 idx=0, 75 idx=0,
73 lang="zh_en", 76 lang="zh_en",
  77 + lang2="Chinese,English",
74 short_name="paraformer", 78 short_name="paraformer",
75 rule_fsts="itn_zh_number.fst", 79 rule_fsts="itn_zh_number.fst",
76 cmd=""" 80 cmd="""
@@ -92,6 +96,7 @@ def get_models(): @@ -92,6 +96,7 @@ def get_models():
92 model_name="sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17", 96 model_name="sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17",
93 idx=15, 97 idx=15,
94 lang="zh_en_ko_ja_yue", 98 lang="zh_en_ko_ja_yue",
  99 + lang2="中英粤日韩",
95 short_name="sense_voice", 100 short_name="sense_voice",
96 cmd=""" 101 cmd="""
97 pushd $model_name 102 pushd $model_name
@@ -109,6 +114,7 @@ def get_models(): @@ -109,6 +114,7 @@ def get_models():
109 model_name="sherpa-onnx-paraformer-zh-small-2024-03-09", 114 model_name="sherpa-onnx-paraformer-zh-small-2024-03-09",
110 idx=14, 115 idx=14,
111 lang="zh_en", 116 lang="zh_en",
  117 + lang2="Chinese,English",
112 short_name="small_paraformer", 118 short_name="small_paraformer",
113 rule_fsts="itn_zh_number.fst", 119 rule_fsts="itn_zh_number.fst",
114 cmd=""" 120 cmd="""
@@ -132,6 +138,7 @@ def get_models(): @@ -132,6 +138,7 @@ def get_models():
132 model_name="icefall-asr-zipformer-wenetspeech-20230615", 138 model_name="icefall-asr-zipformer-wenetspeech-20230615",
133 idx=4, 139 idx=4,
134 lang="zh", 140 lang="zh",
  141 + lang2="Chinese",
135 short_name="zipformer", 142 short_name="zipformer",
136 rule_fsts="itn_zh_number.fst", 143 rule_fsts="itn_zh_number.fst",
137 cmd=""" 144 cmd="""
@@ -159,6 +166,7 @@ def get_models(): @@ -159,6 +166,7 @@ def get_models():
159 model_name="sherpa-onnx-nemo-fast-conformer-ctc-be-de-en-es-fr-hr-it-pl-ru-uk-20k", 166 model_name="sherpa-onnx-nemo-fast-conformer-ctc-be-de-en-es-fr-hr-it-pl-ru-uk-20k",
160 idx=7, 167 idx=7,
161 lang="be_de_en_es_fr_hr_it_pl_ru_uk", 168 lang="be_de_en_es_fr_hr_it_pl_ru_uk",
  169 + lang2="be_de_en_es_fr_hr_it_pl_ru_uk",
162 short_name="fast_conformer_ctc_20k", 170 short_name="fast_conformer_ctc_20k",
163 cmd=""" 171 cmd="""
164 pushd $model_name 172 pushd $model_name
@@ -174,6 +182,7 @@ def get_models(): @@ -174,6 +182,7 @@ def get_models():
174 model_name="sherpa-onnx-nemo-fast-conformer-ctc-en-24500", 182 model_name="sherpa-onnx-nemo-fast-conformer-ctc-en-24500",
175 idx=8, 183 idx=8,
176 lang="en", 184 lang="en",
  185 + lang2="English",
177 short_name="fast_conformer_ctc_24500", 186 short_name="fast_conformer_ctc_24500",
178 cmd=""" 187 cmd="""
179 pushd $model_name 188 pushd $model_name
@@ -188,7 +197,8 @@ def get_models(): @@ -188,7 +197,8 @@ def get_models():
188 Model( 197 Model(
189 model_name="sherpa-onnx-nemo-fast-conformer-ctc-en-de-es-fr-14288", 198 model_name="sherpa-onnx-nemo-fast-conformer-ctc-en-de-es-fr-14288",
190 idx=9, 199 idx=9,
191 - lang="en_des_es_fr", 200 + lang="en_de_es_fr",
  201 + lang2="English,German,Spanish,French",
192 short_name="fast_conformer_ctc_14288", 202 short_name="fast_conformer_ctc_14288",
193 cmd=""" 203 cmd="""
194 pushd $model_name 204 pushd $model_name
@@ -204,6 +214,7 @@ def get_models(): @@ -204,6 +214,7 @@ def get_models():
204 model_name="sherpa-onnx-nemo-fast-conformer-ctc-es-1424", 214 model_name="sherpa-onnx-nemo-fast-conformer-ctc-es-1424",
205 idx=10, 215 idx=10,
206 lang="es", 216 lang="es",
  217 + lang2="Spanish",
207 short_name="fast_conformer_ctc_1424", 218 short_name="fast_conformer_ctc_1424",
208 cmd=""" 219 cmd="""
209 pushd $model_name 220 pushd $model_name
@@ -219,6 +230,7 @@ def get_models(): @@ -219,6 +230,7 @@ def get_models():
219 model_name="sherpa-onnx-telespeech-ctc-int8-zh-2024-06-04", 230 model_name="sherpa-onnx-telespeech-ctc-int8-zh-2024-06-04",
220 idx=11, 231 idx=11,
221 lang="zh", 232 lang="zh",
  233 + lang2="Chinese",
222 short_name="telespeech", 234 short_name="telespeech",
223 rule_fsts="itn_zh_number.fst", 235 rule_fsts="itn_zh_number.fst",
224 cmd=""" 236 cmd="""
@@ -239,6 +251,7 @@ def get_models(): @@ -239,6 +251,7 @@ def get_models():
239 model_name="sherpa-onnx-zipformer-thai-2024-06-20", 251 model_name="sherpa-onnx-zipformer-thai-2024-06-20",
240 idx=12, 252 idx=12,
241 lang="th", 253 lang="th",
  254 + lang2="Thai",
242 short_name="zipformer", 255 short_name="zipformer",
243 cmd=""" 256 cmd="""
244 pushd $model_name 257 pushd $model_name
@@ -260,6 +273,7 @@ def get_models(): @@ -260,6 +273,7 @@ def get_models():
260 model_name="sherpa-onnx-zipformer-korean-2024-06-24", 273 model_name="sherpa-onnx-zipformer-korean-2024-06-24",
261 idx=13, 274 idx=13,
262 lang="ko", 275 lang="ko",
  276 + lang2="Korean",
263 short_name="zipformer", 277 short_name="zipformer",
264 cmd=""" 278 cmd="""
265 pushd $model_name 279 pushd $model_name
@@ -281,6 +295,7 @@ def get_models(): @@ -281,6 +295,7 @@ def get_models():
281 model_name="sherpa-onnx-zipformer-ja-reazonspeech-2024-08-01", 295 model_name="sherpa-onnx-zipformer-ja-reazonspeech-2024-08-01",
282 idx=16, 296 idx=16,
283 lang="ja", 297 lang="ja",
  298 + lang2="Japanese",
284 short_name="zipformer_reazonspeech", 299 short_name="zipformer_reazonspeech",
285 cmd=""" 300 cmd="""
286 pushd $model_name 301 pushd $model_name
@@ -300,6 +315,7 @@ def get_models(): @@ -300,6 +315,7 @@ def get_models():
300 model_name="sherpa-onnx-zipformer-ru-2024-09-18", 315 model_name="sherpa-onnx-zipformer-ru-2024-09-18",
301 idx=17, 316 idx=17,
302 lang="ru", 317 lang="ru",
  318 + lang2="Russian",
303 short_name="zipformer", 319 short_name="zipformer",
304 cmd=""" 320 cmd="""
305 pushd $model_name 321 pushd $model_name
@@ -320,6 +336,7 @@ def get_models(): @@ -320,6 +336,7 @@ def get_models():
320 model_name="sherpa-onnx-small-zipformer-ru-2024-09-18", 336 model_name="sherpa-onnx-small-zipformer-ru-2024-09-18",
321 idx=18, 337 idx=18,
322 lang="ru", 338 lang="ru",
  339 + lang2="Russian",
323 short_name="small_zipformer", 340 short_name="small_zipformer",
324 cmd=""" 341 cmd="""
325 pushd $model_name 342 pushd $model_name
@@ -340,6 +357,7 @@ def get_models(): @@ -340,6 +357,7 @@ def get_models():
340 model_name="sherpa-onnx-nemo-ctc-giga-am-russian-2024-10-24", 357 model_name="sherpa-onnx-nemo-ctc-giga-am-russian-2024-10-24",
341 idx=19, 358 idx=19,
342 lang="ru", 359 lang="ru",
  360 + lang2="Russian",
343 short_name="nemo_ctc_giga_am", 361 short_name="nemo_ctc_giga_am",
344 cmd=""" 362 cmd="""
345 pushd $model_name 363 pushd $model_name
@@ -358,6 +376,7 @@ def get_models(): @@ -358,6 +376,7 @@ def get_models():
358 model_name="sherpa-onnx-nemo-transducer-giga-am-russian-2024-10-24", 376 model_name="sherpa-onnx-nemo-transducer-giga-am-russian-2024-10-24",
359 idx=20, 377 idx=20,
360 lang="ru", 378 lang="ru",
  379 + lang2="Russian",
361 short_name="nemo_transducer_giga_am", 380 short_name="nemo_transducer_giga_am",
362 cmd=""" 381 cmd="""
363 pushd $model_name 382 pushd $model_name
@@ -376,6 +395,7 @@ def get_models(): @@ -376,6 +395,7 @@ def get_models():
376 model_name="sherpa-onnx-moonshine-tiny-en-int8", 395 model_name="sherpa-onnx-moonshine-tiny-en-int8",
377 idx=21, 396 idx=21,
378 lang="en", 397 lang="en",
  398 + lang2="English",
379 short_name="moonshine_tiny_int8", 399 short_name="moonshine_tiny_int8",
380 cmd=""" 400 cmd="""
381 pushd $model_name 401 pushd $model_name
@@ -391,6 +411,7 @@ def get_models(): @@ -391,6 +411,7 @@ def get_models():
391 model_name="sherpa-onnx-moonshine-base-en-int8", 411 model_name="sherpa-onnx-moonshine-base-en-int8",
392 idx=22, 412 idx=22,
393 lang="en", 413 lang="en",
  414 + lang2="English",
394 short_name="moonshine_base_int8", 415 short_name="moonshine_base_int8",
395 cmd=""" 416 cmd="""
396 pushd $model_name 417 pushd $model_name
@@ -436,9 +457,14 @@ def main(): @@ -436,9 +457,14 @@ def main():
436 457
437 filename_list = [ 458 filename_list = [
438 "./build-apk-vad-asr.sh", 459 "./build-apk-vad-asr.sh",
  460 + "./build-hap-vad-asr.sh",
439 ] 461 ]
440 for filename in filename_list: 462 for filename in filename_list:
441 environment = jinja2.Environment() 463 environment = jinja2.Environment()
  464 + if not Path(f"{filename}.in").is_file():
  465 + print(f"skip {filename}")
  466 + continue
  467 +
442 with open(f"{filename}.in") as f: 468 with open(f"{filename}.in") as f:
443 s = f.read() 469 s = f.read()
444 template = environment.from_string(s) 470 template = environment.from_string(s)
  1 +#!/usr/bin/env bash
  2 +#
  3 +# Auto generated! Please DO NOT EDIT!
  4 +
  5 +# Please set the environment variable COMMANDLINE_TOOLS_DIR
  6 +# before running this script
  7 +
  8 +# Inside the $COMMANDLINE_TOOL_DIR directory, you can find the following:
  9 +#
  10 +# command-line-tools fangjun$ ls
  11 +# LICENSE.txt NOTICE.txt bin codelinter hstack hvigor ohpm sdk tool
  12 +
  13 +set -ex
  14 +
  15 +log() {
  16 + # This function is from espnet
  17 + local fname=${BASH_SOURCE[1]##*/}
  18 + echo -e "$(date '+%Y-%m-%d %H:%M:%S') (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $*"
  19 +}
  20 +
  21 +SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
  22 +
  23 +log "Building streaming VAD + ASR Hap for sherpa-onnx v${SHERPA_ONNX_VERSION}"
  24 +
  25 +export SHERPA_ONNX_ENABLE_TTS=OFF
  26 +
  27 +if [ ! -f $COMMANDLINE_TOOLS_DIR/bin/hvigorw ]; then
  28 + echo "Please first download Command Line Tools for HarmonyOS"
  29 + echo "See https://developer.huawei.com/consumer/cn/download/"
  30 + echo "or"
  31 + echo "https://hf-mirror.com/csukuangfj/harmonyos-commandline-tools/tree/main"
  32 + exit 1
  33 +fi
  34 +
  35 +jar=$COMMANDLINE_TOOLS_DIR/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar
  36 +
  37 +export PATH=$COMMANDLINE_TOOLS_DIR/bin:$PATH
  38 +
  39 +mkdir -p haps
  40 +
  41 +{% for model in model_list %}
  42 +pushd ./harmony-os/SherpaOnnxVadAsr/entry/src/main/resources/rawfile
  43 +model_name={{ model.model_name }}
  44 +type={{ model.idx }}
  45 +lang={{ model.lang }}
  46 +lang2={{ model.lang2 }}
  47 +short_name={{ model.short_name }}
  48 +
  49 +curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/${model_name}.tar.bz2
  50 +tar xvf ${model_name}.tar.bz2
  51 +
  52 +{{ model.cmd }}
  53 +
  54 +rm -rf *.tar.bz2
  55 +ls -lh $model_name
  56 +
  57 +if [ ! -f ./silero_vad.onnx ]; then
  58 + curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad.onnx
  59 +fi
  60 +
  61 +popd
  62 +# Now we are at the project root directory
  63 +
  64 +git checkout .
  65 +pushd harmony-os/SherpaOnnxVadAsr/entry/src/main/ets/workers/
  66 +sed -i.bak s/"const type = 2/const type = $type/" ./NonStreamingAsrWithVadWorker.ets
  67 +
  68 +{% if model.rule_fsts %}
  69 + rule_fsts={{ model.rule_fsts }}
  70 + sed -i.bak s%"ruleFsts = ''"%"ruleFsts = \"$rule_fsts\""% ./NonStreamingAsrWithVadWorker.ets
  71 +{% endif %}
  72 +
  73 +git diff
  74 +popd
  75 +
  76 +pushd harmony-os/SherpaOnnxVadAsr/entry/src/main/ets/pages
  77 +sed -i.bak s/English/$lang2/ ./Index.ets
  78 +popd
  79 +
  80 +pushd harmony-os/SherpaOnnxVadAsr
  81 +
  82 +git diff
  83 +
  84 +cd entry
  85 +ohpm install
  86 +cd ..
  87 +
  88 +hvigorw clean --no-daemon
  89 +hvigorw assembleHap --mode module -p product=default -p buildMode=release --no-daemon
  90 +
  91 +ls -lh ./entry/build/default/outputs/default/entry-default-unsigned.hap
  92 +
  93 +in_file=./entry/build/default/outputs/default/entry-default-unsigned.hap
  94 +out_file=$PWD/entry/build/default/outputs/default/entry-default-signed.hap
  95 +
  96 +java -jar $jar sign-app -keyAlias "$HAP_KEY_ALIAS" -signAlg "SHA256withECDSA" -mode "localSign" \
  97 + -appCertFile "/tmp/sherpa_onnx.cer" -profileFile "/tmp/sherpa_onnx_profileRelease.p7b" \
  98 + -inFile $in_file -keystoreFile "/tmp/sherpa_onnx_ohos_key.p12" \
  99 + -outFile $out_file -keyPwd "$HAP_KEY_PWD" -keystorePwd "$HAP_KEY_STORE_PWD" -signCode "1"
  100 +
  101 +ls -l $in_file $out_file
  102 +ls -lh $in_file $out_file
  103 +rm $in_file
  104 +rm -rf ./entry/src/main/resources/rawfile/$model_name
  105 +popd
  106 +
  107 +mv $out_file ./haps/sherpa-onnx-${SHERPA_ONNX_VERSION}-vad_asr-$lang-$short_name.hap
  108 +
  109 +ls -lh haps
  110 +
  111 +{% endfor %}
  112 +
  113 +git checkout .
  114 +
  115 +ls -lh haps/
  1 +../apk/generate-vad-asr-apk-script.py