Skip to content

Commit 0f647d3

Browse files
authored
Add Koltin and Java API for Omnilingual ASR CTC models (k2-fsa#2783)
1 parent c218342 commit 0f647d3

11 files changed

Lines changed: 247 additions & 1 deletion

File tree

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,20 @@ jobs:
108108
cd ./java-api-examples
109109
./run-version-test.sh
110110
111+
- name: Run java test (Omnilingual ASR CTC)
112+
shell: bash
113+
run: |
114+
cd ./java-api-examples
115+
./run-non-streaming-decode-file-omnilingual-asr-ctc.sh
116+
rm -rf sherpa-onnx-omnilingual-*
117+
118+
- name: Run java test (WeNet CTC)
119+
shell: bash
120+
run: |
121+
cd ./java-api-examples
122+
./run-non-streaming-decode-file-wenet-ctc.sh
123+
rm -rf sherpa-onnx-wenet*
124+
111125
- name: Run java test (Streaming T-one)
112126
shell: bash
113127
run: |
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2025 Xiaomi Corporation
2+
3+
// This file shows how to use an offline Omnilingual ASR CTC model,
4+
// i.e., non-streaming Omnilingual ASR CTC model,
5+
// to decode files.
6+
import com.k2fsa.sherpa.onnx.*;
7+
8+
public class NonStreamingDecodeFileOmnilingualAsrCtc {
9+
public static void main(String[] args) {
10+
// please refer to
11+
// https://k2-fsa.github.io/sherpa/onnx/sense-voice/index.html
12+
// to download model files
13+
String model =
14+
"sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/model.int8.onnx";
15+
16+
String tokens =
17+
"sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/tokens.txt";
18+
19+
String waveFilename =
20+
"./sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/test_wavs/en.wav";
21+
22+
WaveReader reader = new WaveReader(waveFilename);
23+
24+
OfflineOmnilingualAsrCtcModelConfig omnilingual =
25+
OfflineOmnilingualAsrCtcModelConfig.builder().setModel(model).build();
26+
27+
OfflineModelConfig modelConfig =
28+
OfflineModelConfig.builder()
29+
.setOmnilingual(omnilingual)
30+
.setTokens(tokens)
31+
.setNumThreads(1)
32+
.setDebug(true)
33+
.build();
34+
35+
OfflineRecognizerConfig config =
36+
OfflineRecognizerConfig.builder()
37+
.setOfflineModelConfig(modelConfig)
38+
.setDecodingMethod("greedy_search")
39+
.build();
40+
41+
OfflineRecognizer recognizer = new OfflineRecognizer(config);
42+
OfflineStream stream = recognizer.createStream();
43+
stream.acceptWaveform(reader.getSamples(), reader.getSampleRate());
44+
45+
recognizer.decode(stream);
46+
47+
String text = recognizer.getResult(stream).getText();
48+
49+
System.out.printf("filename:%s\nresult:%s\n", waveFilename, text);
50+
51+
stream.release();
52+
recognizer.release();
53+
}
54+
}
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-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/tokens.txt ]; then
29+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12.tar.bz2
30+
tar xvf sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12.tar.bz2
31+
rm sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12.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+
NonStreamingDecodeFileOmnilingualAsrCtc.java

kotlin-api-examples/run.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,28 @@ function testOfflineNeMoCanary() {
488488
java -Djava.library.path=../build/lib -jar $out_filename
489489
}
490490

491+
492+
function testOfflineOmnilingualAsrCtc() {
493+
if [ ! -f sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/tokens.txt ]; then
494+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12.tar.bz2
495+
tar xvf sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12.tar.bz2
496+
rm sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12.tar.bz2
497+
fi
498+
499+
out_filename=test_offline_omnilingual_asr_ctc.jar
500+
kotlinc-jvm -include-runtime -d $out_filename \
501+
test_offline_omnilingual_asr_ctc.kt \
502+
FeatureConfig.kt \
503+
HomophoneReplacerConfig.kt \
504+
OfflineRecognizer.kt \
505+
OfflineStream.kt \
506+
WaveReader.kt \
507+
faked-asset-manager.kt
508+
509+
ls -lh $out_filename
510+
java -Djava.library.path=../build/lib -jar $out_filename
511+
}
512+
491513
function testOfflineWenetCtc() {
492514
if [ ! -f sherpa-onnx-wenetspeech-yue-u2pp-conformer-ctc-zh-en-cantonese-int8-2025-09-10/model.int8.onnx ]; then
493515
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
@@ -511,6 +533,7 @@ function testOfflineWenetCtc() {
511533

512534
testVersion
513535

536+
testOfflineOmnilingualAsrCtc
514537
testOfflineWenetCtc
515538
testOfflineNeMoCanary
516539
testOfflineSenseVoiceWithHr
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-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12/test_wavs/en.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 = 44)!!,
28+
)
29+
30+
return OfflineRecognizer(config = config)
31+
}

scripts/apk/generate-vad-asr-apk-script.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,22 @@ def get_models():
743743
744744
ls -lh
745745
746+
popd
747+
""",
748+
),
749+
Model(
750+
model_name="sherpa-onnx-omnilingual-asr-1600-languages-300M-ctc-int8-2025-11-12",
751+
idx=44,
752+
lang="1600",
753+
lang2="1600_languages",
754+
short_name="omnilingual_asr_300M_ctc_int8",
755+
cmd="""
756+
pushd $model_name
757+
758+
rm -rfv test_wavs
759+
760+
ls -lh
761+
746762
popd
747763
""",
748764
),

sherpa-onnx/java-api/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ java_files += OfflineMoonshineModelConfig.java
3737
java_files += OfflineNemoEncDecCtcModelConfig.java
3838
java_files += OfflineZipformerCtcModelConfig.java
3939
java_files += OfflineWenetCtcModelConfig.java
40+
java_files += OfflineOmnilingualAsrCtcModelConfig.java
4041
java_files += OfflineCanaryModelConfig.java
4142
java_files += OfflineSenseVoiceModelConfig.java
4243
java_files += OfflineDolphinModelConfig.java

sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineModelConfig.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class OfflineModelConfig {
1313
private final OfflineDolphinModelConfig dolphin;
1414
private final OfflineZipformerCtcModelConfig zipformerCtc;
1515
private final OfflineWenetCtcModelConfig wenetCtc;
16+
private final OfflineOmnilingualAsrCtcModelConfig omnilingual;
1617
private final OfflineCanaryModelConfig canary;
1718
private final String teleSpeech;
1819
private final String tokens;
@@ -34,6 +35,7 @@ private OfflineModelConfig(Builder builder) {
3435
this.zipformerCtc = builder.zipformerCtc;
3536
this.canary = builder.canary;
3637
this.wenetCtc = builder.wenetCtc;
38+
this.omnilingual = builder.omnilingual;
3739
this.senseVoice = builder.senseVoice;
3840
this.dolphin = builder.dolphin;
3941
this.teleSpeech = builder.teleSpeech;
@@ -86,6 +88,10 @@ public OfflineWenetCtcModelConfig getWenetCtc() {
8688
return wenetCtc;
8789
}
8890

91+
public OfflineOmnilingualAsrCtcModelConfig getOmnilingual() {
92+
return omnilingual;
93+
}
94+
8995
public OfflineCanaryModelConfig getCanary() {
9096
return canary;
9197
}
@@ -133,6 +139,7 @@ public static class Builder {
133139
private OfflineDolphinModelConfig dolphin = OfflineDolphinModelConfig.builder().build();
134140
private OfflineZipformerCtcModelConfig zipformerCtc = OfflineZipformerCtcModelConfig.builder().build();
135141
private OfflineWenetCtcModelConfig wenetCtc = OfflineWenetCtcModelConfig.builder().build();
142+
private OfflineOmnilingualAsrCtcModelConfig omnilingual = OfflineOmnilingualAsrCtcModelConfig.builder().build();
136143
private OfflineCanaryModelConfig canary = OfflineCanaryModelConfig.builder().build();
137144
private String teleSpeech = "";
138145
private String tokens = "";
@@ -177,6 +184,11 @@ public Builder setWenetCtc(OfflineWenetCtcModelConfig wenetCtc) {
177184
return this;
178185
}
179186

187+
public Builder setOmnilingual(OfflineOmnilingualAsrCtcModelConfig omnilingual) {
188+
this.omnilingual = omnilingual;
189+
return this;
190+
}
191+
180192
public Builder setCanary(OfflineCanaryModelConfig canary) {
181193
this.canary = canary;
182194
return this;
@@ -242,4 +254,4 @@ public Builder setBpeVocab(String bpeVocab) {
242254
return this;
243255
}
244256
}
245-
}
257+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.k2fsa.sherpa.onnx;
2+
3+
public class OfflineOmnilingualAsrCtcModelConfig {
4+
private final String model;
5+
6+
private OfflineOmnilingualAsrCtcModelConfig(Builder builder) {
7+
this.model = builder.model;
8+
}
9+
10+
public static Builder builder() {
11+
return new Builder();
12+
}
13+
14+
public String getModel() {
15+
return model;
16+
}
17+
18+
public static class Builder {
19+
private String model = "";
20+
21+
public OfflineOmnilingualAsrCtcModelConfig build() {
22+
return new OfflineOmnilingualAsrCtcModelConfig(this);
23+
}
24+
25+
public Builder setModel(String model) {
26+
this.model = model;
27+
return this;
28+
}
29+
}
30+
}

sherpa-onnx/jni/offline-recognizer.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,18 @@ static OfflineRecognizerConfig GetOfflineConfig(JNIEnv *env, jobject config,
193193
SHERPA_ONNX_JNI_READ_STRING(ans.model_config.wenet_ctc.model, model,
194194
wenet_ctc_config_cls, wenet_ctc_config);
195195

196+
// omnilingual asr ctc
197+
fid = env->GetFieldID(
198+
model_config_cls, "omnilingual",
199+
"Lcom/k2fsa/sherpa/onnx/OfflineOmnilingualAsrCtcModelConfig;");
200+
jobject omnilingual_ctc_config = env->GetObjectField(model_config, fid);
201+
jclass omnilingual_ctc_config_cls =
202+
env->GetObjectClass(omnilingual_ctc_config);
203+
204+
SHERPA_ONNX_JNI_READ_STRING(ans.model_config.omnilingual.model, model,
205+
omnilingual_ctc_config_cls,
206+
omnilingual_ctc_config);
207+
196208
// canary
197209
fid = env->GetFieldID(model_config_cls, "canary",
198210
"Lcom/k2fsa/sherpa/onnx/OfflineCanaryModelConfig;");

0 commit comments

Comments
 (0)