react-native-sherpa-onnx 0.3.7 → 0.3.9
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/README.md +7 -2
- package/SherpaOnnx.podspec +4 -1
- package/android/prebuilt-download.gradle +23 -23
- package/android/src/main/assets/model_licenses/asr-models-license-status.csv +1 -0
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.cpp +23 -0
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.h +9 -0
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-stt.cpp +51 -8
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-tts.cpp +31 -4
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect.h +19 -1
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-stt-wrapper.cpp +5 -0
- 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-stt.cpp +11 -0
- package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-tts.cpp +14 -0
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxArchiveHelper.kt +110 -35
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxExtractionNotificationHelper.kt +102 -0
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +92 -18
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxSttHelper.kt +22 -0
- package/android/src/main/java/com/sherpaonnx/SherpaOnnxTtsHelper.kt +15 -0
- package/ios/Resources/model_licenses/asr-models-license-status.csv +1 -0
- package/ios/SherpaOnnx+STT.mm +13 -1
- package/ios/SherpaOnnx+TTS.mm +1 -0
- package/ios/SherpaOnnx.mm +87 -17
- package/ios/model_detect/sherpa-onnx-model-detect-helper.h +5 -0
- package/ios/model_detect/sherpa-onnx-model-detect-helper.mm +23 -0
- package/ios/model_detect/sherpa-onnx-model-detect-stt.mm +51 -7
- package/ios/model_detect/sherpa-onnx-model-detect-tts.mm +36 -4
- package/ios/model_detect/sherpa-onnx-model-detect.h +19 -1
- package/ios/model_detect/sherpa-onnx-validate-stt.mm +11 -0
- package/ios/model_detect/sherpa-onnx-validate-tts.mm +14 -0
- package/ios/stt/sherpa-onnx-stt-wrapper.h +11 -1
- package/ios/stt/sherpa-onnx-stt-wrapper.mm +30 -2
- package/ios/tts/sherpa-onnx-tts-wrapper.mm +25 -0
- package/lib/module/NativeSherpaOnnx.js.map +1 -1
- package/lib/module/download/ModelDownloadManager.js +1 -1
- package/lib/module/download/ModelDownloadManager.js.map +1 -1
- 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/downloadTask.js +54 -1
- package/lib/module/download/downloadTask.js.map +1 -1
- package/lib/module/download/index.js +1 -1
- package/lib/module/download/index.js.map +1 -1
- package/lib/module/download/postDownloadProcessing.js +17 -4
- package/lib/module/download/postDownloadProcessing.js.map +1 -1
- package/lib/module/download/registry.js +1 -0
- package/lib/module/download/registry.js.map +1 -1
- package/lib/module/extraction/extractTarBz2.js +2 -2
- package/lib/module/extraction/extractTarBz2.js.map +1 -1
- package/lib/module/extraction/extractTarZst.js +2 -2
- package/lib/module/extraction/extractTarZst.js.map +1 -1
- package/lib/module/extraction/index.js +10 -5
- package/lib/module/extraction/index.js.map +1 -1
- package/lib/module/stt/index.js +4 -2
- package/lib/module/stt/index.js.map +1 -1
- package/lib/module/stt/streaming.js +2 -1
- package/lib/module/stt/streaming.js.map +1 -1
- package/lib/module/stt/types.js +3 -1
- package/lib/module/stt/types.js.map +1 -1
- package/lib/module/tts/index.js +5 -3
- package/lib/module/tts/index.js.map +1 -1
- package/lib/module/tts/streaming.js +4 -2
- 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/typescript/src/NativeSherpaOnnx.d.ts +26 -10
- package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
- package/lib/typescript/src/download/ModelDownloadManager.d.ts +2 -1
- package/lib/typescript/src/download/ModelDownloadManager.d.ts.map +1 -1
- 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/downloadTask.d.ts +10 -0
- package/lib/typescript/src/download/downloadTask.d.ts.map +1 -1
- package/lib/typescript/src/download/index.d.ts +2 -2
- package/lib/typescript/src/download/index.d.ts.map +1 -1
- package/lib/typescript/src/download/postDownloadProcessing.d.ts +9 -0
- package/lib/typescript/src/download/postDownloadProcessing.d.ts.map +1 -1
- package/lib/typescript/src/download/registry.d.ts.map +1 -1
- package/lib/typescript/src/extraction/extractTarBz2.d.ts +2 -1
- package/lib/typescript/src/extraction/extractTarBz2.d.ts.map +1 -1
- package/lib/typescript/src/extraction/extractTarZst.d.ts +2 -1
- package/lib/typescript/src/extraction/extractTarZst.d.ts.map +1 -1
- package/lib/typescript/src/extraction/index.d.ts +1 -1
- package/lib/typescript/src/extraction/index.d.ts.map +1 -1
- package/lib/typescript/src/extraction/types.d.ts +12 -0
- package/lib/typescript/src/extraction/types.d.ts.map +1 -1
- package/lib/typescript/src/stt/index.d.ts +1 -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/types.d.ts +16 -1
- package/lib/typescript/src/stt/types.d.ts.map +1 -1
- package/lib/typescript/src/tts/index.d.ts +1 -1
- 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 +6 -1
- package/lib/typescript/src/tts/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/ci/update_model_license_csv.sh +16 -16
- package/src/NativeSherpaOnnx.ts +38 -11
- package/src/download/ModelDownloadManager.ts +2 -0
- package/src/download/background-downloader-types.ts +73 -0
- package/src/download/downloadTask.ts +68 -0
- package/src/download/index.ts +2 -0
- package/src/download/postDownloadProcessing.ts +24 -1
- package/src/download/registry.ts +1 -0
- package/src/extraction/extractTarBz2.ts +7 -2
- package/src/extraction/extractTarZst.ts +7 -2
- package/src/extraction/index.ts +29 -6
- package/src/extraction/types.ts +16 -0
- package/src/stt/index.ts +8 -7
- package/src/stt/streaming.ts +7 -1
- package/src/stt/types.ts +18 -0
- package/src/tts/index.ts +10 -7
- package/src/tts/streaming.ts +8 -3
- package/src/tts/types.ts +9 -0
- package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -1
- package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -1
- package/lib/module/download/background-downloader.d.js +0 -2
- package/lib/module/download/background-downloader.d.js.map +0 -1
- package/src/download/background-downloader.d.ts +0 -43
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# - Uses tree-cache (from asr/tts-models-structure.txt + new downloads) to see if a LICENSE-like
|
|
15
15
|
# path exists — no full extract unless we need file contents for detection.
|
|
16
16
|
# - Downloads the .tar.bz2 only when a license-like path was found and license_type is still empty.
|
|
17
|
-
# - Pipeline: try archive (if applicable)
|
|
17
|
+
# - Pipeline: try archive (if applicable) --> HF/ModelScope fallbacks for eligible assets. If no license
|
|
18
18
|
# is found after all attempts, license_type is set to exhausted (default keyword; override with
|
|
19
19
|
# LICENSE_EXHAUSTED env). You can set exhausted manually after review.
|
|
20
20
|
# - .onnx-only: exhausted (no archive to scan).
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
# asr-models-license-status.csv (default: same directory as --csv). Strip prefix
|
|
31
31
|
# sherpa-onnx-qnn-<soc>-binary-<n>-seconds- from the QNN asset name, then try a few derived filenames
|
|
32
32
|
# (exact, sherpa-onnx-…, and sherpa-onnx-<stem>.tar.bz2 when …-int8.tar.bz2). On match, copy the ASR row’s
|
|
33
|
-
# license fields (not asset_name) onto the QNN asset; on no match
|
|
33
|
+
# license fields (not asset_name) onto the QNN asset; on no match --> exhausted like other dead ends.
|
|
34
34
|
# - Hugging Face: set HF_TOKEN or HUGGINGFACE_HUB_TOKEN (read token is enough for public repos). Anonymous
|
|
35
35
|
# requests from CI often get HTTP 401; without a token README/MODEL_CARD cannot be fetched.
|
|
36
36
|
#
|
|
@@ -566,7 +566,7 @@ for asset_name in "${release_assets[@]}"; do
|
|
|
566
566
|
|
|
567
567
|
if [[ "$asset_name" == *.onnx ]]; then
|
|
568
568
|
set_exhausted "$asset_name"
|
|
569
|
-
echo " $asset_name — .onnx bundle
|
|
569
|
+
echo " $asset_name — .onnx bundle --> license_type=$LICENSE_EXHAUSTED (no archive; skipped next run)"
|
|
570
570
|
continue
|
|
571
571
|
fi
|
|
572
572
|
|
|
@@ -601,15 +601,15 @@ for asset_name in "${release_assets[@]}"; do
|
|
|
601
601
|
|
|
602
602
|
if [[ ${#license_paths[@]} -eq 0 ]]; then
|
|
603
603
|
if try_hf_model_card_fallback "$asset_name"; then
|
|
604
|
-
echo " $asset_name — no license in tree
|
|
604
|
+
echo " $asset_name — no license in tree --> filled from $(log_license_fallback_source "$asset_name") (license_type=${existing_license_type["$asset_name"]})"
|
|
605
605
|
continue
|
|
606
606
|
fi
|
|
607
607
|
if try_qnn_asr_license_fallback "$asset_name"; then
|
|
608
|
-
echo " $asset_name — no license in tree + HF exhausted
|
|
608
|
+
echo " $asset_name — no license in tree + HF exhausted --> QNN mirror from asr row (${_QNN_ASR_MIRROR_MATCHED}) (license_type=${existing_license_type["$asset_name"]})"
|
|
609
609
|
continue
|
|
610
610
|
fi
|
|
611
611
|
set_exhausted "$asset_name"
|
|
612
|
-
echo " $asset_name — no license in tree + fallbacks exhausted
|
|
612
|
+
echo " $asset_name — no license in tree + fallbacks exhausted --> license_type=$LICENSE_EXHAUSTED"
|
|
613
613
|
continue
|
|
614
614
|
fi
|
|
615
615
|
|
|
@@ -624,15 +624,15 @@ for asset_name in "${release_assets[@]}"; do
|
|
|
624
624
|
if ! curl "${_curl_dl[@]}" -o "$archive_path" "$url"; then
|
|
625
625
|
rm -rf "$td"
|
|
626
626
|
if try_hf_model_card_fallback "$asset_name"; then
|
|
627
|
-
echo " $asset_name — download failed
|
|
627
|
+
echo " $asset_name — download failed --> filled from $(log_license_fallback_source "$asset_name") (license_type=${existing_license_type["$asset_name"]})"
|
|
628
628
|
continue
|
|
629
629
|
fi
|
|
630
630
|
if try_qnn_asr_license_fallback "$asset_name"; then
|
|
631
|
-
echo " $asset_name — download failed + HF exhausted
|
|
631
|
+
echo " $asset_name — download failed + HF exhausted --> QNN mirror from asr row (${_QNN_ASR_MIRROR_MATCHED}) (license_type=${existing_license_type["$asset_name"]})"
|
|
632
632
|
continue
|
|
633
633
|
fi
|
|
634
634
|
set_exhausted "$asset_name"
|
|
635
|
-
echo " $asset_name — download failed + fallbacks exhausted
|
|
635
|
+
echo " $asset_name — download failed + fallbacks exhausted --> license_type=$LICENSE_EXHAUSTED"
|
|
636
636
|
continue
|
|
637
637
|
fi
|
|
638
638
|
|
|
@@ -665,15 +665,15 @@ for asset_name in "${release_assets[@]}"; do
|
|
|
665
665
|
if [[ -z "$extracted_text" ]]; then
|
|
666
666
|
rm -rf "$td"
|
|
667
667
|
if try_hf_model_card_fallback "$asset_name"; then
|
|
668
|
-
echo " $asset_name — could not extract license file
|
|
668
|
+
echo " $asset_name — could not extract license file --> filled from $(log_license_fallback_source "$asset_name") (license_type=${existing_license_type["$asset_name"]})"
|
|
669
669
|
continue
|
|
670
670
|
fi
|
|
671
671
|
if try_qnn_asr_license_fallback "$asset_name"; then
|
|
672
|
-
echo " $asset_name — could not extract license + HF exhausted
|
|
672
|
+
echo " $asset_name — could not extract license + HF exhausted --> QNN mirror from asr row (${_QNN_ASR_MIRROR_MATCHED}) (license_type=${existing_license_type["$asset_name"]})"
|
|
673
673
|
continue
|
|
674
674
|
fi
|
|
675
675
|
set_exhausted "$asset_name"
|
|
676
|
-
echo " $asset_name — could not extract license file + fallbacks exhausted
|
|
676
|
+
echo " $asset_name — could not extract license file + fallbacks exhausted --> license_type=$LICENSE_EXHAUSTED"
|
|
677
677
|
continue
|
|
678
678
|
fi
|
|
679
679
|
|
|
@@ -686,15 +686,15 @@ for asset_name in "${release_assets[@]}"; do
|
|
|
686
686
|
|
|
687
687
|
if [[ "$l_res" == "unknown" ]]; then
|
|
688
688
|
if try_hf_model_card_fallback "$asset_name"; then
|
|
689
|
-
echo " $asset_name — archive license text unknown
|
|
689
|
+
echo " $asset_name — archive license text unknown --> filled from $(log_license_fallback_source "$asset_name") (license_type=${existing_license_type["$asset_name"]})"
|
|
690
690
|
continue
|
|
691
691
|
fi
|
|
692
692
|
if try_qnn_asr_license_fallback "$asset_name"; then
|
|
693
|
-
echo " $asset_name — archive text unknown + HF exhausted
|
|
693
|
+
echo " $asset_name — archive text unknown + HF exhausted --> QNN mirror from asr row (${_QNN_ASR_MIRROR_MATCHED}) (license_type=${existing_license_type["$asset_name"]})"
|
|
694
694
|
continue
|
|
695
695
|
fi
|
|
696
696
|
set_exhausted "$asset_name"
|
|
697
|
-
echo " $asset_name — archive text unclassified + fallbacks exhausted
|
|
697
|
+
echo " $asset_name — archive text unclassified + fallbacks exhausted --> license_type=$LICENSE_EXHAUSTED"
|
|
698
698
|
continue
|
|
699
699
|
fi
|
|
700
700
|
|
|
@@ -761,5 +761,5 @@ if [[ -d "$REPO_ROOT/android" && -d "$REPO_ROOT/ios" && -f "$CSV_FILE" ]]; then
|
|
|
761
761
|
if ! same_canonical_path "$CSV_FILE" "$_ios_target"; then
|
|
762
762
|
cp "$CSV_FILE" "$_ios_target"
|
|
763
763
|
fi
|
|
764
|
-
echo "Synced $_bn
|
|
764
|
+
echo "Synced $_bn --> android/src/main/assets/model_licenses/ and ios/Resources/model_licenses/"
|
|
765
765
|
fi
|
package/src/NativeSherpaOnnx.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface Spec extends TurboModule {
|
|
|
21
21
|
* @param instanceId - Unique ID for this engine instance (from createSTT)
|
|
22
22
|
* @param modelDir - Absolute path to model directory
|
|
23
23
|
* @param preferInt8 - Optional: true = prefer int8 models, false = prefer regular models, undefined = try int8 first (default)
|
|
24
|
-
* @param modelType - Optional: explicit model type ('transducer', 'nemo_transducer', 'paraformer', 'nemo_ctc', 'wenet_ctc', 'sense_voice', 'zipformer_ctc', 'whisper', 'funasr_nano', 'fire_red_asr', 'moonshine', 'moonshine_v2', 'dolphin', 'canary', 'omnilingual', 'medasr', 'telespeech_ctc', 'auto'), undefined = auto (default)
|
|
24
|
+
* @param modelType - Optional: explicit model type ('transducer', 'nemo_transducer', 'paraformer', 'nemo_ctc', 'wenet_ctc', 'sense_voice', 'zipformer_ctc', 'whisper', 'funasr_nano', 'qwen3_asr', 'fire_red_asr', 'moonshine', 'moonshine_v2', 'dolphin', 'canary', 'omnilingual', 'medasr', 'telespeech_ctc', 'auto'), undefined = auto (default)
|
|
25
25
|
* @param debug - Optional: enable debug logging in native layer and sherpa-onnx (default: false)
|
|
26
26
|
* @param hotwordsFile - Optional: path to hotwords file (OfflineRecognizerConfig)
|
|
27
27
|
* @param hotwordsScore - Optional: hotwords score (default in Kotlin 1.5)
|
|
@@ -30,10 +30,10 @@ export interface Spec extends TurboModule {
|
|
|
30
30
|
* @param ruleFsts - Optional: path(s) to rule FSTs for ITN (comma-separated)
|
|
31
31
|
* @param ruleFars - Optional: path(s) to rule FARs for ITN (comma-separated)
|
|
32
32
|
* @param dither - Optional: dither for feature extraction. **Android:** applied. **iOS:** ignored (native API does not expose it)
|
|
33
|
-
* @param modelOptions - Optional: model-specific options (whisper, senseVoice, canary, funasrNano). Only the block for the loaded model type is applied.
|
|
33
|
+
* @param modelOptions - Optional: model-specific options (whisper, senseVoice, canary, funasrNano, qwen3Asr). Only the block for the loaded model type is applied.
|
|
34
34
|
* @param modelingUnit - Optional: 'cjkchar' | 'bpe' | 'cjkchar+bpe' for hotwords tokenization (OfflineModelConfig.modelingUnit)
|
|
35
35
|
* @param bpeVocab - Optional: path to BPE vocab file (OfflineModelConfig.bpeVocab), used when modelingUnit is bpe or cjkchar+bpe
|
|
36
|
-
* @returns Object with success boolean
|
|
36
|
+
* @returns Object with success boolean, array of detected models (each with type and modelDir), and optional error when success is false.
|
|
37
37
|
*/
|
|
38
38
|
initializeStt(
|
|
39
39
|
instanceId: string,
|
|
@@ -53,6 +53,8 @@ export interface Spec extends TurboModule {
|
|
|
53
53
|
bpeVocab?: string
|
|
54
54
|
): Promise<{
|
|
55
55
|
success: boolean;
|
|
56
|
+
/** Present when success is false (native structured failure). */
|
|
57
|
+
error?: string;
|
|
56
58
|
detectedModels: Array<{ type: string; modelDir: string }>;
|
|
57
59
|
modelType?: string;
|
|
58
60
|
decodingMethod?: string;
|
|
@@ -131,6 +133,7 @@ export interface Spec extends TurboModule {
|
|
|
131
133
|
* @param instanceId - Unique ID for this engine instance (from createStreamingSTT)
|
|
132
134
|
* @param options - All init options (modelDir, modelType, enableEndpoint, decodingMethod, maxActivePaths, and optional endpoint/rule params).
|
|
133
135
|
* `options.dither`: **Android** only; **iOS** ignores it (native `FeatureConfig` has no dither field).
|
|
136
|
+
* @returns `{ success: true }` on success, or `{ success: false, error?: string }` on structured native failure.
|
|
134
137
|
*/
|
|
135
138
|
initializeOnlineSttWithOptions(
|
|
136
139
|
instanceId: string,
|
|
@@ -160,7 +163,7 @@ export interface Spec extends TurboModule {
|
|
|
160
163
|
rule3MinTrailingSilence?: number;
|
|
161
164
|
rule3MinUtteranceLength?: number;
|
|
162
165
|
}
|
|
163
|
-
): Promise<{ success: boolean }>;
|
|
166
|
+
): Promise<{ success: boolean; error?: string }>;
|
|
164
167
|
|
|
165
168
|
/** Create a new stream for the given OnlineRecognizer instance. */
|
|
166
169
|
createSttStream(
|
|
@@ -238,7 +241,7 @@ export interface Spec extends TurboModule {
|
|
|
238
241
|
* Initialize Text-to-Speech (TTS) with model directory.
|
|
239
242
|
* @param instanceId - Unique ID for this engine instance (from createTTS)
|
|
240
243
|
* @param modelDir - Absolute path to model directory
|
|
241
|
-
* @param modelType - Model type ('vits', 'matcha', 'kokoro', 'kitten', 'pocket', 'zipvoice', 'auto')
|
|
244
|
+
* @param modelType - Model type ('vits', 'matcha', 'kokoro', 'kitten', 'pocket', 'zipvoice', 'supertonic', 'auto')
|
|
242
245
|
* @param numThreads - Number of threads for inference (default: 2)
|
|
243
246
|
* @param debug - Enable debug logging (default: false)
|
|
244
247
|
* @param noiseScale - Optional noise scale (VITS/Matcha)
|
|
@@ -249,7 +252,7 @@ export interface Spec extends TurboModule {
|
|
|
249
252
|
* @param maxNumSentences - Optional max sentences per callback (default: 1)
|
|
250
253
|
* @param silenceScale - Optional silence scale on config (default: 0.2)
|
|
251
254
|
* @param provider - Optional execution provider (e.g. 'cpu', 'coreml', 'xnnpack'; default: 'cpu')
|
|
252
|
-
* @returns Object with success boolean
|
|
255
|
+
* @returns Object with success boolean, array of detected models (each with type and modelDir), sampleRate/numSpeakers on success, and optional error when success is false.
|
|
253
256
|
*/
|
|
254
257
|
initializeTts(
|
|
255
258
|
instanceId: string,
|
|
@@ -267,6 +270,8 @@ export interface Spec extends TurboModule {
|
|
|
267
270
|
provider?: string
|
|
268
271
|
): Promise<{
|
|
269
272
|
success: boolean;
|
|
273
|
+
/** Present when success is false (native structured failure). */
|
|
274
|
+
error?: string;
|
|
270
275
|
detectedModels: Array<{ type: string; modelDir: string }>;
|
|
271
276
|
sampleRate: number;
|
|
272
277
|
numSpeakers: number;
|
|
@@ -299,7 +304,7 @@ export interface Spec extends TurboModule {
|
|
|
299
304
|
* @param noiseScale - Optional noise scale override
|
|
300
305
|
* @param noiseScaleW - Optional noise scale W override
|
|
301
306
|
* @param lengthScale - Optional length scale override
|
|
302
|
-
* @returns Object with success
|
|
307
|
+
* @returns Object with success, detectedModels, sampleRate, numSpeakers on success, and optional error when success is false.
|
|
303
308
|
*/
|
|
304
309
|
updateTtsParams(
|
|
305
310
|
instanceId: string,
|
|
@@ -308,6 +313,8 @@ export interface Spec extends TurboModule {
|
|
|
308
313
|
lengthScale?: number | null
|
|
309
314
|
): Promise<{
|
|
310
315
|
success: boolean;
|
|
316
|
+
/** Present when success is false (native structured failure). */
|
|
317
|
+
error?: string;
|
|
311
318
|
detectedModels: Array<{ type: string; modelDir: string }>;
|
|
312
319
|
sampleRate: number;
|
|
313
320
|
numSpeakers: number;
|
|
@@ -550,11 +557,18 @@ export interface Spec extends TurboModule {
|
|
|
550
557
|
/**
|
|
551
558
|
* Extract a .tar.bz2 archive to a target folder.
|
|
552
559
|
* Returns { success, path } or { success, reason }.
|
|
560
|
+
*
|
|
561
|
+
* **Android:** When `showNotificationsEnabled` is true (default), a system notification shows
|
|
562
|
+
* extraction progress. Optional `notificationTitle` / `notificationText` customize the copy.
|
|
563
|
+
* **iOS:** Notification parameters are accepted but have no effect (no extraction progress notification).
|
|
553
564
|
*/
|
|
554
565
|
extractTarBz2(
|
|
555
566
|
sourcePath: string,
|
|
556
567
|
targetPath: string,
|
|
557
|
-
force: boolean
|
|
568
|
+
force: boolean,
|
|
569
|
+
showNotificationsEnabled?: boolean,
|
|
570
|
+
notificationTitle?: string,
|
|
571
|
+
notificationText?: string
|
|
558
572
|
): Promise<{
|
|
559
573
|
success: boolean;
|
|
560
574
|
path?: string;
|
|
@@ -570,11 +584,16 @@ export interface Spec extends TurboModule {
|
|
|
570
584
|
/**
|
|
571
585
|
* Extract a .tar.zst (or .zst) archive to a target folder.
|
|
572
586
|
* Returns { success, path } or { success, reason }.
|
|
587
|
+
*
|
|
588
|
+
* **Android:** Same notification behavior as `extractTarBz2`. **iOS:** No effect.
|
|
573
589
|
*/
|
|
574
590
|
extractTarZst(
|
|
575
591
|
sourcePath: string,
|
|
576
592
|
targetPath: string,
|
|
577
|
-
force: boolean
|
|
593
|
+
force: boolean,
|
|
594
|
+
showNotificationsEnabled?: boolean,
|
|
595
|
+
notificationTitle?: string,
|
|
596
|
+
notificationText?: string
|
|
578
597
|
): Promise<{
|
|
579
598
|
success: boolean;
|
|
580
599
|
path?: string;
|
|
@@ -601,11 +620,15 @@ export interface Spec extends TurboModule {
|
|
|
601
620
|
/**
|
|
602
621
|
* Extract a .tar.zst archive from Android assets (AssetManager) to a target folder. Android only.
|
|
603
622
|
* Streams from asset; no copy of the archive to disk. Used when PAD pack is APK_ASSETS.
|
|
623
|
+
* Notification options match `extractTarZst` (Android only).
|
|
604
624
|
*/
|
|
605
625
|
extractTarZstFromAsset(
|
|
606
626
|
assetPath: string,
|
|
607
627
|
targetPath: string,
|
|
608
|
-
force: boolean
|
|
628
|
+
force: boolean,
|
|
629
|
+
showNotificationsEnabled?: boolean,
|
|
630
|
+
notificationTitle?: string,
|
|
631
|
+
notificationText?: string
|
|
609
632
|
): Promise<{
|
|
610
633
|
success: boolean;
|
|
611
634
|
path?: string;
|
|
@@ -616,11 +639,15 @@ export interface Spec extends TurboModule {
|
|
|
616
639
|
/**
|
|
617
640
|
* Extract a .tar.bz2 archive from Android assets (AssetManager) to a target folder. Android only.
|
|
618
641
|
* Streams from asset; no copy of the archive to disk. Used when PAD pack is APK_ASSETS.
|
|
642
|
+
* Notification options match `extractTarBz2` (Android only).
|
|
619
643
|
*/
|
|
620
644
|
extractTarBz2FromAsset(
|
|
621
645
|
assetPath: string,
|
|
622
646
|
targetPath: string,
|
|
623
|
-
force: boolean
|
|
647
|
+
force: boolean,
|
|
648
|
+
showNotificationsEnabled?: boolean,
|
|
649
|
+
notificationTitle?: string,
|
|
650
|
+
notificationText?: string
|
|
624
651
|
): Promise<{
|
|
625
652
|
success: boolean;
|
|
626
653
|
path?: string;
|
|
@@ -36,11 +36,13 @@ export {
|
|
|
36
36
|
getDownloadStorageBase,
|
|
37
37
|
} from './localModels';
|
|
38
38
|
export {
|
|
39
|
+
configureModelDownloadBackgroundDownloader,
|
|
39
40
|
downloadModelByCategory,
|
|
40
41
|
getIncompleteDownloads,
|
|
41
42
|
resumeDownload,
|
|
42
43
|
deleteIncompleteDownload,
|
|
43
44
|
} from './downloadTask';
|
|
45
|
+
export type { BackgroundDownloaderSetConfigOptions } from './downloadTask';
|
|
44
46
|
export {
|
|
45
47
|
extractModelByCategory,
|
|
46
48
|
getIncompleteExtractions,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time shim for @kesha-antonov/react-native-background-downloader.
|
|
3
|
+
*
|
|
4
|
+
* The package currently ships TS sources without distributable .d.ts files.
|
|
5
|
+
* We route TS path resolution to this shim so the SDK can typecheck strictly
|
|
6
|
+
* without checking third-party TS internals.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface BackgroundDownloaderNotificationTexts {
|
|
10
|
+
downloadTitle?: string;
|
|
11
|
+
downloadStarting?: string;
|
|
12
|
+
downloadProgress?: string;
|
|
13
|
+
downloadPaused?: string;
|
|
14
|
+
downloadFinished?: string;
|
|
15
|
+
groupTitle?: string;
|
|
16
|
+
groupText?: string | ((count: number) => string);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type BackgroundDownloaderSetConfigOptions = {
|
|
20
|
+
showNotificationsEnabled?: boolean;
|
|
21
|
+
notificationsGrouping?: {
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
mode?: 'individual' | 'summaryOnly';
|
|
24
|
+
texts?: BackgroundDownloaderNotificationTexts;
|
|
25
|
+
};
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
progressInterval?: number;
|
|
28
|
+
progressMinBytes?: number;
|
|
29
|
+
isLogsEnabled?: boolean;
|
|
30
|
+
maxParallelDownloads?: number;
|
|
31
|
+
allowsCellularAccess?: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface DownloadTask {
|
|
35
|
+
id: string;
|
|
36
|
+
start(): void;
|
|
37
|
+
stop(): void;
|
|
38
|
+
pause(): Promise<void>;
|
|
39
|
+
resume(): Promise<void>;
|
|
40
|
+
begin(
|
|
41
|
+
cb: (data: {
|
|
42
|
+
expectedBytes?: number;
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
}) => void
|
|
45
|
+
): DownloadTask;
|
|
46
|
+
progress(
|
|
47
|
+
cb: (data: { bytesDownloaded: number; bytesTotal: number }) => void
|
|
48
|
+
): DownloadTask;
|
|
49
|
+
done(
|
|
50
|
+
cb: (data: {
|
|
51
|
+
location?: string;
|
|
52
|
+
bytesDownloaded: number;
|
|
53
|
+
bytesTotal: number;
|
|
54
|
+
}) => void
|
|
55
|
+
): DownloadTask;
|
|
56
|
+
error(
|
|
57
|
+
cb: (data: { error?: string; errorCode?: number }) => void
|
|
58
|
+
): DownloadTask;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export declare function setConfig(
|
|
62
|
+
options: BackgroundDownloaderSetConfigOptions
|
|
63
|
+
): void;
|
|
64
|
+
|
|
65
|
+
export declare function createDownloadTask(options: {
|
|
66
|
+
id: string;
|
|
67
|
+
url: string;
|
|
68
|
+
destination: string;
|
|
69
|
+
metadata?: Record<string, unknown>;
|
|
70
|
+
}): DownloadTask;
|
|
71
|
+
|
|
72
|
+
export declare function completeHandler(taskId: string): void;
|
|
73
|
+
export declare function getExistingDownloadTasks(): Promise<DownloadTask[]>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import type { BackgroundDownloaderSetConfigOptions } from './background-downloader-types';
|
|
1
3
|
import {
|
|
2
4
|
createDownloadTask,
|
|
3
5
|
completeHandler,
|
|
4
6
|
getExistingDownloadTasks,
|
|
7
|
+
setConfig,
|
|
5
8
|
} from '@kesha-antonov/react-native-background-downloader';
|
|
6
9
|
import {
|
|
7
10
|
exists,
|
|
@@ -41,6 +44,68 @@ function makeDownloadTaskId(category: ModelCategory, id: string): string {
|
|
|
41
44
|
|
|
42
45
|
const activeDownloadTasks = new Map<string, { stop: () => void }>();
|
|
43
46
|
|
|
47
|
+
let androidDownloaderNotificationConfigApplied = false;
|
|
48
|
+
let didWarnConfigFailure = false;
|
|
49
|
+
|
|
50
|
+
function warnBackgroundDownloaderConfigFailure(
|
|
51
|
+
context: string,
|
|
52
|
+
error: unknown
|
|
53
|
+
) {
|
|
54
|
+
if (didWarnConfigFailure) return;
|
|
55
|
+
didWarnConfigFailure = true;
|
|
56
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
57
|
+
console.warn(
|
|
58
|
+
`[Download] Background downloader config failed (${context}): ${reason}`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type { BackgroundDownloaderSetConfigOptions };
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Apply your own `@kesha-antonov/react-native-background-downloader` `setConfig` **before** the first
|
|
66
|
+
* model download. When called, the SDK will **not** overwrite it with built-in defaults on first download.
|
|
67
|
+
*
|
|
68
|
+
* Safe to call at app startup (e.g. `App.tsx`). Other `setConfig` options (e.g. headers) are forwarded
|
|
69
|
+
* where the native module supports them on each platform.
|
|
70
|
+
*/
|
|
71
|
+
export function configureModelDownloadBackgroundDownloader(
|
|
72
|
+
options: BackgroundDownloaderSetConfigOptions
|
|
73
|
+
): void {
|
|
74
|
+
try {
|
|
75
|
+
setConfig(options);
|
|
76
|
+
androidDownloaderNotificationConfigApplied = true;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
// Keep fallback default config enabled if custom config fails.
|
|
79
|
+
warnBackgroundDownloaderConfigFailure('custom', error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Library default is showNotificationsEnabled: false (silent empty FGS notification).
|
|
85
|
+
* Enable visible notifications unless the host app already called `configureModelDownloadBackgroundDownloader`.
|
|
86
|
+
*/
|
|
87
|
+
function ensureAndroidBackgroundDownloaderNotifications() {
|
|
88
|
+
if (androidDownloaderNotificationConfigApplied) return;
|
|
89
|
+
if (Platform.OS !== 'android') return;
|
|
90
|
+
try {
|
|
91
|
+
setConfig({
|
|
92
|
+
showNotificationsEnabled: true,
|
|
93
|
+
notificationsGrouping: {
|
|
94
|
+
enabled: false,
|
|
95
|
+
mode: 'individual',
|
|
96
|
+
texts: {
|
|
97
|
+
downloadTitle: 'Model download',
|
|
98
|
+
downloadStarting: 'Starting download…',
|
|
99
|
+
downloadProgress: 'Downloading… {progress}%',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
androidDownloaderNotificationConfigApplied = true;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
warnBackgroundDownloaderConfigFailure('default', error);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
44
109
|
export async function downloadModelByCategory<T extends ModelMetaBase>(
|
|
45
110
|
category: ModelCategory,
|
|
46
111
|
id: string,
|
|
@@ -103,6 +168,8 @@ export async function downloadModelByCategory<T extends ModelMetaBase>(
|
|
|
103
168
|
throw new Error(`Insufficient disk space: ${diskSpaceCheck.message}`);
|
|
104
169
|
}
|
|
105
170
|
|
|
171
|
+
ensureAndroidBackgroundDownloaderNotifications();
|
|
172
|
+
|
|
106
173
|
const statePath = getDownloadStatePath(category, id);
|
|
107
174
|
|
|
108
175
|
if (opts?.overwrite) {
|
|
@@ -339,6 +406,7 @@ export async function resumeDownload<T extends ModelMetaBase>(
|
|
|
339
406
|
deleteArchiveAfterExtract?: boolean;
|
|
340
407
|
}
|
|
341
408
|
): Promise<DownloadResult> {
|
|
409
|
+
ensureAndroidBackgroundDownloaderNotifications();
|
|
342
410
|
const taskId = makeDownloadTaskId(category, id);
|
|
343
411
|
const existingTasks = await getExistingDownloadTasks();
|
|
344
412
|
const existing = existingTasks.find((t) => t.id === taskId);
|
package/src/download/index.ts
CHANGED
|
@@ -30,8 +30,10 @@ export {
|
|
|
30
30
|
ModelCategory,
|
|
31
31
|
getProtectedModelKeysForBulkDelete,
|
|
32
32
|
purgeDownloadedModelArtifacts,
|
|
33
|
+
configureModelDownloadBackgroundDownloader,
|
|
33
34
|
} from './ModelDownloadManager';
|
|
34
35
|
export type {
|
|
36
|
+
BackgroundDownloaderSetConfigOptions,
|
|
35
37
|
ModelMetaBase,
|
|
36
38
|
TtsModelMeta,
|
|
37
39
|
TtsModelType,
|
|
@@ -43,6 +43,15 @@ export type RunPostDownloadProcessingOptions = {
|
|
|
43
43
|
onChecksumIssue?: (issue: ChecksumIssue) => Promise<boolean>;
|
|
44
44
|
deleteArchiveAfterExtract?: boolean;
|
|
45
45
|
onProgress?: (progress: DownloadProgress) => void;
|
|
46
|
+
/**
|
|
47
|
+
* **Android:** Native extraction progress notification (default true), aligned with the download-manager flow.
|
|
48
|
+
* **iOS:** No effect.
|
|
49
|
+
*/
|
|
50
|
+
showExtractionNotifications?: boolean;
|
|
51
|
+
/** **Android:** Optional notification title (default: SDK/native default title). */
|
|
52
|
+
extractionNotificationTitle?: string;
|
|
53
|
+
/** **Android:** Optional notification body prefix (progress percent is appended natively). */
|
|
54
|
+
extractionNotificationText?: string;
|
|
46
55
|
/** Called to get current list of downloaded models for emitModelsListUpdated. */
|
|
47
56
|
getDownloadedList: () => Promise<ModelMetaBase[]>;
|
|
48
57
|
};
|
|
@@ -63,6 +72,9 @@ export async function runPostDownloadProcessing(
|
|
|
63
72
|
deleteArchiveAfterExtract,
|
|
64
73
|
onProgress,
|
|
65
74
|
getDownloadedList,
|
|
75
|
+
showExtractionNotifications,
|
|
76
|
+
extractionNotificationTitle,
|
|
77
|
+
extractionNotificationText,
|
|
66
78
|
} = options;
|
|
67
79
|
|
|
68
80
|
registerActivePostProcess(category, id);
|
|
@@ -80,6 +92,9 @@ export async function runPostDownloadProcessing(
|
|
|
80
92
|
deleteArchiveAfterExtract,
|
|
81
93
|
onProgress,
|
|
82
94
|
getDownloadedList,
|
|
95
|
+
showExtractionNotifications,
|
|
96
|
+
extractionNotificationTitle,
|
|
97
|
+
extractionNotificationText,
|
|
83
98
|
});
|
|
84
99
|
} finally {
|
|
85
100
|
unregisterActivePostProcess(category, id);
|
|
@@ -102,6 +117,9 @@ async function runPostDownloadProcessingBody(
|
|
|
102
117
|
deleteArchiveAfterExtract,
|
|
103
118
|
onProgress,
|
|
104
119
|
getDownloadedList,
|
|
120
|
+
showExtractionNotifications,
|
|
121
|
+
extractionNotificationTitle,
|
|
122
|
+
extractionNotificationText,
|
|
105
123
|
} = options;
|
|
106
124
|
|
|
107
125
|
const isAborted = () => Boolean(signal?.aborted);
|
|
@@ -164,7 +182,12 @@ async function runPostDownloadProcessingBody(
|
|
|
164
182
|
onProgress?.(progress);
|
|
165
183
|
emitDownloadProgress(category, id, progress);
|
|
166
184
|
},
|
|
167
|
-
signal
|
|
185
|
+
signal,
|
|
186
|
+
{
|
|
187
|
+
showNotificationsEnabled: showExtractionNotifications !== false,
|
|
188
|
+
notificationTitle: extractionNotificationTitle,
|
|
189
|
+
notificationText: extractionNotificationText,
|
|
190
|
+
}
|
|
168
191
|
);
|
|
169
192
|
}
|
|
170
193
|
|
package/src/download/registry.ts
CHANGED
|
@@ -96,6 +96,7 @@ function deriveType(id: string): TtsModelType {
|
|
|
96
96
|
if (lower.includes('kitten')) return 'kitten';
|
|
97
97
|
if (lower.includes('pocket')) return 'pocket';
|
|
98
98
|
if (lower.includes('zipvoice')) return 'zipvoice';
|
|
99
|
+
if (lower.includes('supertonic')) return 'supertonic';
|
|
99
100
|
return 'unknown';
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DeviceEventEmitter } from 'react-native';
|
|
2
2
|
import SherpaOnnx from '../NativeSherpaOnnx';
|
|
3
|
+
import type { ExtractNotificationArgs } from './types';
|
|
3
4
|
|
|
4
5
|
export type ExtractProgressEvent = {
|
|
5
6
|
bytes: number;
|
|
@@ -19,7 +20,8 @@ export async function extractTarBz2(
|
|
|
19
20
|
targetPath: string,
|
|
20
21
|
force = true,
|
|
21
22
|
onProgress?: (event: ExtractProgressEvent) => void,
|
|
22
|
-
signal?: AbortSignal
|
|
23
|
+
signal?: AbortSignal,
|
|
24
|
+
notification?: ExtractNotificationArgs
|
|
23
25
|
): Promise<ExtractResult> {
|
|
24
26
|
let subscription: { remove: () => void } | null = null;
|
|
25
27
|
let removeAbortListener: (() => void) | null = null;
|
|
@@ -62,7 +64,10 @@ export async function extractTarBz2(
|
|
|
62
64
|
const result = await SherpaOnnx.extractTarBz2(
|
|
63
65
|
sourcePath,
|
|
64
66
|
targetPath,
|
|
65
|
-
force
|
|
67
|
+
force,
|
|
68
|
+
notification?.showNotificationsEnabled,
|
|
69
|
+
notification?.notificationTitle,
|
|
70
|
+
notification?.notificationText
|
|
66
71
|
);
|
|
67
72
|
if (!result.success) {
|
|
68
73
|
const message = result.reason || 'Extraction failed';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DeviceEventEmitter } from 'react-native';
|
|
2
2
|
import SherpaOnnx from '../NativeSherpaOnnx';
|
|
3
|
+
import type { ExtractNotificationArgs } from './types';
|
|
3
4
|
|
|
4
5
|
export type ExtractProgressEvent = {
|
|
5
6
|
bytes: number;
|
|
@@ -19,7 +20,8 @@ export async function extractTarZst(
|
|
|
19
20
|
targetPath: string,
|
|
20
21
|
force = true,
|
|
21
22
|
onProgress?: (event: ExtractProgressEvent) => void,
|
|
22
|
-
signal?: AbortSignal
|
|
23
|
+
signal?: AbortSignal,
|
|
24
|
+
notification?: ExtractNotificationArgs
|
|
23
25
|
): Promise<ExtractResult> {
|
|
24
26
|
let subscription: { remove: () => void } | null = null;
|
|
25
27
|
let removeAbortListener: (() => void) | null = null;
|
|
@@ -61,7 +63,10 @@ export async function extractTarZst(
|
|
|
61
63
|
const result = await SherpaOnnx.extractTarZst(
|
|
62
64
|
sourcePath,
|
|
63
65
|
targetPath,
|
|
64
|
-
force
|
|
66
|
+
force,
|
|
67
|
+
notification?.showNotificationsEnabled,
|
|
68
|
+
notification?.notificationTitle,
|
|
69
|
+
notification?.notificationText
|
|
65
70
|
);
|
|
66
71
|
if (!result.success) {
|
|
67
72
|
const message = result.reason || 'Extraction failed';
|