Skip to content

Commit 1f12460

Browse files
authored
Add Kotlin and Java API for Google MedAsr model (#2956)
1 parent 2f8fb50 commit 1f12460

16 files changed

Lines changed: 257 additions & 21 deletions

.github/workflows/run-java-test.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ jobs:
108108
cd ./java-api-examples
109109
./run-version-test.sh
110110
111+
- name: Run java test (MedASR CTC)
112+
shell: bash
113+
run: |
114+
cd ./java-api-examples
115+
./run-non-streaming-decode-file-medasr-ctc.sh
116+
rm -rf sherpa-onnx-medasr-*
117+
118+
111119
- name: Run java test (Omnilingual ASR CTC)
112120
shell: bash
113121
run: |
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2025 Xiaomi Corporation
2+
3+
// This file shows how to use an offline Google MedASR CTC model,
4+
// i.e., non-streaming MedASR CTC model,
5+
// to decode files.
6+
import com.k2fsa.sherpa.onnx.*;
7+
8+
public class NonStreamingDecodeFileMedAsrCtc {
9+
public static void main(String[] args) {
10+
// please refer to
11+
// https://k2-fsa.github.io/sherpa/onnx/medasr/index.html
12+
// to download model files
13+
String model = "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/model.int8.onnx";
14+
15+
String tokens = "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/tokens.txt";
16+
17+
String waveFilename = "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/test_wavs/0.wav";
18+
19+
WaveReader reader = new WaveReader(waveFilename);
20+
21+
OfflineMedAsrCtcModelConfig medasr =
22+
OfflineMedAsrCtcModelConfig.builder().setModel(model).build();
23+
24+
OfflineModelConfig modelConfig =
25+
OfflineModelConfig.builder()
26+
.setMedAsr(medasr)
27+
.setTokens(tokens)
28+
.setNumThreads(1)
29+
.setDebug(true)
30+
.build();
31+
32+
OfflineRecognizerConfig config =
33+
OfflineRecognizerConfig.builder()
34+
.setOfflineModelConfig(modelConfig)
35+
.setDecodingMethod("greedy_search")
36+
.build();
37+
38+
OfflineRecognizer recognizer = new OfflineRecognizer(config);
39+
OfflineStream stream = recognizer.createStream();
40+
stream.acceptWaveform(reader.getSamples(), reader.getSampleRate());
41+
42+
recognizer.decode(stream);
43+
44+
String text = recognizer.getResult(stream).getText();
45+
46+
System.out.printf("filename:%s\nresult:%s\n", waveFilename, text);
47+
48+
stream.release();
49+
recognizer.release();
50+
}
51+
}

java-api-examples/NonStreamingDecodeFileOmnilingualAsrCtc.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
public class NonStreamingDecodeFileOmnilingualAsrCtc {
99
public static void main(String[] args) {
1010
// please refer to
11-
// https://k2-fsa.github.io/sherpa/onnx/sense-voice/index.html
11+
// https://k2-fsa.github.io/sherpa/onnx/omnilingual-asr/index.html
1212
// to download model files
1313
String model =
1414
"sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/model.int8.onnx";
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
3+
set -ex
4+
5+
if [[ ! -f ../build/lib/libsherpa-onnx-jni.dylib && ! -f ../build/lib/libsherpa-onnx-jni.so ]]; then
6+
mkdir -p ../build
7+
pushd ../build
8+
cmake \
9+
-DSHERPA_ONNX_ENABLE_PYTHON=OFF \
10+
-DSHERPA_ONNX_ENABLE_TESTS=OFF \
11+
-DSHERPA_ONNX_ENABLE_CHECK=OFF \
12+
-DBUILD_SHARED_LIBS=ON \
13+
-DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
14+
-DSHERPA_ONNX_ENABLE_JNI=ON \
15+
..
16+
17+
make -j4
18+
ls -lh lib
19+
popd
20+
fi
21+
22+
if [ ! -f ../sherpa-onnx/java-api/build/sherpa-onnx.jar ]; then
23+
pushd ../sherpa-onnx/java-api
24+
make
25+
popd
26+
fi
27+
28+
if [ ! -f ./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/tokens.txt ]; then
29+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2
30+
tar xvf sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2
31+
rm sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2
32+
fi
33+
34+
35+
java \
36+
-Djava.library.path=$PWD/../build/lib \
37+
-cp ../sherpa-onnx/java-api/build/sherpa-onnx.jar \
38+
NonStreamingDecodeFileMedAsrCtc.java

kotlin-api-examples/run.sh

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,10 @@ function testOfflineAsr() {
234234
rm sherpa-onnx-moonshine-tiny-en-int8.tar.bz2
235235
fi
236236

237-
if [ ! -f ./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/tokens.txt ]; then
238-
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
239-
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
240-
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
237+
if [ ! -f ./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/tokens.txt ]; then
238+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
239+
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
240+
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
241241
fi
242242

243243
if [ ! -f ./sherpa-onnx-whisper-tiny.en/tiny.en-encoder.int8.onnx ]; then
@@ -439,10 +439,10 @@ function testOfflineSpeechDenoiser() {
439439
}
440440

441441
function testOfflineSenseVoiceWithHr() {
442-
if [ ! -f ./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/tokens.txt ]; then
443-
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
444-
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
445-
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
442+
if [ ! -f ./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/tokens.txt ]; then
443+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
444+
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
445+
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
446446
fi
447447

448448
if [ ! -d dict ]; then
@@ -515,6 +515,28 @@ function testOfflineOmnilingualAsrCtc() {
515515
java -Djava.library.path=../build/lib -jar $out_filename
516516
}
517517

518+
function testOfflineMedAsrCtc() {
519+
if [ ! -f ./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/tokens.txt ]; then
520+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2
521+
tar xvf sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2
522+
rm sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2
523+
fi
524+
525+
out_filename=test_offline_medasr_ctc.jar
526+
kotlinc-jvm -include-runtime -d $out_filename \
527+
test_offline_medasr_ctc.kt \
528+
FeatureConfig.kt \
529+
QnnConfig.kt \
530+
HomophoneReplacerConfig.kt \
531+
OfflineRecognizer.kt \
532+
OfflineStream.kt \
533+
WaveReader.kt \
534+
faked-asset-manager.kt
535+
536+
ls -lh $out_filename
537+
java -Djava.library.path=../build/lib -jar $out_filename
538+
}
539+
518540
function testOfflineWenetCtc() {
519541
if [ ! -f sherpa-onnx-wenetspeech-yue-u2pp-conformer-ctc-zh-en-cantonese-int8-2025-09-10/model.int8.onnx ]; then
520542
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-wenetspeech-yue-u2pp-conformer-ctc-zh-en-cantonese-int8-2025-09-10.tar.bz2
@@ -539,6 +561,7 @@ function testOfflineWenetCtc() {
539561

540562
testVersion
541563

564+
testOfflineMedAsrCtc
542565
testOfflineOmnilingualAsrCtc
543566
testOfflineWenetCtc
544567
testOfflineNeMoCanary

kotlin-api-examples/test_offline_asr.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fun test(type: Int) {
1515
2 -> "./sherpa-onnx-whisper-tiny.en/test_wavs/0.wav"
1616
5 -> "./sherpa-onnx-zipformer-multi-zh-hans-2023-9-2/test_wavs/1.wav"
1717
6 -> "./sherpa-onnx-nemo-ctc-en-citrinet-512/test_wavs/8k.wav"
18-
15 -> "./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/test_wavs/zh.wav"
18+
15 -> "./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/test_wavs/zh.wav"
1919
21 -> "./sherpa-onnx-moonshine-tiny-en-int8/test_wavs/0.wav"
2020
24 -> "./sherpa-onnx-fire-red-asr-large-zh_en-2025-02-16/test_wavs/0.wav"
2121
25 -> "./sherpa-onnx-dolphin-base-ctc-multi-lang-int8-2025-04-02/test_wavs/0.wav"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.k2fsa.sherpa.onnx
2+
3+
fun main() {
4+
val recognizer = createOfflineRecognizer()
5+
val waveFilename = "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/test_wavs/0.wav"
6+
7+
val objArray = WaveReader.readWaveFromFile(
8+
filename = waveFilename,
9+
)
10+
val samples: FloatArray = objArray[0] as FloatArray
11+
val sampleRate: Int = objArray[1] as Int
12+
13+
var stream = recognizer.createStream()
14+
stream.acceptWaveform(samples, sampleRate=sampleRate)
15+
recognizer.decode(stream)
16+
17+
var result = recognizer.getResult(stream)
18+
println(result)
19+
20+
stream.release()
21+
recognizer.release()
22+
}
23+
24+
25+
fun createOfflineRecognizer(): OfflineRecognizer {
26+
val config = OfflineRecognizerConfig(
27+
modelConfig = getOfflineModelConfig(type = 45)!!,
28+
)
29+
30+
return OfflineRecognizer(config = config)
31+
}

nodejs-examples/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,9 @@ how to decode a file with a non-streaming SenseVoice model with homophone replac
287287
You can use the following command to run it:
288288

289289
```bash
290-
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
291-
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
292-
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
290+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
291+
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
292+
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
293293

294294
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/hr-files/dict.tar.bz2
295295
tar xf dict.tar.bz2
@@ -309,9 +309,9 @@ how to decode a file with a non-streaming SenseVoice model.
309309
You can use the following command to run it:
310310

311311
```bash
312-
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
313-
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
314-
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
312+
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
313+
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
314+
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2
315315

316316
node ./test-offline-sense-voice.js
317317
```

nodejs-examples/test-offline-sense-voice-with-hr.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ function createOfflineRecognizer() {
66
let modelConfig = {
77
senseVoice: {
88
model:
9-
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/model.int8.onnx',
9+
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/model.int8.onnx',
1010
language: '',
1111
useInverseTextNormalization: 1,
1212
},
13-
tokens: './sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/tokens.txt',
13+
tokens:
14+
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/tokens.txt',
1415
};
1516

1617
let config = {

nodejs-examples/test-offline-sense-voice.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ function createOfflineRecognizer() {
66
let modelConfig = {
77
senseVoice: {
88
model:
9-
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/model.int8.onnx',
9+
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/model.int8.onnx',
1010
language: '',
1111
useInverseTextNormalization: 1,
1212
},
13-
tokens: './sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/tokens.txt',
13+
tokens:
14+
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/tokens.txt',
1415
};
1516

1617
let config = {
@@ -24,7 +25,7 @@ const recognizer = createOfflineRecognizer();
2425
const stream = recognizer.createStream();
2526

2627
const waveFilename =
27-
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/test_wavs/zh.wav';
28+
'./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/test_wavs/zh.wav';
2829
const wave = sherpa_onnx.readWave(waveFilename);
2930
stream.acceptWaveform(wave.sampleRate, wave.samples);
3031

0 commit comments

Comments
 (0)