Skip to content

Commit 7ad44bc

Browse files
authored
Add JavaScript API (WebAssembly) for FireRedAsr model. (#1874)
1 parent 050df2a commit 7ad44bc

6 files changed

+112
-4
lines changed

new-release.sh

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ find dart-api-examples -name *.yaml -type f -exec sed -i.bak 's/1\.10\.43/1\.10\
1414
find flutter-examples -name *.yaml -type f -exec sed -i.bak 's/1\.10\.43/1\.10\.44/g' {} \;
1515
find flutter -name *.podspec -type f -exec sed -i.bak 's/1\.10\.43/1\.10\.44/g' {} \;
1616
find nodejs-addon-examples -name package.json -type f -exec sed -i.bak 's/1\.10\.43/1\.10\.44/g' {} \;
17+
find nodejs-examples -name package.json -type f -exec sed -i.bak 's/1\.10\.43/1\.10\.44/g' {} \;
1718

1819
find harmony-os -name "README.md" -type f -exec sed -i.bak 's/1\.10\.43/1\.10\.44/g' {} \;
1920
find harmony-os -name oh-package.json5 -type f -exec sed -i.bak 's/1\.10\.43/1\.10\.44/g' {} \;

nodejs-examples/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,21 @@ tar xvf sherpa-onnx-whisper-tiny.en.tar.bz2
216216
node ./test-offline-whisper.js
217217
```
218218

219+
## ./test-offline-fire-red-asr.js
220+
221+
[./test-offline-fire-red-asr.js](./test-offline-fire-red-asr.js) demonstrates
222+
how to decode a file with a FireRedAsr AED model.
223+
224+
You can use the following command to run it:
225+
226+
```bash
227+
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16.tar.bz2
228+
tar xvf sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16.tar.bz2
229+
rm sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16.tar.bz2
230+
231+
node ./test-offline-fire-red-asr.js
232+
```
233+
219234
## ./test-offline-moonshine.js
220235

221236
[./test-offline-moonshine.js](./test-offline-moonshine.js) demonstrates

nodejs-examples/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"dependencies": {
33
"naudiodon2": "^2.4.0",
4-
"sherpa-onnx": "*",
4+
"sherpa-onnx": "^1.10.44",
55
"wav": "^1.0.2"
66
}
77
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) 2025 Xiaomi Corporation (authors: Fangjun Kuang)
2+
//
3+
const sherpa_onnx = require('sherpa-onnx');
4+
5+
function createOfflineRecognizer() {
6+
let modelConfig = {
7+
fireRedAsr: {
8+
encoder:
9+
'./sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16/encoder.int8.onnx',
10+
decoder:
11+
'./sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16/decoder.int8.onnx',
12+
},
13+
tokens: './sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16/tokens.txt',
14+
debug: 1,
15+
};
16+
17+
let config = {
18+
modelConfig: modelConfig,
19+
};
20+
21+
return sherpa_onnx.createOfflineRecognizer(config);
22+
}
23+
24+
recognizer = createOfflineRecognizer();
25+
stream = recognizer.createStream();
26+
27+
const waveFilename =
28+
'./sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16/test_wavs/0.wav';
29+
const wave = sherpa_onnx.readWave(waveFilename);
30+
stream.acceptWaveform(wave.sampleRate, wave.samples);
31+
32+
recognizer.decode(stream);
33+
const text = recognizer.getResult(stream).text;
34+
console.log(text);
35+
36+
stream.free();
37+
recognizer.free();

wasm/asr/sherpa-onnx-asr.js

+49-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ function freeConfig(config, Module) {
3535
freeConfig(config.whisper, Module)
3636
}
3737

38+
if ('fireRedAsr' in config) {
39+
freeConfig(config.fireRedAsr, Module)
40+
}
41+
3842
if ('moonshine' in config) {
3943
freeConfig(config.moonshine, Module)
4044
}
@@ -651,6 +655,35 @@ function initSherpaOnnxOfflineMoonshineModelConfig(config, Module) {
651655
}
652656
}
653657

658+
function initSherpaOnnxOfflineFireRedAsrModelConfig(config, Module) {
659+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
660+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
661+
662+
const n = encoderLen + decoderLen;
663+
const buffer = Module._malloc(n);
664+
665+
const len = 2 * 4; // 2 pointers
666+
const ptr = Module._malloc(len);
667+
668+
let offset = 0;
669+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
670+
offset += encoderLen;
671+
672+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
673+
offset += decoderLen;
674+
675+
offset = 0;
676+
Module.setValue(ptr, buffer + offset, 'i8*');
677+
offset += encoderLen;
678+
679+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
680+
offset += decoderLen;
681+
682+
return {
683+
buffer: buffer, ptr: ptr, len: len,
684+
}
685+
}
686+
654687
function initSherpaOnnxOfflineTdnnModelConfig(config, Module) {
655688
const n = Module.lengthBytesUTF8(config.model || '') + 1;
656689
const buffer = Module._malloc(n);
@@ -755,6 +788,13 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
755788
};
756789
}
757790

791+
if (!('fireRedAsr' in config)) {
792+
config.fireRedAsr = {
793+
encoder: '',
794+
decoder: '',
795+
};
796+
}
797+
758798
if (!('tdnn' in config)) {
759799
config.tdnn = {
760800
model: '',
@@ -789,8 +829,11 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
789829
const moonshine =
790830
initSherpaOnnxOfflineMoonshineModelConfig(config.moonshine, Module);
791831

832+
const fireRedAsr =
833+
initSherpaOnnxOfflineFireRedAsrModelConfig(config.fireRedAsr, Module);
834+
792835
const len = transducer.len + paraformer.len + nemoCtc.len + whisper.len +
793-
tdnn.len + 8 * 4 + senseVoice.len + moonshine.len;
836+
tdnn.len + 8 * 4 + senseVoice.len + moonshine.len + fireRedAsr.len;
794837

795838
const ptr = Module._malloc(len);
796839

@@ -884,11 +927,15 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
884927
offset += senseVoice.len;
885928

886929
Module._CopyHeap(moonshine.ptr, moonshine.len, ptr + offset);
930+
offset += moonshine.len;
931+
932+
Module._CopyHeap(fireRedAsr.ptr, fireRedAsr.len, ptr + offset);
933+
offset += fireRedAsr.len;
887934

888935
return {
889936
buffer: buffer, ptr: ptr, len: len, transducer: transducer,
890937
paraformer: paraformer, nemoCtc: nemoCtc, whisper: whisper, tdnn: tdnn,
891-
senseVoice: senseVoice, moonshine: moonshine,
938+
senseVoice: senseVoice, moonshine: moonshine, fireRedAsr: fireRedAsr
892939
}
893940
}
894941

wasm/nodejs/sherpa-onnx-wasm-nodejs.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ static_assert(sizeof(SherpaOnnxOfflineParaformerModelConfig) == 4, "");
1515

1616
static_assert(sizeof(SherpaOnnxOfflineNemoEncDecCtcModelConfig) == 4, "");
1717
static_assert(sizeof(SherpaOnnxOfflineWhisperModelConfig) == 5 * 4, "");
18+
static_assert(sizeof(SherpaOnnxOfflineFireRedAsrModelConfig) == 2 * 4, "");
1819
static_assert(sizeof(SherpaOnnxOfflineMoonshineModelConfig) == 4 * 4, "");
1920
static_assert(sizeof(SherpaOnnxOfflineTdnnModelConfig) == 4, "");
2021
static_assert(sizeof(SherpaOnnxOfflineSenseVoiceModelConfig) == 3 * 4, "");
@@ -27,7 +28,9 @@ static_assert(sizeof(SherpaOnnxOfflineModelConfig) ==
2728
sizeof(SherpaOnnxOfflineWhisperModelConfig) +
2829
sizeof(SherpaOnnxOfflineTdnnModelConfig) + 8 * 4 +
2930
sizeof(SherpaOnnxOfflineSenseVoiceModelConfig) +
30-
sizeof(SherpaOnnxOfflineMoonshineModelConfig),
31+
sizeof(SherpaOnnxOfflineMoonshineModelConfig) +
32+
sizeof(SherpaOnnxOfflineFireRedAsrModelConfig),
33+
3134
"");
3235
static_assert(sizeof(SherpaOnnxFeatureConfig) == 2 * 4, "");
3336
static_assert(sizeof(SherpaOnnxOfflineRecognizerConfig) ==
@@ -69,6 +72,7 @@ void PrintOfflineRecognizerConfig(SherpaOnnxOfflineRecognizerConfig *config) {
6972
auto tdnn = &model_config->tdnn;
7073
auto sense_voice = &model_config->sense_voice;
7174
auto moonshine = &model_config->moonshine;
75+
auto fire_red_asr = &model_config->fire_red_asr;
7276

7377
fprintf(stdout, "----------offline transducer model config----------\n");
7478
fprintf(stdout, "encoder: %s\n", transducer->encoder);
@@ -102,6 +106,10 @@ void PrintOfflineRecognizerConfig(SherpaOnnxOfflineRecognizerConfig *config) {
102106
fprintf(stdout, "uncached_decoder: %s\n", moonshine->uncached_decoder);
103107
fprintf(stdout, "cached_decoder: %s\n", moonshine->cached_decoder);
104108

109+
fprintf(stdout, "----------offline FireRedAsr model config----------\n");
110+
fprintf(stdout, "encoder: %s\n", fire_red_asr->encoder);
111+
fprintf(stdout, "decoder: %s\n", fire_red_asr->decoder);
112+
105113
fprintf(stdout, "tokens: %s\n", model_config->tokens);
106114
fprintf(stdout, "num_threads: %d\n", model_config->num_threads);
107115
fprintf(stdout, "provider: %s\n", model_config->provider);

0 commit comments

Comments
 (0)