react-native-sherpa-onnx 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/README.md +92 -21
- package/SherpaOnnx.podspec +3 -0
- package/THIRD_PARTY_LICENSES/README.md +62 -0
- package/THIRD_PARTY_LICENSES/ffmpeg.txt +502 -0
- package/THIRD_PARTY_LICENSES/libarchive.txt +65 -0
- package/THIRD_PARTY_LICENSES/nvidia_omla.txt +181 -0
- package/THIRD_PARTY_LICENSES/onnxruntime.txt +21 -0
- package/THIRD_PARTY_LICENSES/opus.txt +44 -0
- package/THIRD_PARTY_LICENSES/sherpa-onnx.txt +201 -0
- package/THIRD_PARTY_LICENSES/shine.txt +482 -0
- package/THIRD_PARTY_LICENSES/zstd.txt +30 -0
- package/android/build.gradle +7 -3
- package/android/prebuilt-download.gradle +344 -152
- package/android/prebuilt-versions.gradle +1 -1
- package/android/src/main/assets/model_licenses/asr-models-license-status.csv +409 -0
- package/android/src/main/assets/model_licenses/qnn-asr-models-license-status.csv +695 -0
- package/android/src/main/assets/model_licenses/tts-models-license-status.csv +596 -0
- package/android/src/main/cpp/CMakeLists.txt +28 -10
- package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-helper.cpp +2 -2
- package/android/src/main/cpp/jni/audio/sherpa-onnx-audio-convert-jni.cpp +268 -2
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-tts.cpp +37 -6
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect.h +9 -1
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-tts-wrapper.cpp +7 -0
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-tts.cpp +18 -2
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxArchiveHelper.kt +40 -10
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +99 -0
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxOnlineSttHelper.kt +4 -1
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxTtsHelper.kt +127 -97
- package/ios/Resources/model_licenses/asr-models-license-status.csv +409 -0
- package/ios/Resources/model_licenses/qnn-asr-models-license-status.csv +695 -0
- package/ios/Resources/model_licenses/tts-models-license-status.csv +596 -0
- package/ios/SherpaOnnx+OnlineSTT.mm +2 -0
- package/ios/SherpaOnnx+PcmLiveStream.mm +2 -29
- package/ios/SherpaOnnx+TTS.mm +179 -20
- package/ios/SherpaOnnx.mm +54 -0
- package/ios/SherpaOnnxAudioConvert.h +10 -0
- package/ios/SherpaOnnxAudioConvert.mm +257 -1
- package/ios/archive/sherpa-onnx-archive-helper.h +3 -0
- package/ios/archive/sherpa-onnx-archive-helper.mm +39 -6
- package/ios/model_detect/sherpa-onnx-model-detect-tts.mm +49 -6
- package/ios/model_detect/sherpa-onnx-model-detect.h +9 -1
- package/ios/model_detect/sherpa-onnx-validate-tts.mm +18 -2
- package/ios/online_stt/sherpa-onnx-online-stt-wrapper.h +1 -0
- package/ios/online_stt/sherpa-onnx-online-stt-wrapper.mm +4 -0
- package/ios/tts/sherpa-onnx-tts-wrapper.h +37 -0
- package/ios/tts/sherpa-onnx-tts-wrapper.mm +158 -3
- package/lib/module/NativeSherpaOnnx.js.map +1 -1
- package/lib/module/audio/index.js +8 -0
- package/lib/module/audio/index.js.map +1 -1
- package/lib/module/download/ModelDownloadManager.js +10 -929
- package/lib/module/download/ModelDownloadManager.js.map +1 -1
- package/lib/module/download/activeModelOperations.js +26 -0
- package/lib/module/download/activeModelOperations.js.map +1 -0
- package/lib/module/download/background-downloader-types.js +2 -0
- package/lib/module/download/background-downloader-types.js.map +1 -0
- package/lib/module/download/bulkPurge.js +72 -0
- package/lib/module/download/bulkPurge.js.map +1 -0
- package/lib/module/download/checksumPrompt.js +19 -0
- package/lib/module/download/checksumPrompt.js.map +1 -0
- package/lib/module/download/constants.js +7 -0
- package/lib/module/download/constants.js.map +1 -0
- package/lib/module/download/downloadEvents.js +35 -0
- package/lib/module/download/downloadEvents.js.map +1 -0
- package/lib/module/download/downloadTask.js +438 -0
- package/lib/module/download/downloadTask.js.map +1 -0
- package/lib/module/download/ensureModel.js +89 -0
- package/lib/module/download/ensureModel.js.map +1 -0
- package/lib/module/download/index.js +4 -4
- package/lib/module/download/index.js.map +1 -1
- package/lib/module/download/localModels.js +151 -0
- package/lib/module/download/localModels.js.map +1 -0
- package/lib/module/download/modelExtraction.js +174 -0
- package/lib/module/download/modelExtraction.js.map +1 -0
- package/lib/module/download/paths.js +98 -0
- package/lib/module/download/paths.js.map +1 -0
- package/lib/module/download/postDownloadProcessing.js +206 -0
- package/lib/module/download/postDownloadProcessing.js.map +1 -0
- package/lib/module/download/protectedModelKeys.js +31 -0
- package/lib/module/download/protectedModelKeys.js.map +1 -0
- package/lib/module/download/registry.js +268 -0
- package/lib/module/download/registry.js.map +1 -0
- package/lib/module/download/retry.js +59 -0
- package/lib/module/download/retry.js.map +1 -0
- package/lib/module/download/types.js +17 -0
- package/lib/module/download/types.js.map +1 -0
- package/lib/module/download/validation.js +101 -5
- package/lib/module/download/validation.js.map +1 -1
- package/lib/module/{download → extraction}/extractTarBz2.js +3 -1
- package/lib/module/extraction/extractTarBz2.js.map +1 -0
- package/lib/module/{download → extraction}/extractTarZst.js +3 -1
- package/lib/module/extraction/extractTarZst.js.map +1 -0
- package/lib/module/extraction/index.js +3 -4
- package/lib/module/extraction/index.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/licenses.js +63 -0
- package/lib/module/licenses.js.map +1 -0
- package/lib/module/stt/index.js +16 -2
- package/lib/module/stt/index.js.map +1 -1
- package/lib/module/stt/streaming.js +2 -0
- package/lib/module/stt/streaming.js.map +1 -1
- package/lib/module/stt/streamingTypes.js.map +1 -1
- package/lib/module/stt/types.js.map +1 -1
- package/lib/module/tts/index.js +21 -3
- package/lib/module/tts/index.js.map +1 -1
- package/lib/module/tts/streaming.js +5 -1
- package/lib/module/tts/streaming.js.map +1 -1
- package/lib/module/tts/types.js +4 -1
- package/lib/module/tts/types.js.map +1 -1
- package/lib/module/utils.js +16 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/src/NativeSherpaOnnx.d.ts +34 -6
- package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
- package/lib/typescript/src/audio/index.d.ts +10 -0
- package/lib/typescript/src/audio/index.d.ts.map +1 -1
- package/lib/typescript/src/download/ModelDownloadManager.d.ts +11 -108
- package/lib/typescript/src/download/ModelDownloadManager.d.ts.map +1 -1
- package/lib/typescript/src/download/activeModelOperations.d.ts +6 -0
- package/lib/typescript/src/download/activeModelOperations.d.ts.map +1 -0
- package/lib/typescript/src/download/background-downloader-types.d.ts +64 -0
- package/lib/typescript/src/download/background-downloader-types.d.ts.map +1 -0
- package/lib/typescript/src/download/bulkPurge.d.ts +14 -0
- package/lib/typescript/src/download/bulkPurge.d.ts.map +1 -0
- package/lib/typescript/src/download/checksumPrompt.d.ts +3 -0
- package/lib/typescript/src/download/checksumPrompt.d.ts.map +1 -0
- package/lib/typescript/src/download/constants.d.ts +5 -0
- package/lib/typescript/src/download/constants.d.ts.map +1 -0
- package/lib/typescript/src/download/downloadEvents.d.ts +6 -0
- package/lib/typescript/src/download/downloadEvents.d.ts.map +1 -0
- package/lib/typescript/src/download/downloadTask.d.ts +30 -0
- package/lib/typescript/src/download/downloadTask.d.ts.map +1 -0
- package/lib/typescript/src/download/ensureModel.d.ts +26 -0
- package/lib/typescript/src/download/ensureModel.d.ts.map +1 -0
- package/lib/typescript/src/download/index.d.ts +7 -7
- package/lib/typescript/src/download/index.d.ts.map +1 -1
- package/lib/typescript/src/download/localModels.d.ts +15 -0
- package/lib/typescript/src/download/localModels.d.ts.map +1 -0
- package/lib/typescript/src/download/modelExtraction.d.ts +36 -0
- package/lib/typescript/src/download/modelExtraction.d.ts.map +1 -0
- package/lib/typescript/src/download/paths.d.ts +28 -0
- package/lib/typescript/src/download/paths.d.ts.map +1 -0
- package/lib/typescript/src/download/postDownloadProcessing.d.ts +19 -0
- package/lib/typescript/src/download/postDownloadProcessing.d.ts.map +1 -0
- package/lib/typescript/src/download/protectedModelKeys.d.ts +6 -0
- package/lib/typescript/src/download/protectedModelKeys.d.ts.map +1 -0
- package/lib/typescript/src/download/registry.d.ts +14 -0
- package/lib/typescript/src/download/registry.d.ts.map +1 -0
- package/lib/typescript/src/download/retry.d.ts +15 -0
- package/lib/typescript/src/download/retry.d.ts.map +1 -0
- package/lib/typescript/src/download/types.d.ts +96 -0
- package/lib/typescript/src/download/types.d.ts.map +1 -0
- package/lib/typescript/src/download/validation.d.ts +19 -0
- package/lib/typescript/src/download/validation.d.ts.map +1 -1
- package/lib/typescript/src/extraction/extractTarBz2.d.ts.map +1 -0
- package/lib/typescript/src/extraction/extractTarZst.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/licenses.d.ts +10 -0
- package/lib/typescript/src/licenses.d.ts.map +1 -0
- package/lib/typescript/src/stt/index.d.ts +4 -1
- package/lib/typescript/src/stt/index.d.ts.map +1 -1
- package/lib/typescript/src/stt/streaming.d.ts.map +1 -1
- package/lib/typescript/src/stt/streamingTypes.d.ts +5 -0
- package/lib/typescript/src/stt/streamingTypes.d.ts.map +1 -1
- package/lib/typescript/src/stt/types.d.ts +3 -1
- package/lib/typescript/src/stt/types.d.ts.map +1 -1
- package/lib/typescript/src/tts/index.d.ts +4 -2
- package/lib/typescript/src/tts/index.d.ts.map +1 -1
- package/lib/typescript/src/tts/streaming.d.ts.map +1 -1
- package/lib/typescript/src/tts/types.d.ts +12 -6
- package/lib/typescript/src/tts/types.d.ts.map +1 -1
- package/lib/typescript/src/utils.d.ts +5 -0
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/package.json +6 -1
- package/scripts/{check-model-csvs.sh → ci/check-model-csvs.sh} +9 -2
- package/scripts/ci/collect_all_sherpa_model_streams.sh +101 -0
- package/scripts/ci/collect_one_sherpa_release_stream.sh +189 -0
- package/scripts/ci/sherpa_asr_model_release_streams.json +21 -0
- package/scripts/ci/sherpa_tts_model_release_streams.json +13 -0
- package/scripts/ci/update_model_license_csv.sh +765 -0
- package/scripts/setup-ios-framework.sh +14 -11
- package/scripts/update_commercial_use.js +73 -0
- package/src/NativeSherpaOnnx.ts +37 -6
- package/src/audio/index.ts +20 -0
- package/src/download/ModelDownloadManager.ts +57 -1343
- package/src/download/activeModelOperations.ts +38 -0
- package/src/download/background-downloader-types.ts +73 -0
- package/src/download/bulkPurge.ts +102 -0
- package/src/download/checksumPrompt.ts +25 -0
- package/src/download/constants.ts +5 -0
- package/src/download/downloadEvents.ts +55 -0
- package/src/download/downloadTask.ts +565 -0
- package/src/download/ensureModel.ts +124 -0
- package/src/download/index.ts +21 -4
- package/src/download/localModels.ts +234 -0
- package/src/download/modelExtraction.ts +244 -0
- package/src/download/paths.ts +134 -0
- package/src/download/postDownloadProcessing.ts +292 -0
- package/src/download/protectedModelKeys.ts +30 -0
- package/src/download/registry.ts +405 -0
- package/src/download/retry.ts +76 -0
- package/src/download/types.ts +120 -0
- package/src/download/validation.ts +114 -8
- package/src/{download → extraction}/extractTarBz2.ts +3 -1
- package/src/{download → extraction}/extractTarZst.ts +3 -1
- package/src/extraction/index.ts +3 -7
- package/src/index.tsx +1 -0
- package/src/licenses.ts +100 -0
- package/src/stt/index.ts +20 -2
- package/src/stt/streaming.ts +3 -0
- package/src/stt/streamingTypes.ts +5 -0
- package/src/stt/types.ts +3 -1
- package/src/tts/index.ts +33 -2
- package/src/tts/streaming.ts +12 -0
- package/src/tts/types.ts +15 -5
- package/src/utils.ts +22 -1
- package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -1
- package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -1
- package/android/src/main/cpp/jni/tts/sherpa-onnx-tts-zipvoice-jni.cpp +0 -301
- package/android/src/main/java/com/sherpaonnx/ZipvoiceTtsWrapper.kt +0 -187
- package/lib/module/download/extractTarBz2.js.map +0 -1
- package/lib/module/download/extractTarZst.js.map +0 -1
- package/lib/typescript/src/download/extractTarBz2.d.ts.map +0 -1
- package/lib/typescript/src/download/extractTarZst.d.ts.map +0 -1
- package/scripts/check-qnn-support.sh +0 -78
- /package/lib/typescript/src/{download → extraction}/extractTarBz2.d.ts +0 -0
- /package/lib/typescript/src/{download → extraction}/extractTarZst.d.ts +0 -0
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
stat,
|
|
4
4
|
exists,
|
|
5
5
|
readDir,
|
|
6
|
+
unlink,
|
|
6
7
|
type ReadDirResItemT,
|
|
7
8
|
} from '@dr.pogodin/react-native-fs';
|
|
8
9
|
import SherpaOnnx from '../NativeSherpaOnnx';
|
|
@@ -25,6 +26,37 @@ export class ValidationResult {
|
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Delete a directory and all contents. No-op if the path is missing.
|
|
31
|
+
* Best-effort: continues on per-entry errors (permissions, race).
|
|
32
|
+
*/
|
|
33
|
+
export async function removeDirectoryRecursive(dirPath: string): Promise<void> {
|
|
34
|
+
if (!(await exists(dirPath))) return;
|
|
35
|
+
let entries: ReadDirResItemT[];
|
|
36
|
+
try {
|
|
37
|
+
entries = await readDir(dirPath);
|
|
38
|
+
} catch {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
const childPath = `${dirPath}/${entry.name}`.replace(/\/+/g, '/');
|
|
43
|
+
try {
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
await removeDirectoryRecursive(childPath);
|
|
46
|
+
} else {
|
|
47
|
+
await unlink(childPath);
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
// ignore
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await unlink(dirPath);
|
|
55
|
+
} catch {
|
|
56
|
+
// ignore
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
28
60
|
/**
|
|
29
61
|
* Parse checksum.txt format into a Map of filename -> hash
|
|
30
62
|
* Expected format:
|
|
@@ -148,12 +180,15 @@ export async function validateExtractedFiles(
|
|
|
148
180
|
|
|
149
181
|
for (const entry of entries) {
|
|
150
182
|
if (entry.isDirectory()) {
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
183
|
+
const subPath = entry.path;
|
|
184
|
+
if (subPath != null) {
|
|
185
|
+
const nested = await collectFilesRecursive(
|
|
186
|
+
subPath,
|
|
187
|
+
depth + 1,
|
|
188
|
+
maxDepth
|
|
189
|
+
);
|
|
190
|
+
files.push(...nested);
|
|
191
|
+
}
|
|
157
192
|
} else {
|
|
158
193
|
files.push(entry);
|
|
159
194
|
}
|
|
@@ -175,13 +210,13 @@ export async function validateExtractedFiles(
|
|
|
175
210
|
}
|
|
176
211
|
|
|
177
212
|
let hasModelLikeFiles = actualFiles.some((file) =>
|
|
178
|
-
isModelLikeFile(file.name)
|
|
213
|
+
isModelLikeFile(file.name ?? '')
|
|
179
214
|
);
|
|
180
215
|
|
|
181
216
|
if (!hasModelLikeFiles) {
|
|
182
217
|
const nestedFiles = await collectFilesRecursive(modelDir);
|
|
183
218
|
hasModelLikeFiles = nestedFiles.some((file) =>
|
|
184
|
-
isModelLikeFile(file.name)
|
|
219
|
+
isModelLikeFile(file.name ?? '')
|
|
185
220
|
);
|
|
186
221
|
}
|
|
187
222
|
|
|
@@ -203,6 +238,77 @@ export async function validateExtractedFiles(
|
|
|
203
238
|
}
|
|
204
239
|
}
|
|
205
240
|
|
|
241
|
+
/** True if the file is a native sherpa-onnx model file (e.g. encoder.onnx). Excludes our metadata (.ready, manifest.json). */
|
|
242
|
+
function isNativeModelFileName(name: string): boolean {
|
|
243
|
+
const lower = name.toLowerCase();
|
|
244
|
+
return lower.endsWith('.onnx') || lower.endsWith('.bin');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Check if a directory contains native model files (.onnx or .bin) at the top level or one level of subdirectories.
|
|
249
|
+
* Used to find the actual model dir; ignores our metadata (manifest.json, .ready).
|
|
250
|
+
*/
|
|
251
|
+
async function dirContainsModelFiles(dir: string): Promise<boolean> {
|
|
252
|
+
const entries = await readDir(dir);
|
|
253
|
+
const files = entries.filter((e) => !e.isDirectory());
|
|
254
|
+
if (files.some((f) => isNativeModelFileName(f.name ?? ''))) return true;
|
|
255
|
+
const subdirs = entries.filter((e) => e.isDirectory());
|
|
256
|
+
for (const sub of subdirs) {
|
|
257
|
+
const subPath = sub?.path;
|
|
258
|
+
if (subPath == null) continue;
|
|
259
|
+
const subEntries = await readDir(subPath);
|
|
260
|
+
const subFiles = subEntries.filter((e) => !e.isDirectory());
|
|
261
|
+
if (subFiles.some((f) => isNativeModelFileName(f.name ?? ''))) return true;
|
|
262
|
+
}
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Resolve the directory that actually contains model files.
|
|
268
|
+
* After extracting a tarball, model files often end up in a single top-level subdirectory
|
|
269
|
+
* (e.g. installDir/modelId/encoder.onnx). Native APIs expect the path to the folder
|
|
270
|
+
* that directly contains encoder.onnx, decoder.onnx, etc.
|
|
271
|
+
*
|
|
272
|
+
* - If installDir itself contains native model files (.onnx/.bin), returns installDir.
|
|
273
|
+
* - If installDir has exactly one subdirectory that contains native model files, returns that subdirectory path.
|
|
274
|
+
* (Ignores our metadata: .ready, manifest.json.) This can produce paths like
|
|
275
|
+
* .../tts/vits-piper-de_DE-thorsten-medium-int8/vits-piper-de_DE-thorsten-medium-int8 when the
|
|
276
|
+
* archive extracts a top-level folder with the same name as the model id; that is intentional.
|
|
277
|
+
* - Otherwise returns installDir unchanged.
|
|
278
|
+
*/
|
|
279
|
+
export async function resolveActualModelDir(
|
|
280
|
+
installDir: string
|
|
281
|
+
): Promise<string> {
|
|
282
|
+
try {
|
|
283
|
+
const dirExists = await exists(installDir);
|
|
284
|
+
if (!dirExists) return installDir;
|
|
285
|
+
|
|
286
|
+
const entries = await readDir(installDir);
|
|
287
|
+
const topLevelFiles = entries.filter((e) => !e.isDirectory());
|
|
288
|
+
if (topLevelFiles.some((f) => isNativeModelFileName(f.name ?? ''))) {
|
|
289
|
+
return installDir;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const subdirs = entries.filter((e) => e.isDirectory());
|
|
293
|
+
const firstSubdir = subdirs[0];
|
|
294
|
+
const singleSubdir = subdirs.length === 1 ? firstSubdir : undefined;
|
|
295
|
+
|
|
296
|
+
if (singleSubdir != null) {
|
|
297
|
+
const candidatePath = singleSubdir.path;
|
|
298
|
+
if (
|
|
299
|
+
candidatePath != null &&
|
|
300
|
+
(await dirContainsModelFiles(candidatePath))
|
|
301
|
+
) {
|
|
302
|
+
return candidatePath;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return installDir;
|
|
307
|
+
} catch {
|
|
308
|
+
return installDir;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
206
312
|
/**
|
|
207
313
|
* Get available disk space (in bytes)
|
|
208
314
|
* This is a simplified version. For accurate values on Android/iOS, use native modules.
|
|
@@ -47,7 +47,9 @@ export async function extractTarBz2(
|
|
|
47
47
|
if (signal) {
|
|
48
48
|
const onAbort = () => {
|
|
49
49
|
try {
|
|
50
|
-
|
|
50
|
+
// Use per-path cancel so aborting this extraction doesn't affect
|
|
51
|
+
// other extractions that may be running in parallel.
|
|
52
|
+
SherpaOnnx.cancelExtractBySourcePath(sourcePath);
|
|
51
53
|
} catch {
|
|
52
54
|
// Ignore cancel errors to avoid crashing on abort.
|
|
53
55
|
}
|
|
@@ -46,7 +46,9 @@ export async function extractTarZst(
|
|
|
46
46
|
if (signal) {
|
|
47
47
|
const onAbort = () => {
|
|
48
48
|
try {
|
|
49
|
-
|
|
49
|
+
// Use per-path cancel so aborting this extraction doesn't affect
|
|
50
|
+
// other extractions that may be running in parallel.
|
|
51
|
+
SherpaOnnx.cancelExtractBySourcePath(sourcePath);
|
|
50
52
|
} catch {
|
|
51
53
|
// Ignore cancel errors to avoid crashing on abort.
|
|
52
54
|
}
|
package/src/extraction/index.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
import { DeviceEventEmitter, Platform } from 'react-native';
|
|
13
13
|
import { readDir, stat, exists } from '@dr.pogodin/react-native-fs';
|
|
14
14
|
import SherpaOnnx from '../NativeSherpaOnnx';
|
|
15
|
-
import { extractTarZst } from '
|
|
16
|
-
import { extractTarBz2 } from '
|
|
15
|
+
import { extractTarZst } from './extractTarZst';
|
|
16
|
+
import { extractTarBz2 } from './extractTarBz2';
|
|
17
17
|
import type {
|
|
18
18
|
BundledArchive,
|
|
19
19
|
ExtractArchiveOptions,
|
|
@@ -228,13 +228,9 @@ async function extractFromAsset(
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
if (signal) {
|
|
231
|
-
const cancel =
|
|
232
|
-
archive.format === 'tar.zst'
|
|
233
|
-
? SherpaOnnx.cancelExtractTarZst
|
|
234
|
-
: SherpaOnnx.cancelExtractTarBz2;
|
|
235
231
|
const onAbort = () => {
|
|
236
232
|
try {
|
|
237
|
-
|
|
233
|
+
SherpaOnnx.cancelExtractBySourcePath(archive.archivePath);
|
|
238
234
|
} catch {
|
|
239
235
|
// ignore
|
|
240
236
|
}
|
package/src/index.tsx
CHANGED
|
@@ -18,6 +18,7 @@ export {
|
|
|
18
18
|
|
|
19
19
|
export { copyFileToContentUri } from './tts';
|
|
20
20
|
|
|
21
|
+
export { getModelLicenses, type ModelLicense } from './licenses';
|
|
21
22
|
// Note: Feature-specific exports are available via subpath imports:
|
|
22
23
|
// - import { createSTT, createStreamingSTT, ... } from 'react-native-sherpa-onnx/stt'
|
|
23
24
|
// - import { createTTS, ... } from 'react-native-sherpa-onnx/tts'
|
package/src/licenses.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import SherpaOnnx from './NativeSherpaOnnx';
|
|
2
|
+
|
|
3
|
+
export interface ModelLicense {
|
|
4
|
+
asset_name: string;
|
|
5
|
+
license_type: string;
|
|
6
|
+
commercial_use: 'yes' | 'no' | 'conditional' | 'restricted' | 'unknown';
|
|
7
|
+
confidence: string;
|
|
8
|
+
detection_source: string;
|
|
9
|
+
license_file: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function getModelLicenses(): Promise<ModelLicense[]> {
|
|
13
|
+
const asrPath = 'model_licenses/asr-models-license-status.csv';
|
|
14
|
+
const qnnPath = 'model_licenses/qnn-asr-models-license-status.csv';
|
|
15
|
+
const ttsPath = 'model_licenses/tts-models-license-status.csv';
|
|
16
|
+
|
|
17
|
+
const results = await Promise.allSettled([
|
|
18
|
+
SherpaOnnx.readAssetFileAsUtf8(asrPath),
|
|
19
|
+
SherpaOnnx.readAssetFileAsUtf8(qnnPath),
|
|
20
|
+
SherpaOnnx.readAssetFileAsUtf8(ttsPath),
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const [asrResult, qnnResult, ttsResult] = results;
|
|
24
|
+
|
|
25
|
+
const licenses: ModelLicense[] = [];
|
|
26
|
+
|
|
27
|
+
if (asrResult.status === 'fulfilled') {
|
|
28
|
+
licenses.push(...parseCsv(asrResult.value));
|
|
29
|
+
} else {
|
|
30
|
+
console.warn(
|
|
31
|
+
`[SherpaOnnx] Failed to load ASR model licenses: ${asrResult.reason}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (qnnResult.status === 'fulfilled') {
|
|
36
|
+
licenses.push(...parseCsv(qnnResult.value));
|
|
37
|
+
} else {
|
|
38
|
+
console.warn(
|
|
39
|
+
`[SherpaOnnx] Failed to load QNN model licenses: ${qnnResult.reason}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (ttsResult.status === 'fulfilled') {
|
|
44
|
+
licenses.push(...parseCsv(ttsResult.value));
|
|
45
|
+
} else {
|
|
46
|
+
console.warn(
|
|
47
|
+
`[SherpaOnnx] Failed to load TTS model licenses: ${ttsResult.reason}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return licenses;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseCsv(csvString: string): ModelLicense[] {
|
|
55
|
+
const lines = csvString.split(/\r?\n/);
|
|
56
|
+
if (lines.length === 0) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The first line is the header
|
|
61
|
+
const headerLine = lines[0];
|
|
62
|
+
if (!headerLine) return [];
|
|
63
|
+
|
|
64
|
+
const headers = headerLine.split(',').map((h) => h.trim());
|
|
65
|
+
|
|
66
|
+
const results: ModelLicense[] = [];
|
|
67
|
+
|
|
68
|
+
for (let i = 1; i < lines.length; i++) {
|
|
69
|
+
const line = lines[i];
|
|
70
|
+
if (!line || line.trim() === '') continue;
|
|
71
|
+
|
|
72
|
+
// The CSV has 6 columns: asset_name, license_type, commercial_use,
|
|
73
|
+
// confidence, detection_source, license_file. The last column
|
|
74
|
+
// (license_file) may itself contain commas (e.g. URLs with query strings),
|
|
75
|
+
// so split into at most 6 parts and join any excess back into the last field.
|
|
76
|
+
const COLUMN_COUNT = 6;
|
|
77
|
+
const rawParts = line.split(',');
|
|
78
|
+
const parts =
|
|
79
|
+
rawParts.length <= COLUMN_COUNT
|
|
80
|
+
? rawParts
|
|
81
|
+
: [
|
|
82
|
+
...rawParts.slice(0, COLUMN_COUNT - 1),
|
|
83
|
+
rawParts.slice(COLUMN_COUNT - 1).join(','),
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
const entry: Record<string, string> = {};
|
|
87
|
+
for (let j = 0; j < headers.length; j++) {
|
|
88
|
+
const header = headers[j];
|
|
89
|
+
if (header) {
|
|
90
|
+
entry[header] = (parts[j] ?? '').trim();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (entry['asset_name']) {
|
|
95
|
+
results.push(entry as unknown as ModelLicense);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return results;
|
|
100
|
+
}
|
package/src/stt/index.ts
CHANGED
|
@@ -40,7 +40,7 @@ function normalizeSttResult(raw: {
|
|
|
40
40
|
*
|
|
41
41
|
* @param modelPath - Model path configuration (asset, file, or auto)
|
|
42
42
|
* @param options - Optional preferInt8 and modelType (default: auto)
|
|
43
|
-
* @returns Object with success, detectedModels (array of { type, modelDir }),
|
|
43
|
+
* @returns Object with success, detectedModels (array of { type, modelDir }), modelType (primary detected type), optional error when success is false, and optionally isHardwareSpecificUnsupported
|
|
44
44
|
* @example
|
|
45
45
|
* ```typescript
|
|
46
46
|
* const path = { type: 'asset' as const, path: 'models/sherpa-onnx-whisper-tiny-en' };
|
|
@@ -55,15 +55,33 @@ export async function detectSttModel(
|
|
|
55
55
|
options?: { preferInt8?: boolean; modelType?: STTModelType }
|
|
56
56
|
): Promise<{
|
|
57
57
|
success: boolean;
|
|
58
|
+
/** Native validation/detect failure. */
|
|
59
|
+
error?: string;
|
|
58
60
|
detectedModels: Array<{ type: string; modelDir: string }>;
|
|
59
61
|
modelType?: string;
|
|
62
|
+
isHardwareSpecificUnsupported?: boolean;
|
|
60
63
|
}> {
|
|
61
64
|
const resolvedPath = await resolveModelPath(modelPath);
|
|
62
|
-
|
|
65
|
+
const raw = await SherpaOnnx.detectSttModel(
|
|
63
66
|
resolvedPath,
|
|
64
67
|
options?.preferInt8,
|
|
65
68
|
options?.modelType
|
|
66
69
|
);
|
|
70
|
+
const err =
|
|
71
|
+
typeof (raw as { error?: unknown }).error === 'string'
|
|
72
|
+
? String((raw as { error: string }).error).trim()
|
|
73
|
+
: '';
|
|
74
|
+
return {
|
|
75
|
+
success: raw.success,
|
|
76
|
+
...(err.length > 0 ? { error: err } : {}),
|
|
77
|
+
...(raw.isHardwareSpecificUnsupported === true
|
|
78
|
+
? { isHardwareSpecificUnsupported: true }
|
|
79
|
+
: {}),
|
|
80
|
+
detectedModels: raw.detectedModels ?? [],
|
|
81
|
+
...(raw.modelType != null && raw.modelType !== ''
|
|
82
|
+
? { modelType: raw.modelType }
|
|
83
|
+
: {}),
|
|
84
|
+
};
|
|
67
85
|
}
|
|
68
86
|
|
|
69
87
|
/**
|
package/src/stt/streaming.ts
CHANGED
|
@@ -82,6 +82,7 @@ function flattenInitOptionsForNative(options: StreamingSttInitOptions): {
|
|
|
82
82
|
provider?: string;
|
|
83
83
|
ruleFsts?: string;
|
|
84
84
|
ruleFars?: string;
|
|
85
|
+
dither?: number;
|
|
85
86
|
blankPenalty?: number;
|
|
86
87
|
debug?: boolean;
|
|
87
88
|
rule1MustContainNonSilence?: boolean;
|
|
@@ -107,6 +108,7 @@ function flattenInitOptionsForNative(options: StreamingSttInitOptions): {
|
|
|
107
108
|
provider: options.provider,
|
|
108
109
|
ruleFsts: options.ruleFsts,
|
|
109
110
|
ruleFars: options.ruleFars,
|
|
111
|
+
dither: options.dither,
|
|
110
112
|
blankPenalty: options.blankPenalty,
|
|
111
113
|
debug: options.debug,
|
|
112
114
|
rule1MustContainNonSilence: ep?.rule1?.mustContainNonSilence,
|
|
@@ -200,6 +202,7 @@ export async function createStreamingSTT(
|
|
|
200
202
|
if (flat.provider !== undefined) nativeOptions.provider = flat.provider;
|
|
201
203
|
if (flat.ruleFsts !== undefined) nativeOptions.ruleFsts = flat.ruleFsts;
|
|
202
204
|
if (flat.ruleFars !== undefined) nativeOptions.ruleFars = flat.ruleFars;
|
|
205
|
+
if (flat.dither !== undefined) nativeOptions.dither = flat.dither;
|
|
203
206
|
if (flat.blankPenalty !== undefined)
|
|
204
207
|
nativeOptions.blankPenalty = flat.blankPenalty;
|
|
205
208
|
if (flat.debug !== undefined) nativeOptions.debug = flat.debug;
|
|
@@ -75,6 +75,11 @@ export interface StreamingSttInitOptions {
|
|
|
75
75
|
ruleFsts?: string;
|
|
76
76
|
/** Path(s) to rule FARs for ITN. */
|
|
77
77
|
ruleFars?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Feature extraction dither. **Android:** applied natively. **iOS:** ignored (C/CXX API has no
|
|
80
|
+
* `dither` on `FeatureConfig`); library default applies.
|
|
81
|
+
*/
|
|
82
|
+
dither?: number;
|
|
78
83
|
/** Blank penalty. */
|
|
79
84
|
blankPenalty?: number;
|
|
80
85
|
/** Enable debug logging. Default: false. */
|
package/src/stt/types.ts
CHANGED
|
@@ -228,7 +228,9 @@ export interface STTInitializeOptions {
|
|
|
228
228
|
ruleFars?: string;
|
|
229
229
|
|
|
230
230
|
/**
|
|
231
|
-
* Dither for feature extraction (Kotlin FeatureConfig.dither). Default
|
|
231
|
+
* Dither for feature extraction (Kotlin `FeatureConfig.dither`). Default: no dither.
|
|
232
|
+
* **Android:** applied natively. **iOS:** ignored — the bundled sherpa-onnx C/CXX API does not
|
|
233
|
+
* expose this field; the native default is used.
|
|
232
234
|
*/
|
|
233
235
|
dither?: number;
|
|
234
236
|
|
package/src/tts/index.ts
CHANGED
|
@@ -49,6 +49,8 @@ function flattenTtsModelOptionsForNative(
|
|
|
49
49
|
? modelOptions.kitten
|
|
50
50
|
: modelType === 'pocket'
|
|
51
51
|
? modelOptions.pocket
|
|
52
|
+
: modelType === 'supertonic'
|
|
53
|
+
? modelOptions.supertonic
|
|
52
54
|
: undefined;
|
|
53
55
|
if (!block)
|
|
54
56
|
return {
|
|
@@ -86,7 +88,7 @@ function flattenTtsModelOptionsForNative(
|
|
|
86
88
|
*
|
|
87
89
|
* @param modelPath - Model path configuration (asset, file, or auto)
|
|
88
90
|
* @param options - Optional modelType (default: 'auto')
|
|
89
|
-
* @returns Object with success, detectedModels (array of { type, modelDir }), modelType (primary detected type), and optionally lexiconLanguageCandidates (language ids for multi-lang Kokoro/Kitten)
|
|
91
|
+
* @returns Object with success, detectedModels (array of { type, modelDir }), modelType (primary detected type), optional error when success is false, and optionally lexiconLanguageCandidates (language ids for multi-lang Kokoro/Kitten)
|
|
90
92
|
* @example
|
|
91
93
|
* ```typescript
|
|
92
94
|
* const result = await detectTtsModel({ type: 'asset', path: 'models/vits-piper-en' });
|
|
@@ -101,13 +103,31 @@ export async function detectTtsModel(
|
|
|
101
103
|
options?: { modelType?: TTSModelType }
|
|
102
104
|
): Promise<{
|
|
103
105
|
success: boolean;
|
|
106
|
+
/** Native validation/detect failure (e.g. missing lexicon for Zipvoice). */
|
|
107
|
+
error?: string;
|
|
104
108
|
detectedModels: Array<{ type: string; modelDir: string }>;
|
|
105
109
|
modelType?: string;
|
|
106
110
|
/** Language ids from detected lexicon files ("default" for lexicon.txt, or e.g. "us-en", "zh" from lexicon-us-en.txt, lexicon-zh.txt). Present for Kokoro/Kitten; use for language selection UI. */
|
|
107
111
|
lexiconLanguageCandidates?: string[];
|
|
108
112
|
}> {
|
|
109
113
|
const resolvedPath = await resolveModelPath(modelPath);
|
|
110
|
-
|
|
114
|
+
const raw = await SherpaOnnx.detectTtsModel(resolvedPath, options?.modelType);
|
|
115
|
+
const err =
|
|
116
|
+
typeof (raw as { error?: unknown }).error === 'string'
|
|
117
|
+
? String((raw as { error: string }).error).trim()
|
|
118
|
+
: '';
|
|
119
|
+
return {
|
|
120
|
+
success: raw.success,
|
|
121
|
+
...(err.length > 0 ? { error: err } : {}),
|
|
122
|
+
detectedModels: raw.detectedModels ?? [],
|
|
123
|
+
...(raw.modelType != null && raw.modelType !== ''
|
|
124
|
+
? { modelType: raw.modelType }
|
|
125
|
+
: {}),
|
|
126
|
+
...(raw.lexiconLanguageCandidates != null &&
|
|
127
|
+
raw.lexiconLanguageCandidates.length > 0
|
|
128
|
+
? { lexiconLanguageCandidates: raw.lexiconLanguageCandidates }
|
|
129
|
+
: {}),
|
|
130
|
+
};
|
|
111
131
|
}
|
|
112
132
|
|
|
113
133
|
/**
|
|
@@ -124,6 +144,16 @@ function toNativeTtsOptions(
|
|
|
124
144
|
if (options.silenceScale !== undefined)
|
|
125
145
|
out.silenceScale = options.silenceScale;
|
|
126
146
|
if (options.referenceAudio != null) {
|
|
147
|
+
const sr = options.referenceAudio.sampleRate;
|
|
148
|
+
if (
|
|
149
|
+
typeof __DEV__ !== 'undefined' &&
|
|
150
|
+
__DEV__ &&
|
|
151
|
+
(!Number.isFinite(sr) || sr <= 0)
|
|
152
|
+
) {
|
|
153
|
+
console.warn(
|
|
154
|
+
'[react-native-sherpa-onnx] TTS referenceAudio.sampleRate must be > 0 for voice cloning (Zipvoice/Pocket).'
|
|
155
|
+
);
|
|
156
|
+
}
|
|
127
157
|
out.referenceAudio = options.referenceAudio.samples;
|
|
128
158
|
out.referenceSampleRate = options.referenceAudio.sampleRate;
|
|
129
159
|
}
|
|
@@ -418,6 +448,7 @@ export type {
|
|
|
418
448
|
TtsKokoroModelOptions,
|
|
419
449
|
TtsKittenModelOptions,
|
|
420
450
|
TtsPocketModelOptions,
|
|
451
|
+
TtsSupertonicModelOptions,
|
|
421
452
|
TtsUpdateOptions,
|
|
422
453
|
TtsGenerationOptions,
|
|
423
454
|
GeneratedAudio,
|
package/src/tts/streaming.ts
CHANGED
|
@@ -52,6 +52,8 @@ function flattenTtsModelOptionsForNative(
|
|
|
52
52
|
? modelOptions.kitten
|
|
53
53
|
: modelType === 'pocket'
|
|
54
54
|
? modelOptions.pocket
|
|
55
|
+
: modelType === 'supertonic'
|
|
56
|
+
? modelOptions.supertonic
|
|
55
57
|
: undefined;
|
|
56
58
|
if (!block)
|
|
57
59
|
return {
|
|
@@ -90,6 +92,16 @@ function toNativeTtsOptions(
|
|
|
90
92
|
if (options.silenceScale !== undefined)
|
|
91
93
|
out.silenceScale = options.silenceScale;
|
|
92
94
|
if (options.referenceAudio != null) {
|
|
95
|
+
const sr = options.referenceAudio.sampleRate;
|
|
96
|
+
if (
|
|
97
|
+
typeof __DEV__ !== 'undefined' &&
|
|
98
|
+
__DEV__ &&
|
|
99
|
+
(!Number.isFinite(sr) || sr <= 0)
|
|
100
|
+
) {
|
|
101
|
+
console.warn(
|
|
102
|
+
'[react-native-sherpa-onnx] TTS referenceAudio.sampleRate must be > 0 for voice cloning (Zipvoice/Pocket).'
|
|
103
|
+
);
|
|
104
|
+
}
|
|
93
105
|
out.referenceAudio = options.referenceAudio.samples;
|
|
94
106
|
out.referenceSampleRate = options.referenceAudio.sampleRate;
|
|
95
107
|
}
|
package/src/tts/types.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { ModelPathConfig } from '../types';
|
|
|
9
9
|
* - 'kitten': KittenTTS models (lightweight, multi-speaker)
|
|
10
10
|
* - 'pocket': Pocket TTS models
|
|
11
11
|
* - 'zipvoice': Zipvoice models (voice cloning capable)
|
|
12
|
+
* - 'supertonic': Supertonic models
|
|
12
13
|
* - 'auto': Auto-detect model type based on files present (default)
|
|
13
14
|
*/
|
|
14
15
|
export type TTSModelType =
|
|
@@ -18,6 +19,7 @@ export type TTSModelType =
|
|
|
18
19
|
| 'kitten'
|
|
19
20
|
| 'pocket'
|
|
20
21
|
| 'zipvoice'
|
|
22
|
+
| 'supertonic'
|
|
21
23
|
| 'auto';
|
|
22
24
|
|
|
23
25
|
/** Runtime list of supported TTS model types. */
|
|
@@ -28,6 +30,7 @@ export const TTS_MODEL_TYPES: readonly TTSModelType[] = [
|
|
|
28
30
|
'kitten',
|
|
29
31
|
'pocket',
|
|
30
32
|
'zipvoice',
|
|
33
|
+
'supertonic',
|
|
31
34
|
'auto',
|
|
32
35
|
] as const;
|
|
33
36
|
|
|
@@ -68,6 +71,11 @@ export interface TtsPocketModelOptions {
|
|
|
68
71
|
// No init-time options in Kotlin OfflineTtsPocketModelConfig; voice cloning is via GenerationConfig at generate time.
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
/** Options for Supertonic models. Applied only when modelType is 'supertonic'. */
|
|
75
|
+
export interface TtsSupertonicModelOptions {
|
|
76
|
+
// No init-time model options exposed by sherpa-onnx currently.
|
|
77
|
+
}
|
|
78
|
+
|
|
71
79
|
/**
|
|
72
80
|
* Model-specific TTS options. Only the block for the actually loaded model type is applied;
|
|
73
81
|
* others are ignored (e.g. vits options have no effect when a kokoro model is loaded).
|
|
@@ -78,6 +86,7 @@ export interface TtsModelOptions {
|
|
|
78
86
|
kokoro?: TtsKokoroModelOptions;
|
|
79
87
|
kitten?: TtsKittenModelOptions;
|
|
80
88
|
pocket?: TtsPocketModelOptions;
|
|
89
|
+
supertonic?: TtsSupertonicModelOptions;
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
/**
|
|
@@ -202,15 +211,16 @@ export interface TtsGenerationOptions {
|
|
|
202
211
|
silenceScale?: number;
|
|
203
212
|
|
|
204
213
|
/**
|
|
205
|
-
* Reference audio for voice cloning (
|
|
206
|
-
*
|
|
207
|
-
*
|
|
214
|
+
* Reference audio for voice cloning (native GenerationConfig / Zipvoice prompt).
|
|
215
|
+
* **Native (iOS & Android):** Requires non-empty samples and `sampleRate > 0`. Used for **Zipvoice** (cloning) and **Pocket** (Mimi encoder).
|
|
216
|
+
* Other model types (vits, matcha, kokoro, kitten) are **rejected** if reference audio is passed.
|
|
217
|
+
* Mono float samples in [-1, 1].
|
|
208
218
|
*/
|
|
209
219
|
referenceAudio?: { samples: number[]; sampleRate: number };
|
|
210
220
|
|
|
211
221
|
/**
|
|
212
|
-
* Transcript
|
|
213
|
-
*
|
|
222
|
+
* Transcript of the reference utterance for **Zipvoice** voice cloning (prompt text); **required** when cloning with Zipvoice (non-empty after trim).
|
|
223
|
+
* **Pocket:** not read by sherpa-onnx native code; optional, e.g. for app metadata only.
|
|
214
224
|
*/
|
|
215
225
|
referenceText?: string;
|
|
216
226
|
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import type { ModelPathConfig } from './types';
|
|
3
3
|
import SherpaOnnx from './NativeSherpaOnnx';
|
|
4
|
+
import { resolveActualModelDir } from './download';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Utility functions for model path handling
|
|
@@ -73,13 +74,33 @@ export function autoModelPath(path: string): ModelPathConfig {
|
|
|
73
74
|
* This handles different path types (asset, file, auto) and returns
|
|
74
75
|
* a platform-specific absolute path that can be used by native code.
|
|
75
76
|
*
|
|
77
|
+
* For type 'file', the path is normalized so that when the given path is an
|
|
78
|
+
* install directory (e.g. with .ready and manifest.json and one model subdir),
|
|
79
|
+
* the returned path is the subdirectory that actually contains the .onnx files.
|
|
80
|
+
* This allows apps that build paths as baseDir/modelId to work without change.
|
|
81
|
+
*
|
|
76
82
|
* @param config - Model path configuration
|
|
77
83
|
* @returns Promise resolving to absolute path usable by native code
|
|
78
84
|
*/
|
|
79
85
|
export async function resolveModelPath(
|
|
80
86
|
config: ModelPathConfig
|
|
81
87
|
): Promise<string> {
|
|
82
|
-
|
|
88
|
+
const path = await SherpaOnnx.resolveModelPath(config);
|
|
89
|
+
if (config.type === 'file') {
|
|
90
|
+
const resolved = await resolveActualModelDir(path);
|
|
91
|
+
// Diagnostic: log so we can tell if /usr/share/espeak-ng-data is due to our path or sherpa-onnx fallback.
|
|
92
|
+
if (__DEV__) {
|
|
93
|
+
console.log(
|
|
94
|
+
'[SherpaOnnx] resolveModelPath(file): native path=',
|
|
95
|
+
path,
|
|
96
|
+
resolved !== path
|
|
97
|
+
? `resolvedActualModelDir=> ${resolved}`
|
|
98
|
+
: '(unchanged)'
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return resolved;
|
|
102
|
+
}
|
|
103
|
+
return path;
|
|
83
104
|
}
|
|
84
105
|
|
|
85
106
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
sherpa-onnx-android-v1.12.
|
|
1
|
+
sherpa-onnx-android-v1.12.31-1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
sherpa-onnx-ios-v1.12.31-1
|