Tong Li
Committed by GitHub

push to maven center (#2463)

正在显示 90 个修改的文件 包含 1645 行增加766 行删除
  1 +[win.env]
  2 +set JAVA_HOME=D:\java\jdk1.8.0_121
  3 +
  4 +[win.build]
  5 +mvn clean install -DskipTests -Dgpg.skip=true
  6 +
  7 +[linux.env]
  8 +export JAVA_HOME=/usr/java/jdk1.8.0_121
  9 +
  10 +[linux.build]
  11 +mvn clean install -DskipTests -Dgpg.skip=true
  12 +
  13 +[mac.env]
  14 +export JAVA_HOME=~/java/jdk1.8.0_121
  15 +
  16 +[mac.build]
  17 +mvn clean install -DskipTests -Dgpg.skip=true
1 -.idea  
2 -java-api.iml  
3 -out  
4 -META-INF  
5 -build  
6 -*.jar 1 +### Eclipse template
  2 +*.pydevproject
  3 +.metadata
  4 +.gradle*
  5 +classes/
  6 +bin/
  7 +tmp/
  8 +*.tmp
  9 +*.bak
  10 +*.swp
  11 +*~.nib
  12 +local.properties
  13 +.settings/
  14 +.loadpath
  15 +rebel.xml
  16 +
  17 +# Eclipse Core
  18 +.project
  19 +
  20 +generatedsources
  21 +
  22 +# External tool builders
  23 +.externalToolBuilders/
  24 +
  25 +# Locally stored "Eclipse launch configurations"
  26 +*.launch
  27 +
  28 +# CDT-specific
  29 +.cproject
  30 +
  31 +# JDT-specific (Eclipse Java Development Tools)
  32 +.classpath
  33 +
  34 +# PDT-specific
  35 +.buildpath
  36 +
  37 +# sbteclipse plugin
  38 +.target
  39 +
  40 +# TeXlipse plugin
  41 +.texlipse
  42 +
  43 +
  44 +
  45 +### JetBrains template
  46 +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
  47 +
  48 +*.iml
  49 +.flattened-pom.xml
  50 +## Directory-based project format:
  51 +.idea/
  52 +# if you remove the above rule, at least ignore the following:
  53 +
  54 +# User-specific stuff:
  55 +# .idea/workspace.xml
  56 +# .idea/tasks.xml
  57 +# .idea/dictionaries
  58 +
  59 +# Sensitive or high-churn files:
  60 +# .idea/dataSources.ids
  61 +# .idea/dataSources.xml
  62 +# .idea/sqlDataSources.xml
  63 +# .idea/dynamic.xml
  64 +# .idea/uiDesigner.xml
  65 +
  66 +# Gradle:
  67 +# .idea/gradle.xml
  68 +# .idea/libraries
  69 +
  70 +# Mongo Explorer plugin:
  71 +# .idea/mongoSettings.xml
  72 +
  73 +## File-based project format:
  74 +*.ipr
  75 +*.iws
  76 +
  77 +## Plugin-specific files:
  78 +
  79 +# IntelliJ
  80 +/out/
  81 +
  82 +# mpeltonen/sbt-idea plugin
  83 +.idea_modules/
  84 +
  85 +# JIRA plugin
  86 +atlassian-ide-plugin.xml
  87 +
  88 +# Crashlytics plugin (for Android Studio and IntelliJ)
  89 +com_crashlytics_export_strings.xml
  90 +crashlytics.properties
  91 +crashlytics-build.properties
  92 +
  93 +build/
  94 +
  95 +# Ignore Gradle GUI config
  96 +gradle-app.setting
  97 +
  98 +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
  99 +!gradle-wrapper.jar
  100 +
  101 +db
  102 +
  103 +### Java template
  104 +*.class
  105 +
  106 +# Mobile Tools for Java (J2ME)
  107 +.mtj.tmp/
  108 +
  109 +# Package Files #
  110 +#*.jar
  111 +
  112 +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
  113 +hs_err_pid*
  114 +
  115 +
  116 +### Leiningen template
  117 +classes/
  118 +target/
  119 +logs/
  120 +checkouts/
  121 +.lein-deps-sum
  122 +.lein-repl-history
  123 +.lein-plugins/
  124 +.lein-failures
  125 +.nrepl-port
  126 +
  127 +querydsl/
  128 +
  129 +.DS_Store
  130 +
  131 +*.exe
  132 +*.out
  133 +
  134 +*.log
  135 +node_modules/
  136 +dist/
  137 +dist.zip
  138 +package-lock.json
  139 +*.lock
  140 +local.properties
  141 +.cxx
  142 +.externalNativeBuild
  143 +/captures
  144 +/build
  145 +__pycache__/
  146 +*.pyc
  147 +
  148 +
  149 +cmake-build-debug/
  150 +cmake-build-debug-mingw/
  151 +venv/
  152 +.vs/
  153 +Debug/
  154 +vcpkg_installed/
  155 +.env
  156 +.next/
  157 +app.zip
  158 +secrets.txt
  159 +src.zip
@@ -101,7 +101,7 @@ java_files += OfflineSpeechDenoiser.java @@ -101,7 +101,7 @@ java_files += OfflineSpeechDenoiser.java
101 101
102 class_files := $(java_files:%.java=%.class) 102 class_files := $(java_files:%.java=%.class)
103 103
104 -java_files := $(addprefix src/$(package_dir)/,$(java_files)) 104 +java_files := $(addprefix src/main/java/$(package_dir)/,$(java_files))
105 class_files := $(addprefix $(out_dir)/$(package_dir)/,$(class_files)) 105 class_files := $(addprefix $(out_dir)/$(package_dir)/,$(class_files))
106 106
107 $(info -- java files $(java_files)) 107 $(info -- java files $(java_files))
@@ -119,6 +119,6 @@ $(out_jar): $(class_files) @@ -119,6 +119,6 @@ $(out_jar): $(class_files)
119 clean: 119 clean:
120 $(RM) -rfv $(out_dir) 120 $(RM) -rfv $(out_dir)
121 121
122 -$(class_files): $(out_dir)/$(package_dir)/%.class: src/$(package_dir)/%.java 122 +$(class_files): $(out_dir)/$(package_dir)/%.class: src/main/java/$(package_dir)/%.java
123 mkdir -p build 123 mkdir -p build
124 javac -d $(out_dir) -cp $(out_dir) $< 124 javac -d $(out_dir) -cp $(out_dir) $<
  1 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  2 + <modelVersion>4.0.0</modelVersion>
  3 + <groupId>com.litongjava</groupId>
  4 + <artifactId>sherpa-onnx-java-api</artifactId>
  5 + <version>1.0.1</version>
  6 + <packaging>jar</packaging>
  7 + <name>sherpa-onnx-java-api</name>
  8 + <description>sherpa-onnx-java-api</description>
  9 + <url>https://github.com/k2-fsa/sherpa-onnx/tree/master/sherpa-onnx/java-api</url>
  10 + <properties>
  11 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12 + <java.version>1.8</java.version>
  13 + <maven.compiler.source>${java.version}</maven.compiler.source>
  14 + <maven.compiler.target>${java.version}</maven.compiler.target>
  15 + </properties>
  16 +
  17 + <licenses>
  18 + <license>
  19 + <name>The Apache Software License, Version 2.0</name>
  20 + <url>http://apache.org/licenses/LICENSE-2.0.txt</url>
  21 + </license>
  22 + </licenses>
  23 +
  24 + <developers>
  25 + <developer>
  26 + <id>litongjava</id>
  27 + <name>Tong Li</name>
  28 + <email>litongjava001@gmail.com</email>
  29 + <url>https://github.com/litongjava</url>
  30 + </developer>
  31 + </developers>
  32 +
  33 + <scm>
  34 + <connection>scm:git:git@github.com:k2-fsa/sherpa-onnx.git</connection>
  35 + <developerConnection>scm:git:git@github.com:k2-fsa/sherpa-onnx.git</developerConnection>
  36 + <url>git@github.com:k2-fsa/sherpa-onnx.git</url>
  37 + </scm>
  38 +
  39 + <build>
  40 + <plugins>
  41 + <!-- Source -->
  42 + <plugin>
  43 + <groupId>org.apache.maven.plugins</groupId>
  44 + <artifactId>maven-source-plugin</artifactId>
  45 + <version>2.2.1</version>
  46 + <executions>
  47 + <execution>
  48 + <phase>package</phase>
  49 + <goals>
  50 + <goal>jar-no-fork</goal>
  51 + </goals>
  52 + </execution>
  53 + </executions>
  54 + </plugin>
  55 + <!-- Javadoc -->
  56 + <plugin>
  57 + <groupId>org.apache.maven.plugins</groupId>
  58 + <artifactId>maven-javadoc-plugin</artifactId>
  59 + <version>2.9.1</version>
  60 + <configuration>
  61 + <!-- 添加这个压制JavaDoc检查 -->
  62 + <additionalparam>-Xdoclint:none</additionalparam>
  63 + </configuration>
  64 + <executions>
  65 + <execution>
  66 + <phase>package</phase>
  67 + <goals>
  68 + <goal>jar</goal>
  69 + </goals>
  70 + </execution>
  71 + </executions>
  72 + </plugin>
  73 + <!-- GPG mvn clean deploy -Dgpg.passphrase=YourPassphase -->
  74 + <plugin>
  75 + <groupId>org.apache.maven.plugins</groupId>
  76 + <artifactId>maven-gpg-plugin</artifactId>
  77 + <version>1.5</version>
  78 + <executions>
  79 + <execution>
  80 + <id>sign-artifacts</id>
  81 + <phase>verify</phase>
  82 + <goals>
  83 + <goal>sign</goal>
  84 + </goals>
  85 + </execution>
  86 + </executions>
  87 + </plugin>
  88 + <plugin>
  89 + <groupId>org.sonatype.central</groupId>
  90 + <artifactId>central-publishing-maven-plugin</artifactId>
  91 + <version>0.7.0</version>
  92 + <extensions>true</extensions>
  93 + <configuration>
  94 + <publishingServerId>central</publishingServerId>
  95 + </configuration>
  96 + </plugin>
  97 + </plugins>
  98 + </build>
  99 +</project>
  1 +# User Guide
  2 +
  3 +*Applicable to Windows / macOS / Linux (using Windows as an example for dynamic library loading)*
  4 +
  5 +## 1. Prerequisites
  6 +
  7 +* Java 1.8+ environment
  8 +* Download and prepare the following:
  9 +
  10 + * Sherpa-ONNX Java API (Maven dependency)
  11 + * Kokoro TTS model files (including `model.onnx`, etc.)
  12 +
  13 +---
  14 +
  15 +## 2. Add Maven Dependency
  16 +
  17 +In your `pom.xml`, add:
  18 +
  19 +```xml
  20 +<dependency>
  21 + <groupId>com.litongjava</groupId>
  22 + <artifactId>sherpa-onnx-java-api</artifactId>
  23 + <version>1.0.1</version>
  24 +</dependency>
  25 +```
  26 +
  27 +---
  28 +
  29 +## 3. Obtain and Configure Native Dynamic Libraries (JNI)
  30 +
  31 +### 3.1 Install ONNX Runtime
  32 +
  33 +#### Windows 10
  34 +
  35 +Starting from Windows 10 v1809 and all versions of Windows 11, the system comes with built-in ONNX Runtime as part of Windows ML (WinRT API), exposed through Windows.AI.MachineLearning.dll. You can directly use WinML to load and run ONNX models without additional downloads or installations.
  36 +[run-onnx-models](https://learn.microsoft.com/en-us/windows/ai/new-windows-ml/run-onnx-models)
  37 +
  38 +#### Linux
  39 +
  40 +Sherpa-ONNX does **not** bundle ONNX Runtime. To install it manually:
  41 +
  42 +1. Download the Linux x64 binary from Microsoft’s GitHub Releases:
  43 +
  44 + ```bash
  45 + wget https://github.com/microsoft/onnxruntime/releases/download/v1.17.1/onnxruntime-linux-x64-1.17.1.tgz
  46 + tar -xzf onnxruntime-linux-x64-1.17.1.tgz
  47 + ```
  48 +
  49 +2. Copy and symlink the library into a system directory:
  50 +
  51 + ```bash
  52 + sudo cp onnxruntime-linux-x64-1.17.1/lib/libonnxruntime.so* /usr/local/lib/
  53 + sudo ln -sf /usr/local/lib/libonnxruntime.so.1.17.1 /usr/local/lib/libonnxruntime.so
  54 + ```
  55 +
  56 +3. Update the shared-library cache and verify:
  57 +
  58 + ```bash
  59 + sudo ldconfig
  60 + ldconfig -p | grep onnxruntime
  61 + ```
  62 +
  63 +#### macOS
  64 +
  65 +Sherpa-ONNX also requires you to install ONNX Runtime on macOS:
  66 +
  67 +1. Download the macOS ARM64 binary:
  68 +
  69 + ```bash
  70 + wget https://github.com/microsoft/onnxruntime/releases/download/v1.17.1/onnxruntime-osx-arm64-1.17.1.tgz
  71 + tar -xzf onnxruntime-osx-arm64-1.17.1.tgz
  72 + ```
  73 +
  74 +2. Copy the dylib into `/usr/local/lib`:
  75 +
  76 + ```bash
  77 + sudo cp onnxruntime-osx-arm64-1.17.1/lib/libonnxruntime.1.17.1.dylib /usr/local/lib/
  78 + ```
  79 +
  80 +3. Add `/usr/local/lib` to `dyld`’s search path:
  81 +
  82 + ```bash
  83 + export DYLD_LIBRARY_PATH=/usr/local/lib:$DYLD_LIBRARY_PATH
  84 + ```
  85 +
  86 +4. Verify with `otool`:
  87 +
  88 + ```bash
  89 + otool -L /Users/ping/lib/darwin_arm64/libsherpa-onnx-jni.dylib
  90 + ```
  91 +
  92 +---
  93 +
  94 +### 3.2 Common Errors & Troubleshooting
  95 +
  96 +**Error Example:**
  97 +
  98 +```text
  99 +Exception in thread "main" java.lang.UnsatisfiedLinkError: no sherpa-onnx-jni in java.library.path: ...
  100 +```
  101 +
  102 +This means the JVM couldn’t locate the native library in `java.library.path`.
  103 +
  104 +**Troubleshooting steps:**
  105 +
  106 +1. Ensure you downloaded the build matching your OS and architecture (e.g. win-x64 vs. arm64).
  107 +
  108 +2. Test with an absolute path:
  109 +
  110 + ```bash
  111 + java -Djava.library.path=C:\full\path\to\jni -jar your-app.jar
  112 + ```
  113 +
  114 +3. Print or inspect `java.library.path` at runtime (e.g. `System.out.println(System.getProperty("java.library.path"));`).
  115 +
  116 +4. **Do not** hack the internal `sys_paths` via reflection (it may throw `NoSuchFieldException`). Use `-Djava.library.path` instead.
  117 +
  118 +---
  119 +
  120 +## 4. Download & Prepare the Kokoro Model
  121 +
  122 +Fetch the model package from the official release (example: Kokoro v0.19 English):
  123 +
  124 +```
  125 +https://k2-fsa.github.io/sherpa/onnx/tts/pretrained_models/kokoro.html
  126 +```
  127 +
  128 +```bash
  129 +# Download (manually or via script)
  130 +wget https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/kokoro-en-v0_19.tar.bz2
  131 +
  132 +# Extract
  133 +tar -xjf kokoro-en-v0_19.tar.bz2
  134 +
  135 +# Inspect
  136 +ls -lh kokoro-en-v0_19/
  137 +```
  138 +
  139 +You should see:
  140 +
  141 +```
  142 +LICENSE
  143 +README.md
  144 +espeak-ng-data/ # speech data directory
  145 +model.onnx # TTS model
  146 +tokens.txt # token mapping
  147 +voices.bin # voice embeddings
  148 +```
  149 +
  150 +Make sure your Java code points to these files (using either relative or absolute paths).
  151 +
  152 +---
  153 +
  154 +## 5. Test Code (Java Example)
  155 +
  156 +```java
  157 +package com.litongjava.linux.tts;
  158 +
  159 +import com.k2fsa.sherpa.onnx.GeneratedAudio;
  160 +import com.k2fsa.sherpa.onnx.OfflineTts;
  161 +import com.k2fsa.sherpa.onnx.OfflineTtsConfig;
  162 +import com.k2fsa.sherpa.onnx.OfflineTtsKokoroModelConfig;
  163 +import com.k2fsa.sherpa.onnx.OfflineTtsModelConfig;
  164 +
  165 +public class NonStreamingTtsKokoroEn {
  166 + public static void main(String[] args) {
  167 + String model = "./kokoro-en-v0_19/model.onnx";
  168 + String voices = "./kokoro-en-v0_19/voices.bin";
  169 + String tokens = "./kokoro-en-v0_19/tokens.txt";
  170 + String dataDir = "./kokoro-en-v0_19/espeak-ng-data";
  171 + String text = "Today as always, men fall into two groups: slaves and free men. Whoever does not have"
  172 + + " two-thirds of his day for himself, is a slave, whatever he may be: a statesman, a"
  173 + + " businessman, an official, or a scholar.";
  174 +
  175 + OfflineTtsKokoroModelConfig kokoroConfig = OfflineTtsKokoroModelConfig.builder()
  176 + .setModel(model)
  177 + .setVoices(voices)
  178 + .setTokens(tokens)
  179 + .setDataDir(dataDir)
  180 + .build();
  181 +
  182 + OfflineTtsModelConfig modelConfig = OfflineTtsModelConfig.builder()
  183 + .setKokoro(kokoroConfig)
  184 + .setNumThreads(2)
  185 + .setDebug(true)
  186 + .build();
  187 +
  188 + OfflineTtsConfig config = OfflineTtsConfig.builder()
  189 + .setModel(modelConfig)
  190 + .build();
  191 +
  192 + OfflineTts tts = new OfflineTts(config);
  193 +
  194 + int sid = 0;
  195 + float speed = 1.0f;
  196 + long start = System.currentTimeMillis();
  197 + GeneratedAudio audio = tts.generate(text, sid, speed);
  198 + long stop = System.currentTimeMillis();
  199 +
  200 + float elapsed = (stop - start) / 1000.0f;
  201 + float duration = audio.getSamples().length / (float) audio.getSampleRate();
  202 + float rtf = elapsed / duration;
  203 +
  204 + String outFile = "tts-kokoro-en.wav";
  205 + audio.save(outFile);
  206 +
  207 + System.out.printf("-- elapsed : %.3f seconds%n", elapsed);
  208 + System.out.printf("-- audio duration : %.3f seconds%n", duration);
  209 + System.out.printf("-- real-time factor : %.3f%n", rtf);
  210 + System.out.printf("-- text : %s%n", text);
  211 + System.out.printf("-- Saved to : %s%n", outFile);
  212 +
  213 + tts.release();
  214 + }
  215 +}
  216 +```
  217 +
  218 +### Output Explanation
  219 +
  220 +After successful execution, you should see something like:
  221 +
  222 +```
  223 +-- elapsed : 6.739 seconds
  224 +-- audio duration : 6.739 seconds
  225 +-- real-time factor : 0.563
  226 +-- text : ...
  227 +-- Saved to : tts-kokoro-en.wav
  228 +```
  229 +
  230 +A file named `tts-kokoro-en.wav` will appear in the current directory—play it with any audio player to verify.
  1 +# 使用指南
  2 +
  3 +*适用于 Windows / macOS / Linux(以 Windows 为例说明动态库加载)*
  4 +
  5 +## 1. 前提条件
  6 +
  7 +* Java 1.8+ 环境
  8 +* 下载并准备好以下内容:
  9 + * Sherpa-ONNX Java API(Maven 依赖)
  10 + * Kokoro TTS 模型文件(包含 `model.onnx` 等)
  11 +
  12 +---
  13 +
  14 +## 2. 添加 Maven 依赖
  15 +
  16 +在你的 `pom.xml` 中添加如下依赖:
  17 +
  18 +```xml
  19 +<dependency>
  20 + <groupId>com.litongjava</groupId>
  21 + <artifactId>sherpa-onnx-java-api</artifactId>
  22 + <version>1.0.1</version>
  23 +</dependency>
  24 +```
  25 +
  26 +---
  27 +
  28 +## 3. 获取并配置本地动态链接库(JNI)
  29 +
  30 +### 3.1 安装 ONNX Runtime
  31 +
  32 +#### 1. Windows 11
  33 +
  34 +Starting from Windows 10 v1809 and all versions of Windows 11, the system comes with built-in ONNX Runtime as part of Windows ML (WinRT API), exposed through Windows.AI.MachineLearning.dll. You can directly use WinML to load and run ONNX models without additional downloads or installations.
  35 +(run-onnx-models)[https://learn.microsoft.com/en-us/windows/ai/new-windows-ml/run-onnx-models]
  36 +
  37 +#### 2. Linux
  38 +
  39 +Sherpa-ONNX 并不包含 ONNX Runtime,需要手动下载并配置:
  40 +
  41 +1. 从微软官方 GitHub Releases 下载 Linux 64 位二进制包:
  42 +
  43 + ```bash
  44 + wget https://github.com/microsoft/onnxruntime/releases/download/v1.17.1/onnxruntime-linux-x64-1.17.1.tgz
  45 + tar -xzf onnxruntime-linux-x64-1.17.1.tgz
  46 + ```
  47 +2. 将解压后的 `libonnxruntime.so` 文件复制到系统库目录,并创建软链接:
  48 +
  49 + ```bash
  50 + sudo cp onnxruntime-linux-x64-1.17.1/lib/libonnxruntime.so* /usr/local/lib/
  51 + sudo ln -sf /usr/local/lib/libonnxruntime.so.1.17.1 /usr/local/lib/libonnxruntime.so
  52 + ```
  53 +3. 更新共享库缓存并验证安装:
  54 +
  55 + ```bash
  56 + sudo ldconfig
  57 + ldconfig -p | grep onnxruntime
  58 + ```
  59 +
  60 +#### 3. macOS
  61 +
  62 +Sherpa-ONNX 同样不包含 ONNX Runtime,需要从官方获取并配置:
  63 +
  64 +1. 下载 macOS ARM64 版本二进制包:
  65 +
  66 + ```bash
  67 + wget https://github.com/microsoft/onnxruntime/releases/download/v1.17.1/onnxruntime-osx-arm64-1.17.1.tgz
  68 + tar -xzf onnxruntime-osx-arm64-1.17.1.tgz
  69 + ```
  70 +2.`libonnxruntime.1.17.1.dylib` 复制到 `/usr/local/lib`
  71 +
  72 + ```bash
  73 + sudo cp onnxruntime-osx-arm64-1.17.1/lib/libonnxruntime.1.17.1.dylib /usr/local/lib/
  74 + ```
  75 +3.`/usr/local/lib` 添加到 `dyld` 的搜索路径:
  76 +
  77 + ```bash
  78 + export DYLD_LIBRARY_PATH=/usr/local/lib:$DYLD_LIBRARY_PATH
  79 + ```
  80 +4. 使用 `otool` 验证:
  81 +
  82 + ```bash
  83 + otool -L /Users/ping/lib/darwin_arm64/libsherpa-onnx-jni.dylib
  84 + ```
  85 +---
  86 +
  87 +
  88 +### 3.2 常见错误与排查
  89 +
  90 +**错误示例:**
  91 +
  92 +```text
  93 +Exception in thread "main" java.lang.UnsatisfiedLinkError: no sherpa-onnx-jni in java.library.path: ...
  94 +```
  95 +
  96 +说明 JVM 没有在 `java.library.path` 中找到本地库。
  97 +
  98 +排查步骤:
  99 +
  100 +1. 确认下载的是与你操作系统与架构匹配的版本(如 win-x64 vs arm64 等)。
  101 +2. 用绝对路径测试:将 `.dll` 放在某个目录并运行:
  102 +
  103 + ```sh
  104 + java -Djava.library.path=C:\full\path\to\jni -jar your-app.jar
  105 + ```
  106 +3. 打印或检查 `java.library.path` 内容(示例代码里可输出 `System.getProperty("java.library.path")`)。
  107 +4. 避免通过反射修改 `sys_paths`(不要尝试 hack `java.library.path` 的内部字段,容易引发 `NoSuchFieldException: sys_paths`,建议直接用 `-Djava.library.path`)。
  108 +
  109 +---
  110 +
  111 +## 4. 下载并准备 Kokoro 模型
  112 +
  113 +从官方 release 获取模型包(以英文 Kokoro v0.19 为例):
  114 +```
  115 +https://k2-fsa.github.io/sherpa/onnx/tts/pretrained_models/kokoro.html
  116 +```
  117 +
  118 +```sh
  119 +# 下载(手工或脚本)
  120 +# 例如从 GitHub releases:
  121 +wget https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/kokoro-en-v0_19.tar.bz2
  122 +
  123 +# 解压
  124 +tar -xjf kokoro-en-v0_19.tar.bz2
  125 +
  126 +# 查看结构
  127 +ls -lh kokoro-en-v0_19/
  128 +```
  129 +
  130 +该目录结构示例(解压后应包含):
  131 +
  132 +```
  133 +LICENSE
  134 +README.md
  135 +espeak-ng-data/ # 语音数据目录
  136 +model.onnx # TTS 模型
  137 +tokens.txt # token 映射
  138 +voices.bin # voice embedding
  139 +```
  140 +
  141 +确保这些路径在你的 Java 程序中指向正确的位置(相对或绝对皆可)。
  142 +
  143 +---
  144 +
  145 +## 5. 测试代码(Java 示例)
  146 +
  147 +```java
  148 +package com.litongjava.linux.tts;
  149 +
  150 +import com.k2fsa.sherpa.onnx.GeneratedAudio;
  151 +import com.k2fsa.sherpa.onnx.OfflineTts;
  152 +import com.k2fsa.sherpa.onnx.OfflineTtsConfig;
  153 +import com.k2fsa.sherpa.onnx.OfflineTtsKokoroModelConfig;
  154 +import com.k2fsa.sherpa.onnx.OfflineTtsModelConfig;
  155 +
  156 +public class NonStreamingTtsKokoroEn {
  157 + public static void main(String[] args) {
  158 + String model = "./kokoro-en-v0_19/model.onnx";
  159 + String voices = "./kokoro-en-v0_19/voices.bin";
  160 + String tokens = "./kokoro-en-v0_19/tokens.txt";
  161 + String dataDir = "./kokoro-en-v0_19/espeak-ng-data";
  162 + String text = "Today as always, men fall into two groups: slaves and free men. Whoever does not have"
  163 + + " two-thirds of his day for himself, is a slave, whatever he may be: a statesman, a"
  164 + + " businessman, an official, or a scholar.";
  165 +
  166 + OfflineTtsKokoroModelConfig kokoroModelConfig = OfflineTtsKokoroModelConfig.builder()
  167 + .setModel(model)
  168 + .setVoices(voices)
  169 + .setTokens(tokens)
  170 + .setDataDir(dataDir)
  171 + .build();
  172 +
  173 + OfflineTtsModelConfig modelConfig = OfflineTtsModelConfig.builder()
  174 + .setKokoro(kokoroModelConfig)
  175 + .setNumThreads(2)
  176 + .setDebug(true)
  177 + .build();
  178 +
  179 + OfflineTtsConfig config = OfflineTtsConfig.builder()
  180 + .setModel(modelConfig)
  181 + .build();
  182 +
  183 + OfflineTts tts = new OfflineTts(config);
  184 +
  185 + int sid = 0;
  186 + float speed = 1.0f;
  187 + long start = System.currentTimeMillis();
  188 + GeneratedAudio audio = tts.generate(text, sid, speed);
  189 + long stop = System.currentTimeMillis();
  190 +
  191 + float timeElapsedSeconds = (stop - start) / 1000.0f;
  192 + float audioDuration = audio.getSamples().length / (float) audio.getSampleRate();
  193 + float real_time_factor = timeElapsedSeconds / audioDuration;
  194 +
  195 + String waveFilename = "tts-kokoro-en.wav";
  196 + audio.save(waveFilename);
  197 + System.out.printf("-- elapsed : %.3f seconds\n", timeElapsedSeconds);
  198 + System.out.printf("-- audio duration: %.3f seconds\n", audioDuration);
  199 + System.out.printf("-- real-time factor (RTF): %.3f\n", real_time_factor);
  200 + System.out.printf("-- text: %s\n", text);
  201 + System.out.printf("-- Saved to %s\n", waveFilename);
  202 +
  203 + tts.release();
  204 + }
  205 +}
  206 +```
  207 +
  208 +### 输出说明
  209 +
  210 +成功执行后会输出类似:
  211 +
  212 +```
  213 +-- elapsed : 6.739 seconds
  214 +-- audio duration: 6.739 seconds
  215 +-- real-time factor (RTF): 0.563
  216 +-- text: ...
  217 +-- Saved to tts-kokoro-en.wav
  218 +```
  219 +
  220 +并在当前目录生成 `tts-kokoro-en.wav`,可以用任意音频播放器播放验证。
  221 +
  222 +---
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class EndpointConfig {  
7 -  
8 - private final EndpointRule rule1;  
9 - private final EndpointRule rule2;  
10 - private final EndpointRule rule3;  
11 -  
12 - private EndpointConfig(Builder builder) {  
13 - this.rule1 = builder.rule1;  
14 - this.rule2 = builder.rule2;  
15 - this.rule3 = builder.rule3;  
16 - }  
17 -  
18 - public static Builder builder() {  
19 - return new Builder();  
20 - }  
21 -  
22 - public EndpointRule getRule1() {  
23 - return rule1;  
24 - }  
25 -  
26 - public EndpointRule getRule2() {  
27 - return rule2;  
28 - }  
29 -  
30 - public EndpointRule getRule3() {  
31 - return rule3;  
32 - }  
33 -  
34 - public static class Builder {  
35 -  
36 - private EndpointRule rule1 = EndpointRule.builder().  
37 - setMustContainNonSilence(false).  
38 - setMinTrailingSilence(2.4f).  
39 - setMinUtteranceLength(0).  
40 - build();  
41 - private EndpointRule rule2 = EndpointRule.builder().  
42 - setMustContainNonSilence(true).  
43 - setMinTrailingSilence(1.4f).  
44 - setMinUtteranceLength(0).  
45 - build();  
46 - private EndpointRule rule3 = EndpointRule.builder().  
47 - setMustContainNonSilence(false).  
48 - setMinTrailingSilence(0.0f).  
49 - setMinUtteranceLength(20.0f).  
50 - build();  
51 -  
52 - public EndpointConfig build() {  
53 - return new EndpointConfig(this);  
54 - }  
55 -  
56 - public Builder setRule1(EndpointRule rule) {  
57 - this.rule1 = rule;  
58 - return this;  
59 - }  
60 -  
61 - public Builder setRule2(EndpointRule rule) {  
62 - this.rule2 = rule;  
63 - return this;  
64 - }  
65 -  
66 - public Builder setRul3(EndpointRule rule) {  
67 - this.rule3 = rule;  
68 - return this;  
69 - }  
70 - }  
71 -} 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class EndpointConfig {
  7 +
  8 + private final EndpointRule rule1;
  9 + private final EndpointRule rule2;
  10 + private final EndpointRule rule3;
  11 +
  12 + private EndpointConfig(Builder builder) {
  13 + this.rule1 = builder.rule1;
  14 + this.rule2 = builder.rule2;
  15 + this.rule3 = builder.rule3;
  16 + }
  17 +
  18 + public static Builder builder() {
  19 + return new Builder();
  20 + }
  21 +
  22 + public EndpointRule getRule1() {
  23 + return rule1;
  24 + }
  25 +
  26 + public EndpointRule getRule2() {
  27 + return rule2;
  28 + }
  29 +
  30 + public EndpointRule getRule3() {
  31 + return rule3;
  32 + }
  33 +
  34 + public static class Builder {
  35 +
  36 + private EndpointRule rule1 = EndpointRule.builder().
  37 + setMustContainNonSilence(false).
  38 + setMinTrailingSilence(2.4f).
  39 + setMinUtteranceLength(0).
  40 + build();
  41 + private EndpointRule rule2 = EndpointRule.builder().
  42 + setMustContainNonSilence(true).
  43 + setMinTrailingSilence(1.4f).
  44 + setMinUtteranceLength(0).
  45 + build();
  46 + private EndpointRule rule3 = EndpointRule.builder().
  47 + setMustContainNonSilence(false).
  48 + setMinTrailingSilence(0.0f).
  49 + setMinUtteranceLength(20.0f).
  50 + build();
  51 +
  52 + public EndpointConfig build() {
  53 + return new EndpointConfig(this);
  54 + }
  55 +
  56 + public Builder setRule1(EndpointRule rule) {
  57 + this.rule1 = rule;
  58 + return this;
  59 + }
  60 +
  61 + public Builder setRule2(EndpointRule rule) {
  62 + this.rule2 = rule;
  63 + return this;
  64 + }
  65 +
  66 + public Builder setRule3(EndpointRule rule) {
  67 + this.rule3 = rule;
  68 + return this;
  69 + }
  70 + }
  71 +}
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class EndpointRule {  
7 -  
8 - private final boolean mustContainNonSilence;  
9 - private final float minTrailingSilence;  
10 - private final float minUtteranceLength;  
11 -  
12 - private EndpointRule(Builder builder) {  
13 - this.mustContainNonSilence = builder.mustContainNonSilence;  
14 - this.minTrailingSilence = builder.minTrailingSilence;  
15 - this.minUtteranceLength = builder.minUtteranceLength;  
16 - }  
17 -  
18 - public static Builder builder() {  
19 - return new Builder();  
20 - }  
21 -  
22 - public float getMinTrailingSilence() {  
23 - return minTrailingSilence;  
24 - }  
25 -  
26 - public float getMinUtteranceLength() {  
27 - return minUtteranceLength;  
28 - }  
29 -  
30 - public boolean getMustContainNonSilence() {  
31 - return mustContainNonSilence;  
32 - }  
33 -  
34 - public static class Builder {  
35 - private boolean mustContainNonSilence = false;  
36 - private float minTrailingSilence = 0;  
37 - private float minUtteranceLength = 0;  
38 -  
39 - public EndpointRule build() {  
40 - return new EndpointRule(this);  
41 - }  
42 -  
43 - public Builder setMustContainNonSilence(boolean mustContainNonSilence) {  
44 - this.mustContainNonSilence = mustContainNonSilence;  
45 - return this;  
46 - }  
47 -  
48 - public Builder setMinTrailingSilence(float minTrailingSilence) {  
49 - this.minTrailingSilence = minTrailingSilence;  
50 - return this;  
51 - }  
52 -  
53 - public Builder setMinUtteranceLength(float minUtteranceLength) {  
54 - this.minUtteranceLength = minUtteranceLength;  
55 - return this;  
56 - }  
57 - } 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class EndpointRule {
  7 +
  8 + private final boolean mustContainNonSilence;
  9 + private final float minTrailingSilence;
  10 + private final float minUtteranceLength;
  11 +
  12 + private EndpointRule(Builder builder) {
  13 + this.mustContainNonSilence = builder.mustContainNonSilence;
  14 + this.minTrailingSilence = builder.minTrailingSilence;
  15 + this.minUtteranceLength = builder.minUtteranceLength;
  16 + }
  17 +
  18 + public static Builder builder() {
  19 + return new Builder();
  20 + }
  21 +
  22 + public float getMinTrailingSilence() {
  23 + return minTrailingSilence;
  24 + }
  25 +
  26 + public float getMinUtteranceLength() {
  27 + return minUtteranceLength;
  28 + }
  29 +
  30 + public boolean getMustContainNonSilence() {
  31 + return mustContainNonSilence;
  32 + }
  33 +
  34 + public static class Builder {
  35 + private boolean mustContainNonSilence = false;
  36 + private float minTrailingSilence = 0;
  37 + private float minUtteranceLength = 0;
  38 +
  39 + public EndpointRule build() {
  40 + return new EndpointRule(this);
  41 + }
  42 +
  43 + public Builder setMustContainNonSilence(boolean mustContainNonSilence) {
  44 + this.mustContainNonSilence = mustContainNonSilence;
  45 + return this;
  46 + }
  47 +
  48 + public Builder setMinTrailingSilence(float minTrailingSilence) {
  49 + this.minTrailingSilence = minTrailingSilence;
  50 + return this;
  51 + }
  52 +
  53 + public Builder setMinUtteranceLength(float minUtteranceLength) {
  54 + this.minUtteranceLength = minUtteranceLength;
  55 + return this;
  56 + }
  57 + }
58 } 58 }
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class FeatureConfig {  
7 - private final int sampleRate;  
8 - private final int featureDim;  
9 - private final float dither;  
10 -  
11 - private FeatureConfig(Builder builder) {  
12 - this.sampleRate = builder.sampleRate;  
13 - this.featureDim = builder.featureDim;  
14 - this.dither = builder.dither;  
15 - }  
16 -  
17 - public static Builder builder() {  
18 - return new Builder();  
19 - }  
20 -  
21 - public int getSampleRate() {  
22 - return sampleRate;  
23 - }  
24 -  
25 - public int getFeatureDim() {  
26 - return featureDim;  
27 - }  
28 -  
29 - public float getDither() {  
30 - return dither;  
31 - }  
32 -  
33 - public static class Builder {  
34 - private int sampleRate = 16000;  
35 - private int featureDim = 80;  
36 - private float dither = 0.0f;  
37 -  
38 - public FeatureConfig build() {  
39 - return new FeatureConfig(this);  
40 - }  
41 -  
42 - public Builder setSampleRate(int sampleRate) {  
43 - this.sampleRate = sampleRate;  
44 - return this;  
45 - }  
46 -  
47 - public Builder setFeatureDim(int featureDim) {  
48 - this.featureDim = featureDim;  
49 - return this;  
50 - }  
51 - public Builder setDither(float dither) {  
52 - this.dither = dither;  
53 - return this;  
54 - }  
55 - }  
56 -} 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class FeatureConfig {
  7 + private final int sampleRate;
  8 + private final int featureDim;
  9 + private final float dither;
  10 +
  11 + private FeatureConfig(Builder builder) {
  12 + this.sampleRate = builder.sampleRate;
  13 + this.featureDim = builder.featureDim;
  14 + this.dither = builder.dither;
  15 + }
  16 +
  17 + public static Builder builder() {
  18 + return new Builder();
  19 + }
  20 +
  21 + public int getSampleRate() {
  22 + return sampleRate;
  23 + }
  24 +
  25 + public int getFeatureDim() {
  26 + return featureDim;
  27 + }
  28 +
  29 + public float getDither() {
  30 + return dither;
  31 + }
  32 +
  33 + public static class Builder {
  34 + private int sampleRate = 16000;
  35 + private int featureDim = 80;
  36 + private float dither = 0.0f;
  37 +
  38 + public FeatureConfig build() {
  39 + return new FeatureConfig(this);
  40 + }
  41 +
  42 + public Builder setSampleRate(int sampleRate) {
  43 + this.sampleRate = sampleRate;
  44 + return this;
  45 + }
  46 +
  47 + public Builder setFeatureDim(int featureDim) {
  48 + this.featureDim = featureDim;
  49 + return this;
  50 + }
  51 + public Builder setDither(float dither) {
  52 + this.dither = dither;
  53 + return this;
  54 + }
  55 + }
  56 +}
1 package com.k2fsa.sherpa.onnx; 1 package com.k2fsa.sherpa.onnx;
2 2
  3 +import com.k2fsa.sherpa.onnx.utils.LibraryUtils;
  4 +
3 public class LibraryLoader { 5 public class LibraryLoader {
4 private static volatile boolean autoLoadEnabled = true; 6 private static volatile boolean autoLoadEnabled = true;
5 private static volatile boolean isLoaded = false; 7 private static volatile boolean isLoaded = false;
6 8
7 static synchronized void loadLibrary() { 9 static synchronized void loadLibrary() {
8 if (!isLoaded) { 10 if (!isLoaded) {
9 - System.loadLibrary("sherpa-onnx-jni"); 11 + LibraryUtils.load();
10 isLoaded = true; 12 isLoaded = true;
11 } 13 }
12 } 14 }
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineLMConfig {  
7 -  
8 - private final String model;  
9 - private final float scale;  
10 -  
11 - private OnlineLMConfig(Builder builder) {  
12 - this.model = builder.model;  
13 - this.scale = builder.scale;  
14 - }  
15 -  
16 - public static Builder builder() {  
17 - return new Builder();  
18 - }  
19 -  
20 - public String getModel() {  
21 - return model;  
22 - }  
23 -  
24 - public float getScale() {  
25 - return scale;  
26 - }  
27 -  
28 - public static class Builder {  
29 - private String model = "";  
30 - private float scale = 1.0f;  
31 -  
32 - public OnlineLMConfig build() {  
33 - return new OnlineLMConfig(this);  
34 - }  
35 -  
36 - public Builder setModel(String model) {  
37 - this.model = model;  
38 - return this;  
39 - }  
40 -  
41 - public Builder setScale(float scale) {  
42 - this.scale = scale;  
43 - return this;  
44 - }  
45 - } 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineLMConfig {
  7 +
  8 + private final String model;
  9 + private final float scale;
  10 +
  11 + private OnlineLMConfig(Builder builder) {
  12 + this.model = builder.model;
  13 + this.scale = builder.scale;
  14 + }
  15 +
  16 + public static Builder builder() {
  17 + return new Builder();
  18 + }
  19 +
  20 + public String getModel() {
  21 + return model;
  22 + }
  23 +
  24 + public float getScale() {
  25 + return scale;
  26 + }
  27 +
  28 + public static class Builder {
  29 + private String model = "";
  30 + private float scale = 1.0f;
  31 +
  32 + public OnlineLMConfig build() {
  33 + return new OnlineLMConfig(this);
  34 + }
  35 +
  36 + public Builder setModel(String model) {
  37 + this.model = model;
  38 + return this;
  39 + }
  40 +
  41 + public Builder setScale(float scale) {
  42 + this.scale = scale;
  43 + return this;
  44 + }
  45 + }
46 } 46 }
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineModelConfig {  
7 - private final OnlineTransducerModelConfig transducer;  
8 - private final OnlineParaformerModelConfig paraformer;  
9 - private final OnlineZipformer2CtcModelConfig zipformer2Ctc;  
10 - private final OnlineNeMoCtcModelConfig neMoCtc;  
11 - private final String tokens;  
12 - private final int numThreads;  
13 - private final boolean debug;  
14 - private final String provider;  
15 - private final String modelType;  
16 - private final String modelingUnit;  
17 - private final String bpeVocab;  
18 -  
19 - private OnlineModelConfig(Builder builder) {  
20 - this.transducer = builder.transducer;  
21 - this.paraformer = builder.paraformer;  
22 - this.zipformer2Ctc = builder.zipformer2Ctc;  
23 - this.neMoCtc = builder.neMoCtc;  
24 - this.tokens = builder.tokens;  
25 - this.numThreads = builder.numThreads;  
26 - this.debug = builder.debug;  
27 - this.provider = builder.provider;  
28 - this.modelType = builder.modelType;  
29 - this.modelingUnit = builder.modelingUnit;  
30 - this.bpeVocab = builder.bpeVocab;  
31 - }  
32 -  
33 - public static Builder builder() {  
34 - return new Builder();  
35 - }  
36 -  
37 - public OnlineParaformerModelConfig getParaformer() {  
38 - return paraformer;  
39 - }  
40 -  
41 - public OnlineTransducerModelConfig getTransducer() {  
42 - return transducer;  
43 - }  
44 -  
45 - public OnlineZipformer2CtcModelConfig getZipformer2Ctc() {  
46 - return zipformer2Ctc;  
47 - }  
48 -  
49 - public OnlineNeMoCtcModelConfig getNeMoCtc() {  
50 - return neMoCtc;  
51 - }  
52 -  
53 - public String getTokens() {  
54 - return tokens;  
55 - }  
56 -  
57 - public int getNumThreads() {  
58 - return numThreads;  
59 - }  
60 -  
61 - public boolean getDebug() {  
62 - return debug;  
63 - }  
64 -  
65 - public String getProvider() {  
66 - return provider;  
67 - }  
68 -  
69 - public String getModelType() {  
70 - return modelType;  
71 - }  
72 -  
73 - public String getModelingUnit() {  
74 - return modelingUnit;  
75 - }  
76 -  
77 - public String getBpeVocab() {  
78 - return bpeVocab;  
79 - }  
80 -  
81 - public static class Builder {  
82 - private OnlineParaformerModelConfig paraformer = OnlineParaformerModelConfig.builder().build();  
83 - private OnlineTransducerModelConfig transducer = OnlineTransducerModelConfig.builder().build();  
84 - private OnlineZipformer2CtcModelConfig zipformer2Ctc = OnlineZipformer2CtcModelConfig.builder().build();  
85 - private OnlineNeMoCtcModelConfig neMoCtc = OnlineNeMoCtcModelConfig.builder().build();  
86 - private String tokens = "";  
87 - private int numThreads = 1;  
88 - private boolean debug = true;  
89 - private String provider = "cpu";  
90 - private String modelType = "";  
91 - private String modelingUnit = "cjkchar";  
92 - private String bpeVocab = "";  
93 -  
94 - public OnlineModelConfig build() {  
95 - return new OnlineModelConfig(this);  
96 - }  
97 -  
98 - public Builder setTransducer(OnlineTransducerModelConfig transducer) {  
99 - this.transducer = transducer;  
100 - return this;  
101 - }  
102 -  
103 - public Builder setParaformer(OnlineParaformerModelConfig paraformer) {  
104 - this.paraformer = paraformer;  
105 - return this;  
106 - }  
107 -  
108 - public Builder setZipformer2Ctc(OnlineZipformer2CtcModelConfig zipformer2Ctc) {  
109 - this.zipformer2Ctc = zipformer2Ctc;  
110 - return this;  
111 - }  
112 -  
113 - public Builder setNeMoCtc(OnlineNeMoCtcModelConfig neMoCtc) {  
114 - this.neMoCtc = neMoCtc;  
115 - return this;  
116 - }  
117 -  
118 - public Builder setTokens(String tokens) {  
119 - this.tokens = tokens;  
120 - return this;  
121 - }  
122 -  
123 - public Builder setNumThreads(int numThreads) {  
124 - this.numThreads = numThreads;  
125 - return this;  
126 - }  
127 -  
128 - public Builder setDebug(boolean debug) {  
129 - this.debug = debug;  
130 - return this;  
131 - }  
132 -  
133 - public Builder setProvider(String provider) {  
134 - this.provider = provider;  
135 - return this;  
136 - }  
137 -  
138 - public Builder setModelType(String modelType) {  
139 - this.modelType = modelType;  
140 - return this;  
141 - }  
142 -  
143 - public Builder setModelingUnit(String modelingUnit) {  
144 - this.modelingUnit = modelingUnit;  
145 - return this;  
146 - }  
147 -  
148 - public Builder setBpeVocab(String bpeVocab) {  
149 - this.bpeVocab = bpeVocab;  
150 - return this;  
151 - }  
152 - }  
153 -} 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineModelConfig {
  7 + private final OnlineTransducerModelConfig transducer;
  8 + private final OnlineParaformerModelConfig paraformer;
  9 + private final OnlineZipformer2CtcModelConfig zipformer2Ctc;
  10 + private final OnlineNeMoCtcModelConfig neMoCtc;
  11 + private final String tokens;
  12 + private final int numThreads;
  13 + private final boolean debug;
  14 + private final String provider;
  15 + private final String modelType;
  16 + private final String modelingUnit;
  17 + private final String bpeVocab;
  18 +
  19 + private OnlineModelConfig(Builder builder) {
  20 + this.transducer = builder.transducer;
  21 + this.paraformer = builder.paraformer;
  22 + this.zipformer2Ctc = builder.zipformer2Ctc;
  23 + this.neMoCtc = builder.neMoCtc;
  24 + this.tokens = builder.tokens;
  25 + this.numThreads = builder.numThreads;
  26 + this.debug = builder.debug;
  27 + this.provider = builder.provider;
  28 + this.modelType = builder.modelType;
  29 + this.modelingUnit = builder.modelingUnit;
  30 + this.bpeVocab = builder.bpeVocab;
  31 + }
  32 +
  33 + public static Builder builder() {
  34 + return new Builder();
  35 + }
  36 +
  37 + public OnlineParaformerModelConfig getParaformer() {
  38 + return paraformer;
  39 + }
  40 +
  41 + public OnlineTransducerModelConfig getTransducer() {
  42 + return transducer;
  43 + }
  44 +
  45 + public OnlineZipformer2CtcModelConfig getZipformer2Ctc() {
  46 + return zipformer2Ctc;
  47 + }
  48 +
  49 + public OnlineNeMoCtcModelConfig getNeMoCtc() {
  50 + return neMoCtc;
  51 + }
  52 +
  53 + public String getTokens() {
  54 + return tokens;
  55 + }
  56 +
  57 + public int getNumThreads() {
  58 + return numThreads;
  59 + }
  60 +
  61 + public boolean getDebug() {
  62 + return debug;
  63 + }
  64 +
  65 + public String getProvider() {
  66 + return provider;
  67 + }
  68 +
  69 + public String getModelType() {
  70 + return modelType;
  71 + }
  72 +
  73 + public String getModelingUnit() {
  74 + return modelingUnit;
  75 + }
  76 +
  77 + public String getBpeVocab() {
  78 + return bpeVocab;
  79 + }
  80 +
  81 + public static class Builder {
  82 + private OnlineParaformerModelConfig paraformer = OnlineParaformerModelConfig.builder().build();
  83 + private OnlineTransducerModelConfig transducer = OnlineTransducerModelConfig.builder().build();
  84 + private OnlineZipformer2CtcModelConfig zipformer2Ctc = OnlineZipformer2CtcModelConfig.builder().build();
  85 + private OnlineNeMoCtcModelConfig neMoCtc = OnlineNeMoCtcModelConfig.builder().build();
  86 + private String tokens = "";
  87 + private int numThreads = 1;
  88 + private boolean debug = true;
  89 + private String provider = "cpu";
  90 + private String modelType = "";
  91 + private String modelingUnit = "cjkchar";
  92 + private String bpeVocab = "";
  93 +
  94 + public OnlineModelConfig build() {
  95 + return new OnlineModelConfig(this);
  96 + }
  97 +
  98 + public Builder setTransducer(OnlineTransducerModelConfig transducer) {
  99 + this.transducer = transducer;
  100 + return this;
  101 + }
  102 +
  103 + public Builder setParaformer(OnlineParaformerModelConfig paraformer) {
  104 + this.paraformer = paraformer;
  105 + return this;
  106 + }
  107 +
  108 + public Builder setZipformer2Ctc(OnlineZipformer2CtcModelConfig zipformer2Ctc) {
  109 + this.zipformer2Ctc = zipformer2Ctc;
  110 + return this;
  111 + }
  112 +
  113 + public Builder setNeMoCtc(OnlineNeMoCtcModelConfig neMoCtc) {
  114 + this.neMoCtc = neMoCtc;
  115 + return this;
  116 + }
  117 +
  118 + public Builder setTokens(String tokens) {
  119 + this.tokens = tokens;
  120 + return this;
  121 + }
  122 +
  123 + public Builder setNumThreads(int numThreads) {
  124 + this.numThreads = numThreads;
  125 + return this;
  126 + }
  127 +
  128 + public Builder setDebug(boolean debug) {
  129 + this.debug = debug;
  130 + return this;
  131 + }
  132 +
  133 + public Builder setProvider(String provider) {
  134 + this.provider = provider;
  135 + return this;
  136 + }
  137 +
  138 + public Builder setModelType(String modelType) {
  139 + this.modelType = modelType;
  140 + return this;
  141 + }
  142 +
  143 + public Builder setModelingUnit(String modelingUnit) {
  144 + this.modelingUnit = modelingUnit;
  145 + return this;
  146 + }
  147 +
  148 + public Builder setBpeVocab(String bpeVocab) {
  149 + this.bpeVocab = bpeVocab;
  150 + return this;
  151 + }
  152 + }
  153 +}
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineParaformerModelConfig {  
7 - private final String encoder;  
8 - private final String decoder;  
9 -  
10 - private OnlineParaformerModelConfig(Builder builder) {  
11 - this.encoder = builder.encoder;  
12 - this.decoder = builder.decoder;  
13 - }  
14 -  
15 - public static Builder builder() {  
16 - return new Builder();  
17 - }  
18 -  
19 - public String getEncoder() {  
20 - return encoder;  
21 - }  
22 -  
23 - public String getDecoder() {  
24 - return decoder;  
25 - }  
26 -  
27 - public static class Builder {  
28 - private String encoder = "";  
29 - private String decoder = "";  
30 -  
31 - public OnlineParaformerModelConfig build() {  
32 - return new OnlineParaformerModelConfig(this);  
33 - }  
34 -  
35 - public Builder setEncoder(String encoder) {  
36 - this.encoder = encoder;  
37 - return this;  
38 - }  
39 -  
40 - public Builder setDecoder(String decoder) {  
41 - this.decoder = decoder;  
42 - return this;  
43 - }  
44 - }  
45 -} 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineParaformerModelConfig {
  7 + private final String encoder;
  8 + private final String decoder;
  9 +
  10 + private OnlineParaformerModelConfig(Builder builder) {
  11 + this.encoder = builder.encoder;
  12 + this.decoder = builder.decoder;
  13 + }
  14 +
  15 + public static Builder builder() {
  16 + return new Builder();
  17 + }
  18 +
  19 + public String getEncoder() {
  20 + return encoder;
  21 + }
  22 +
  23 + public String getDecoder() {
  24 + return decoder;
  25 + }
  26 +
  27 + public static class Builder {
  28 + private String encoder = "";
  29 + private String decoder = "";
  30 +
  31 + public OnlineParaformerModelConfig build() {
  32 + return new OnlineParaformerModelConfig(this);
  33 + }
  34 +
  35 + public Builder setEncoder(String encoder) {
  36 + this.encoder = encoder;
  37 + return this;
  38 + }
  39 +
  40 + public Builder setDecoder(String decoder) {
  41 + this.decoder = decoder;
  42 + return this;
  43 + }
  44 + }
  45 +}
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineRecognizer {  
7 - private long ptr = 0;  
8 -  
9 - public OnlineRecognizer(OnlineRecognizerConfig config) {  
10 - LibraryLoader.maybeLoad();  
11 - ptr = newFromFile(config);  
12 - }  
13 -  
14 - public void decode(OnlineStream s) {  
15 - decode(ptr, s.getPtr());  
16 - }  
17 -  
18 - public void decode(OnlineStream[] ss) {  
19 - long[] streamPtrs = new long[ss.length];  
20 - for (int i = 0; i < ss.length; ++i) {  
21 - streamPtrs[i] = ss[i].getPtr();  
22 - }  
23 - decodeStreams(ptr, streamPtrs);  
24 - }  
25 -  
26 - public boolean isReady(OnlineStream s) {  
27 - return isReady(ptr, s.getPtr());  
28 - }  
29 -  
30 - public boolean isEndpoint(OnlineStream s) {  
31 - return isEndpoint(ptr, s.getPtr());  
32 - }  
33 -  
34 - public void reset(OnlineStream s) {  
35 - reset(ptr, s.getPtr());  
36 - }  
37 -  
38 - public OnlineStream createStream() {  
39 - long p = createStream(ptr, "");  
40 - return new OnlineStream(p);  
41 - }  
42 -  
43 - @Override  
44 - protected void finalize() throws Throwable {  
45 - release();  
46 - }  
47 -  
48 - // You'd better call it manually if it is not used anymore  
49 - public void release() {  
50 - if (this.ptr == 0) {  
51 - return;  
52 - }  
53 - delete(this.ptr);  
54 - this.ptr = 0;  
55 - }  
56 -  
57 - public OnlineRecognizerResult getResult(OnlineStream s) {  
58 - Object[] arr = getResult(ptr, s.getPtr());  
59 - String text = (String) arr[0];  
60 - String[] tokens = (String[]) arr[1];  
61 - float[] timestamps = (float[]) arr[2];  
62 - return new OnlineRecognizerResult(text, tokens, timestamps);  
63 - }  
64 -  
65 -  
66 - private native void delete(long ptr);  
67 -  
68 - private native long newFromFile(OnlineRecognizerConfig config);  
69 -  
70 - private native long createStream(long ptr, String hotwords);  
71 -  
72 - private native void reset(long ptr, long streamPtr);  
73 -  
74 - private native void decode(long ptr, long streamPtr);  
75 -  
76 - private native void decodeStreams(long ptr, long[] streamPtrs);  
77 -  
78 - private native boolean isEndpoint(long ptr, long streamPtr);  
79 -  
80 - private native boolean isReady(long ptr, long streamPtr);  
81 -  
82 - private native Object[] getResult(long ptr, long streamPtr); 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineRecognizer {
  7 + private long ptr = 0;
  8 +
  9 + public OnlineRecognizer(OnlineRecognizerConfig config) {
  10 + LibraryLoader.maybeLoad();
  11 + ptr = newFromFile(config);
  12 + }
  13 +
  14 + public void decode(OnlineStream s) {
  15 + decode(ptr, s.getPtr());
  16 + }
  17 +
  18 + public void decode(OnlineStream[] ss) {
  19 + if (ss == null || ss.length == 0) {
  20 + throw new IllegalArgumentException("Stream array must be non-empty");
  21 + }
  22 + long[] streamPtrs = new long[ss.length];
  23 + for (int i = 0; i < ss.length; ++i) {
  24 + streamPtrs[i] = ss[i].getPtr();
  25 + }
  26 + decodeStreams(ptr, streamPtrs);
  27 + }
  28 +
  29 + public boolean isReady(OnlineStream s) {
  30 + return isReady(ptr, s.getPtr());
  31 + }
  32 +
  33 + public boolean isEndpoint(OnlineStream s) {
  34 + return isEndpoint(ptr, s.getPtr());
  35 + }
  36 +
  37 + public void reset(OnlineStream s) {
  38 + reset(ptr, s.getPtr());
  39 + }
  40 +
  41 + public OnlineStream createStream() {
  42 + long p = createStream(ptr, "");
  43 + return new OnlineStream(p);
  44 + }
  45 +
  46 + @Override
  47 + protected void finalize() throws Throwable {
  48 + release();
  49 + }
  50 +
  51 + // You'd better call it manually if it is not used anymore
  52 + protected void close() {
  53 + if (this.ptr == 0) {
  54 + return;
  55 + }
  56 + delete(this.ptr);
  57 + this.ptr = 0;
  58 + }
  59 +
  60 + public void release() {
  61 + this.close();
  62 + }
  63 +
  64 + public OnlineRecognizerResult getResult(OnlineStream s) {
  65 + Object[] arr = getResult(ptr, s.getPtr());
  66 + String text = (String) arr[0];
  67 + String[] tokens = (String[]) arr[1];
  68 + float[] timestamps = (float[]) arr[2];
  69 + return new OnlineRecognizerResult(text, tokens, timestamps);
  70 + }
  71 +
  72 +
  73 + private native void delete(long ptr);
  74 +
  75 + private native long newFromFile(OnlineRecognizerConfig config);
  76 +
  77 + private native long createStream(long ptr, String hotwords);
  78 +
  79 + private native void reset(long ptr, long streamPtr);
  80 +
  81 + private native void decode(long ptr, long streamPtr);
  82 +
  83 + private native void decodeStreams(long ptr, long[] streamPtrs);
  84 +
  85 + private native boolean isEndpoint(long ptr, long streamPtr);
  86 +
  87 + private native boolean isReady(long ptr, long streamPtr);
  88 +
  89 + private native Object[] getResult(long ptr, long streamPtr);
83 } 90 }
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineRecognizerConfig {  
7 - private final FeatureConfig featConfig;  
8 - private final OnlineModelConfig modelConfig;  
9 - private final OnlineLMConfig lmConfig;  
10 -  
11 - private final OnlineCtcFstDecoderConfig ctcFstDecoderConfig;  
12 - private final EndpointConfig endpointConfig;  
13 - private final HomophoneReplacerConfig hr;  
14 - private final boolean enableEndpoint;  
15 - private final String decodingMethod;  
16 - private final int maxActivePaths;  
17 - private final String hotwordsFile;  
18 - private final float hotwordsScore;  
19 - private final String ruleFsts;  
20 - private final String ruleFars;  
21 - private final float blankPenalty;  
22 -  
23 - private OnlineRecognizerConfig(Builder builder) {  
24 - this.featConfig = builder.featConfig;  
25 - this.modelConfig = builder.modelConfig;  
26 - this.lmConfig = builder.lmConfig;  
27 - this.ctcFstDecoderConfig = builder.ctcFstDecoderConfig;  
28 - this.endpointConfig = builder.endpointConfig;  
29 - this.hr = builder.hr;  
30 - this.enableEndpoint = builder.enableEndpoint;  
31 - this.decodingMethod = builder.decodingMethod;  
32 - this.maxActivePaths = builder.maxActivePaths;  
33 - this.hotwordsFile = builder.hotwordsFile;  
34 - this.hotwordsScore = builder.hotwordsScore;  
35 - this.ruleFsts = builder.ruleFsts;  
36 - this.ruleFars = builder.ruleFars;  
37 - this.blankPenalty = builder.blankPenalty;  
38 - }  
39 -  
40 - public static Builder builder() {  
41 - return new Builder();  
42 - }  
43 -  
44 - public OnlineModelConfig getModelConfig() {  
45 - return modelConfig;  
46 - }  
47 -  
48 - public static class Builder {  
49 - private FeatureConfig featConfig = FeatureConfig.builder().build();  
50 - private OnlineModelConfig modelConfig = OnlineModelConfig.builder().build();  
51 - private OnlineLMConfig lmConfig = OnlineLMConfig.builder().build();  
52 - private OnlineCtcFstDecoderConfig ctcFstDecoderConfig = OnlineCtcFstDecoderConfig.builder().build();  
53 - private EndpointConfig endpointConfig = EndpointConfig.builder().build();  
54 - private HomophoneReplacerConfig hr = HomophoneReplacerConfig.builder().build();  
55 - private boolean enableEndpoint = true;  
56 - private String decodingMethod = "greedy_search";  
57 - private int maxActivePaths = 4;  
58 - private String hotwordsFile = "";  
59 - private float hotwordsScore = 1.5f;  
60 - private String ruleFsts = "";  
61 - private String ruleFars = "";  
62 - private float blankPenalty = 0.0f;  
63 -  
64 - public OnlineRecognizerConfig build() {  
65 - return new OnlineRecognizerConfig(this);  
66 - }  
67 -  
68 - public Builder setFeatureConfig(FeatureConfig featConfig) {  
69 - this.featConfig = featConfig;  
70 - return this;  
71 - }  
72 -  
73 - public Builder setOnlineModelConfig(OnlineModelConfig modelConfig) {  
74 - this.modelConfig = modelConfig;  
75 - return this;  
76 - }  
77 -  
78 - public Builder setOnlineLMConfig(OnlineLMConfig lmConfig) {  
79 - this.lmConfig = lmConfig;  
80 - return this;  
81 - }  
82 -  
83 - public Builder setCtcFstDecoderConfig(OnlineCtcFstDecoderConfig ctcFstDecoderConfig) {  
84 - this.ctcFstDecoderConfig = ctcFstDecoderConfig;  
85 - return this;  
86 - }  
87 -  
88 - public Builder setEndpointConfig(EndpointConfig endpointConfig) {  
89 - this.endpointConfig = endpointConfig;  
90 - return this;  
91 - }  
92 -  
93 - public Builder setHr(HomophoneReplacerConfig hr) {  
94 - this.hr = hr;  
95 - return this;  
96 - }  
97 -  
98 - public Builder setEnableEndpoint(boolean enableEndpoint) {  
99 - this.enableEndpoint = enableEndpoint;  
100 - return this;  
101 - }  
102 -  
103 - public Builder setDecodingMethod(String decodingMethod) {  
104 - this.decodingMethod = decodingMethod;  
105 - return this;  
106 - }  
107 -  
108 - public Builder setMaxActivePaths(int maxActivePaths) {  
109 - this.maxActivePaths = maxActivePaths;  
110 - return this;  
111 - }  
112 -  
113 - public Builder setHotwordsFile(String hotwordsFile) {  
114 - this.hotwordsFile = hotwordsFile;  
115 - return this;  
116 - }  
117 -  
118 - public Builder setHotwordsScore(float hotwordsScore) {  
119 - this.hotwordsScore = hotwordsScore;  
120 - return this;  
121 - }  
122 -  
123 - public Builder setRuleFsts(String ruleFsts) {  
124 - this.ruleFsts = ruleFsts;  
125 - return this;  
126 - }  
127 -  
128 - public Builder setRuleFars(String ruleFars) {  
129 - this.ruleFars = ruleFars;  
130 - return this;  
131 - }  
132 -  
133 - public Builder setBlankPenalty(float blankPenalty) {  
134 - this.blankPenalty = blankPenalty;  
135 - return this;  
136 - }  
137 - }  
138 -} 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineRecognizerConfig {
  7 + private final FeatureConfig featConfig;
  8 + private final OnlineModelConfig modelConfig;
  9 + private final OnlineLMConfig lmConfig;
  10 +
  11 + private final OnlineCtcFstDecoderConfig ctcFstDecoderConfig;
  12 + private final EndpointConfig endpointConfig;
  13 + private final HomophoneReplacerConfig hr;
  14 + private final boolean enableEndpoint;
  15 + private final String decodingMethod;
  16 + private final int maxActivePaths;
  17 + private final String hotwordsFile;
  18 + private final float hotwordsScore;
  19 + private final String ruleFsts;
  20 + private final String ruleFars;
  21 + private final float blankPenalty;
  22 +
  23 + private OnlineRecognizerConfig(Builder builder) {
  24 + this.featConfig = builder.featConfig;
  25 + this.modelConfig = builder.modelConfig;
  26 + this.lmConfig = builder.lmConfig;
  27 + this.ctcFstDecoderConfig = builder.ctcFstDecoderConfig;
  28 + this.endpointConfig = builder.endpointConfig;
  29 + this.hr = builder.hr;
  30 + this.enableEndpoint = builder.enableEndpoint;
  31 + this.decodingMethod = builder.decodingMethod;
  32 + this.maxActivePaths = builder.maxActivePaths;
  33 + this.hotwordsFile = builder.hotwordsFile;
  34 + this.hotwordsScore = builder.hotwordsScore;
  35 + this.ruleFsts = builder.ruleFsts;
  36 + this.ruleFars = builder.ruleFars;
  37 + this.blankPenalty = builder.blankPenalty;
  38 + }
  39 +
  40 + public static Builder builder() {
  41 + return new Builder();
  42 + }
  43 +
  44 + public OnlineModelConfig getModelConfig() {
  45 + return modelConfig;
  46 + }
  47 +
  48 + public static class Builder {
  49 + private FeatureConfig featConfig = FeatureConfig.builder().build();
  50 + private OnlineModelConfig modelConfig = OnlineModelConfig.builder().build();
  51 + private OnlineLMConfig lmConfig = OnlineLMConfig.builder().build();
  52 + private OnlineCtcFstDecoderConfig ctcFstDecoderConfig = OnlineCtcFstDecoderConfig.builder().build();
  53 + private EndpointConfig endpointConfig = EndpointConfig.builder().build();
  54 + private HomophoneReplacerConfig hr = HomophoneReplacerConfig.builder().build();
  55 + private boolean enableEndpoint = true;
  56 + private String decodingMethod = "greedy_search";
  57 + private int maxActivePaths = 4;
  58 + private String hotwordsFile = "";
  59 + private float hotwordsScore = 1.5f;
  60 + private String ruleFsts = "";
  61 + private String ruleFars = "";
  62 + private float blankPenalty = 0.0f;
  63 +
  64 + public OnlineRecognizerConfig build() {
  65 + return new OnlineRecognizerConfig(this);
  66 + }
  67 +
  68 + public Builder setFeatureConfig(FeatureConfig featConfig) {
  69 + this.featConfig = featConfig;
  70 + return this;
  71 + }
  72 +
  73 + public Builder setOnlineModelConfig(OnlineModelConfig modelConfig) {
  74 + this.modelConfig = modelConfig;
  75 + return this;
  76 + }
  77 +
  78 + public Builder setOnlineLMConfig(OnlineLMConfig lmConfig) {
  79 + this.lmConfig = lmConfig;
  80 + return this;
  81 + }
  82 +
  83 + public Builder setCtcFstDecoderConfig(OnlineCtcFstDecoderConfig ctcFstDecoderConfig) {
  84 + this.ctcFstDecoderConfig = ctcFstDecoderConfig;
  85 + return this;
  86 + }
  87 +
  88 + public Builder setEndpointConfig(EndpointConfig endpointConfig) {
  89 + this.endpointConfig = endpointConfig;
  90 + return this;
  91 + }
  92 +
  93 + public Builder setHr(HomophoneReplacerConfig hr) {
  94 + this.hr = hr;
  95 + return this;
  96 + }
  97 +
  98 + public Builder setEnableEndpoint(boolean enableEndpoint) {
  99 + this.enableEndpoint = enableEndpoint;
  100 + return this;
  101 + }
  102 +
  103 + public Builder setDecodingMethod(String decodingMethod) {
  104 + this.decodingMethod = decodingMethod;
  105 + return this;
  106 + }
  107 +
  108 + public Builder setMaxActivePaths(int maxActivePaths) {
  109 + this.maxActivePaths = maxActivePaths;
  110 + return this;
  111 + }
  112 +
  113 + public Builder setHotwordsFile(String hotwordsFile) {
  114 + this.hotwordsFile = hotwordsFile;
  115 + return this;
  116 + }
  117 +
  118 + public Builder setHotwordsScore(float hotwordsScore) {
  119 + this.hotwordsScore = hotwordsScore;
  120 + return this;
  121 + }
  122 +
  123 + public Builder setRuleFsts(String ruleFsts) {
  124 + this.ruleFsts = ruleFsts;
  125 + return this;
  126 + }
  127 +
  128 + public Builder setRuleFars(String ruleFars) {
  129 + this.ruleFars = ruleFars;
  130 + return this;
  131 + }
  132 +
  133 + public Builder setBlankPenalty(float blankPenalty) {
  134 + this.blankPenalty = blankPenalty;
  135 + return this;
  136 + }
  137 + }
  138 +}
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineStream {  
7 - private long ptr = 0;  
8 -  
9 - public OnlineStream() {  
10 - LibraryLoader.maybeLoad();  
11 - this.ptr = 0;  
12 - }  
13 -  
14 - public OnlineStream(long ptr) {  
15 - this.ptr = ptr;  
16 - }  
17 -  
18 - public long getPtr() {  
19 - return ptr;  
20 - }  
21 -  
22 - public void setPtr(long ptr) {  
23 - this.ptr = ptr;  
24 - }  
25 -  
26 - public void acceptWaveform(float[] samples, int sampleRate) {  
27 - acceptWaveform(this.ptr, samples, sampleRate);  
28 - }  
29 -  
30 - public void inputFinished() {  
31 - inputFinished(this.ptr);  
32 - }  
33 -  
34 - public void release() {  
35 - // stream object must be release after used  
36 - if (this.ptr == 0) {  
37 - return;  
38 - }  
39 - delete(this.ptr);  
40 - this.ptr = 0;  
41 - }  
42 -  
43 - @Override  
44 - protected void finalize() throws Throwable {  
45 - release();  
46 - super.finalize();  
47 - }  
48 -  
49 - private native void acceptWaveform(long ptr, float[] samples, int sampleRate);  
50 -  
51 - private native void inputFinished(long ptr);  
52 -  
53 - private native void delete(long ptr); 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineStream {
  7 + private long ptr = 0;
  8 +
  9 + public OnlineStream() {
  10 + LibraryLoader.maybeLoad();
  11 + this.ptr = 0;
  12 + }
  13 +
  14 + public OnlineStream(long ptr) {
  15 + this.ptr = ptr;
  16 + }
  17 +
  18 + public long getPtr() {
  19 + return ptr;
  20 + }
  21 +
  22 + public void setPtr(long ptr) {
  23 + this.ptr = ptr;
  24 + }
  25 +
  26 + public void acceptWaveform(float[] samples, int sampleRate) {
  27 + acceptWaveform(this.ptr, samples, sampleRate);
  28 + }
  29 +
  30 + public void inputFinished() {
  31 + inputFinished(this.ptr);
  32 + }
  33 +
  34 + public void release() {
  35 + close();
  36 + }
  37 +
  38 + public void close() {
  39 + // stream object must be release after used
  40 + if (this.ptr == 0) {
  41 + return;
  42 + }
  43 + delete(this.ptr);
  44 + this.ptr = 0;
  45 + }
  46 +
  47 + @Override
  48 + protected void finalize() throws Throwable {
  49 + close();
  50 + super.finalize();
  51 + }
  52 +
  53 + private native void acceptWaveform(long ptr, float[] samples, int sampleRate);
  54 +
  55 + private native void inputFinished(long ptr);
  56 +
  57 + private native void delete(long ptr);
54 } 58 }
1 -// Copyright 2022-2023 by zhaoming  
2 -// Copyright 2024 Xiaomi Corporation  
3 -  
4 -package com.k2fsa.sherpa.onnx;  
5 -  
6 -public class OnlineTransducerModelConfig {  
7 - private final String encoder;  
8 - private final String decoder;  
9 - private final String joiner;  
10 -  
11 - private OnlineTransducerModelConfig(Builder builder) {  
12 - this.encoder = builder.encoder;  
13 - this.decoder = builder.decoder;  
14 - this.joiner = builder.joiner;  
15 - }  
16 -  
17 - public static Builder builder() {  
18 - return new Builder();  
19 - }  
20 -  
21 - public String getEncoder() {  
22 - return encoder;  
23 - }  
24 -  
25 - public String getDecoder() {  
26 - return decoder;  
27 - }  
28 -  
29 - public String getJoiner() {  
30 - return joiner;  
31 - }  
32 -  
33 - public static class Builder {  
34 - private String encoder = "";  
35 - private String decoder = "";  
36 - private String joiner = "";  
37 -  
38 - public OnlineTransducerModelConfig build() {  
39 - return new OnlineTransducerModelConfig(this);  
40 - }  
41 -  
42 - public Builder setEncoder(String encoder) {  
43 - this.encoder = encoder;  
44 - return this;  
45 - }  
46 -  
47 - public Builder setDecoder(String decoder) {  
48 - this.decoder = decoder;  
49 - return this;  
50 - }  
51 -  
52 - public Builder setJoiner(String joiner) {  
53 - this.joiner = joiner;  
54 - return this;  
55 - }  
56 - }  
57 -} 1 +// Copyright 2022-2023 by zhaoming
  2 +// Copyright 2024 Xiaomi Corporation
  3 +
  4 +package com.k2fsa.sherpa.onnx;
  5 +
  6 +public class OnlineTransducerModelConfig {
  7 + private final String encoder;
  8 + private final String decoder;
  9 + private final String joiner;
  10 +
  11 + private OnlineTransducerModelConfig(Builder builder) {
  12 + this.encoder = builder.encoder;
  13 + this.decoder = builder.decoder;
  14 + this.joiner = builder.joiner;
  15 + }
  16 +
  17 + public static Builder builder() {
  18 + return new Builder();
  19 + }
  20 +
  21 + public String getEncoder() {
  22 + return encoder;
  23 + }
  24 +
  25 + public String getDecoder() {
  26 + return decoder;
  27 + }
  28 +
  29 + public String getJoiner() {
  30 + return joiner;
  31 + }
  32 +
  33 + public static class Builder {
  34 + private String encoder = "";
  35 + private String decoder = "";
  36 + private String joiner = "";
  37 +
  38 + public OnlineTransducerModelConfig build() {
  39 + return new OnlineTransducerModelConfig(this);
  40 + }
  41 +
  42 + public Builder setEncoder(String encoder) {
  43 + this.encoder = encoder;
  44 + return this;
  45 + }
  46 +
  47 + public Builder setDecoder(String decoder) {
  48 + this.decoder = decoder;
  49 + return this;
  50 + }
  51 +
  52 + public Builder setJoiner(String joiner) {
  53 + this.joiner = joiner;
  54 + return this;
  55 + }
  56 + }
  57 +}
  1 +package com.k2fsa.sherpa.onnx.core;
  2 +
  3 +public interface Core {
  4 + String NATIVE_LIBRARY_NAME = "sherpa-onnx-jni";
  5 +}
  1 +package com.k2fsa.sherpa.onnx.utils;
  2 +
  3 +import java.io.File;
  4 +import java.io.IOException;
  5 +import java.io.InputStream;
  6 +import java.nio.file.Files;
  7 +import java.nio.file.StandardCopyOption;
  8 +import java.util.Locale;
  9 +
  10 +import com.k2fsa.sherpa.onnx.core.Core;
  11 +
  12 +public class LibraryUtils {
  13 + // System property to override native library path
  14 + private static final String NATIVE_PATH_PROP = "sherpa_onnx.native.path";
  15 +
  16 + public static void load() {
  17 + String libFileName = System.mapLibraryName(Core.NATIVE_LIBRARY_NAME);
  18 +
  19 + // 1. Try loading from external directory if provided
  20 + String nativePath = System.getProperty(NATIVE_PATH_PROP);
  21 + if (nativePath != null) {
  22 + File nativeDir = new File(nativePath);
  23 + File libInDir = new File(nativeDir, libFileName);
  24 + if (nativeDir.isDirectory() && libInDir.exists()) {
  25 + System.out.println("Loading native lib from external directory: " + libInDir.getAbsolutePath());
  26 + System.load(libInDir.getAbsolutePath());
  27 + return;
  28 + }
  29 + }
  30 +
  31 + // 2. Fallback to extracting and loading from the JAR
  32 + File libFile = init(libFileName);
  33 + System.out.println("Loading native lib from: " + libFile.getAbsolutePath());
  34 + System.load(libFile.getAbsolutePath());
  35 + }
  36 +
  37 + /* Computes and initializes OS_ARCH_STR (such as linux-x64) */
  38 + private static String initOsArch() {
  39 + String detectedOS = null;
  40 + String os = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
  41 + if (os.contains("mac") || os.contains("darwin")) {
  42 + detectedOS = "osx";
  43 + } else if (os.contains("win")) {
  44 + detectedOS = "win";
  45 + } else if (os.contains("nux")) {
  46 + detectedOS = "linux";
  47 + } else {
  48 + throw new IllegalStateException("Unsupported os:" + os);
  49 + }
  50 + String detectedArch = null;
  51 + String arch = System.getProperty("os.arch", "generic").toLowerCase(Locale.ENGLISH);
  52 + if (arch.startsWith("amd64") || arch.startsWith("x86_64")) {
  53 + detectedArch = "x64";
  54 + } else if (arch.startsWith("x86")) {
  55 + // 32-bit x86 is not supported by the Java API
  56 + detectedArch = "x86";
  57 + } else if (arch.startsWith("aarch64")) {
  58 + detectedArch = "aarch64";
  59 + } else {
  60 + throw new IllegalStateException("Unsupported arch:" + arch);
  61 + }
  62 + return detectedOS + '-' + detectedArch;
  63 + }
  64 +
  65 + private static File init(String libFileName) {
  66 + String osName = System.getProperty("os.name").toLowerCase();
  67 + String osArch = System.getProperty("os.arch").toLowerCase();
  68 + String userHome = System.getProperty("user.home");
  69 + System.out.printf("Detected OS=%s, ARCH=%s, HOME=%s%n", osName, osArch, userHome);
  70 +
  71 + String archName = initOsArch();
  72 +
  73 + // Prepare destination directory under ~/lib/<archName>/
  74 + String dstDir = userHome + File.separator + "lib" + File.separator + archName;
  75 + File libFile = new File(dstDir, libFileName);
  76 + File parentDir = libFile.getParentFile();
  77 + if (!parentDir.exists() && !parentDir.mkdirs()) {
  78 + throw new RuntimeException("Unable to create directory: " + parentDir);
  79 + }
  80 +
  81 + // Extract the native library from JAR
  82 + extractResource("/native/" + archName + "/" + libFileName, libFile);
  83 + return libFile;
  84 + }
  85 +
  86 + /**
  87 + * Copies a resource file from the jar to the specified destination.
  88 + *
  89 + * @param resourcePath The resource path inside the jar, e.g.:
  90 + * /native/linux_x64/libonnxruntime.so
  91 + * @param destination The destination file on disk
  92 + */
  93 + private static void extractResource(String resourcePath, File destination) {
  94 + try (InputStream in = LibraryUtils.class.getResourceAsStream(resourcePath)) {
  95 + if (in == null) {
  96 + throw new RuntimeException("Resource not found: " + resourcePath);
  97 + }
  98 + Files.copy(in, destination.toPath(), StandardCopyOption.REPLACE_EXISTING);
  99 + } catch (IOException e) {
  100 + throw new RuntimeException("Failed to extract resource " + resourcePath + " to " + destination.getAbsolutePath(),
  101 + e);
  102 + }
  103 + }
  104 +}
  1 +please downlaod file and put in folder
  2 +[donwload link](https://huggingface.co/csukuangfj/sherpa-onnx-libs/tree/main/jni)
  3 +
  4 +- sherpa-onnx-v1.12.7-linux-aarch64-jni.tar.bz2
  5 +- sherpa-onnx-v1.12.7-linux-x64-jni.tar.bz2
  6 +- sherpa-onnx-v1.12.7-osx-arm64-jni.tar.bz2
  7 +- sherpa-onnx-v1.12.7-osx-x86_64-jni.tar.bz2
  8 +- sherpa-onnx-v1.12.7-win-x64-jni.tar.bz2
  9 +
  10 +
  11 +- linux_arm64
  12 +- linux_x64
  13 +- darwin_arm64
  14 +- darwin_x64
  15 +- windows_x64
  16 +
  17 +
  18 +add to src/main/resources
  19 +
  20 +```
  21 +.
  22 +├── native
  23 +│ ├── linux-aarch64
  24 +│ │ ├── libsherpa-onnx-jni.so
  25 +│ ├── linux-x64
  26 +│ │ ├── libsherpa-onnx-jni.so
  27 +│ ├── osx-aarch64
  28 +│ │ ├── libsherpa-onnx-jni.dylib
  29 +│ ├── osx-x64
  30 +│ │ ├── libsherpa-onnx-jni.dylib
  31 +│ ├── win-x64
  32 +│ │ ├── sherpa-onnx-jni.dll
  33 +```
  34 +