react-native-sherpa-onnx 0.3.8 → 0.4.0

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.
Files changed (134) hide show
  1. package/README.md +20 -5
  2. package/SherpaOnnx.podspec +5 -1
  3. package/android/prebuilt-download.gradle +89 -49
  4. package/android/prebuilt-versions.gradle +1 -1
  5. package/android/src/main/assets/model_licenses/asr-models-license-status.csv +1 -0
  6. package/android/src/main/assets/model_licenses/speech-enhancement-models-license-status.csv +7 -0
  7. package/android/src/main/cpp/CMakeLists.txt +3 -0
  8. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-enhancement-wrapper.cpp +68 -0
  9. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-enhancement-wrapper.h +17 -0
  10. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-enhancement.cpp +119 -0
  11. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.cpp +23 -0
  12. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.h +9 -0
  13. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-stt.cpp +51 -8
  14. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect.h +41 -0
  15. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-stt-wrapper.cpp +5 -0
  16. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-enhancement.cpp +68 -0
  17. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-enhancement.h +30 -0
  18. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-stt.cpp +11 -0
  19. package/android/src/main/cpp/jni/module/sherpa-onnx-module-jni.cpp +21 -0
  20. package/android/src/main/java/com/sherpaonnx/SherpaOnnxArchiveHelper.kt +110 -35
  21. package/android/src/main/java/com/sherpaonnx/SherpaOnnxAssetHelper.kt +6 -0
  22. package/android/src/main/java/com/sherpaonnx/SherpaOnnxEnhancementHelper.kt +377 -0
  23. package/android/src/main/java/com/sherpaonnx/SherpaOnnxExtractionNotificationHelper.kt +102 -0
  24. package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +198 -18
  25. package/android/src/main/java/com/sherpaonnx/SherpaOnnxSttHelper.kt +22 -0
  26. package/ios/Resources/model_licenses/asr-models-license-status.csv +1 -0
  27. package/ios/Resources/model_licenses/speech-enhancement-models-license-status.csv +7 -0
  28. package/ios/SherpaOnnx+Assets.mm +5 -0
  29. package/ios/SherpaOnnx+Enhancement.mm +435 -0
  30. package/ios/SherpaOnnx+STT.mm +13 -1
  31. package/ios/SherpaOnnx.mm +87 -17
  32. package/ios/enhancement/sherpa-onnx-enhancement-wrapper.h +85 -0
  33. package/ios/enhancement/sherpa-onnx-enhancement-wrapper.mm +218 -0
  34. package/ios/model_detect/sherpa-onnx-model-detect-enhancement.mm +92 -0
  35. package/ios/model_detect/sherpa-onnx-model-detect-helper.h +5 -0
  36. package/ios/model_detect/sherpa-onnx-model-detect-helper.mm +23 -0
  37. package/ios/model_detect/sherpa-onnx-model-detect-stt.mm +51 -7
  38. package/ios/model_detect/sherpa-onnx-model-detect.h +33 -0
  39. package/ios/model_detect/sherpa-onnx-validate-enhancement.h +30 -0
  40. package/ios/model_detect/sherpa-onnx-validate-enhancement.mm +69 -0
  41. package/ios/model_detect/sherpa-onnx-validate-stt.mm +11 -0
  42. package/ios/stt/sherpa-onnx-stt-wrapper.h +11 -1
  43. package/ios/stt/sherpa-onnx-stt-wrapper.mm +30 -2
  44. package/ios/tts/sherpa-onnx-tts-wrapper.mm +16 -0
  45. package/lib/module/NativeSherpaOnnx.js.map +1 -1
  46. package/lib/module/download/localModels.js +2 -3
  47. package/lib/module/download/localModels.js.map +1 -1
  48. package/lib/module/download/paths.js +2 -1
  49. package/lib/module/download/paths.js.map +1 -1
  50. package/lib/module/download/postDownloadProcessing.js +17 -4
  51. package/lib/module/download/postDownloadProcessing.js.map +1 -1
  52. package/lib/module/enhancement/index.js +63 -48
  53. package/lib/module/enhancement/index.js.map +1 -1
  54. package/lib/module/enhancement/streaming.js +60 -0
  55. package/lib/module/enhancement/streaming.js.map +1 -0
  56. package/lib/module/enhancement/streamingTypes.js +4 -0
  57. package/lib/module/enhancement/streamingTypes.js.map +1 -0
  58. package/lib/module/enhancement/types.js +4 -0
  59. package/lib/module/enhancement/types.js.map +1 -0
  60. package/lib/module/extraction/extractTarBz2.js +2 -2
  61. package/lib/module/extraction/extractTarBz2.js.map +1 -1
  62. package/lib/module/extraction/extractTarZst.js +2 -2
  63. package/lib/module/extraction/extractTarZst.js.map +1 -1
  64. package/lib/module/extraction/index.js +10 -5
  65. package/lib/module/extraction/index.js.map +1 -1
  66. package/lib/module/licenses.js +9 -3
  67. package/lib/module/licenses.js.map +1 -1
  68. package/lib/module/stt/index.js +4 -2
  69. package/lib/module/stt/index.js.map +1 -1
  70. package/lib/module/stt/streaming.js +2 -1
  71. package/lib/module/stt/streaming.js.map +1 -1
  72. package/lib/module/stt/types.js +3 -1
  73. package/lib/module/stt/types.js.map +1 -1
  74. package/lib/module/tts/index.js +4 -2
  75. package/lib/module/tts/index.js.map +1 -1
  76. package/lib/module/tts/streaming.js +3 -1
  77. package/lib/module/tts/streaming.js.map +1 -1
  78. package/lib/typescript/src/NativeSherpaOnnx.d.ts +70 -9
  79. package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
  80. package/lib/typescript/src/download/localModels.d.ts.map +1 -1
  81. package/lib/typescript/src/download/paths.d.ts +2 -1
  82. package/lib/typescript/src/download/paths.d.ts.map +1 -1
  83. package/lib/typescript/src/download/postDownloadProcessing.d.ts +9 -0
  84. package/lib/typescript/src/download/postDownloadProcessing.d.ts.map +1 -1
  85. package/lib/typescript/src/enhancement/index.d.ts +9 -46
  86. package/lib/typescript/src/enhancement/index.d.ts.map +1 -1
  87. package/lib/typescript/src/enhancement/streaming.d.ts +6 -0
  88. package/lib/typescript/src/enhancement/streaming.d.ts.map +1 -0
  89. package/lib/typescript/src/enhancement/streamingTypes.d.ts +12 -0
  90. package/lib/typescript/src/enhancement/streamingTypes.d.ts.map +1 -0
  91. package/lib/typescript/src/enhancement/types.d.ts +31 -0
  92. package/lib/typescript/src/enhancement/types.d.ts.map +1 -0
  93. package/lib/typescript/src/extraction/extractTarBz2.d.ts +2 -1
  94. package/lib/typescript/src/extraction/extractTarBz2.d.ts.map +1 -1
  95. package/lib/typescript/src/extraction/extractTarZst.d.ts +2 -1
  96. package/lib/typescript/src/extraction/extractTarZst.d.ts.map +1 -1
  97. package/lib/typescript/src/extraction/index.d.ts +1 -1
  98. package/lib/typescript/src/extraction/index.d.ts.map +1 -1
  99. package/lib/typescript/src/extraction/types.d.ts +12 -0
  100. package/lib/typescript/src/extraction/types.d.ts.map +1 -1
  101. package/lib/typescript/src/licenses.d.ts.map +1 -1
  102. package/lib/typescript/src/stt/index.d.ts +1 -1
  103. package/lib/typescript/src/stt/index.d.ts.map +1 -1
  104. package/lib/typescript/src/stt/streaming.d.ts.map +1 -1
  105. package/lib/typescript/src/stt/types.d.ts +16 -1
  106. package/lib/typescript/src/stt/types.d.ts.map +1 -1
  107. package/lib/typescript/src/tts/index.d.ts.map +1 -1
  108. package/lib/typescript/src/tts/streaming.d.ts.map +1 -1
  109. package/package.json +1 -1
  110. package/scripts/ci/check-model-csvs.sh +27 -2
  111. package/scripts/ci/collect_all_sherpa_model_streams.sh +3 -1
  112. package/scripts/ci/collect_one_sherpa_release_stream.sh +3 -1
  113. package/scripts/ci/sherpa_speech_enhancement_model_release_streams.json +13 -0
  114. package/scripts/ci/update_model_license_csv.sh +17 -17
  115. package/src/NativeSherpaOnnx.ts +108 -10
  116. package/src/download/localModels.ts +1 -3
  117. package/src/download/paths.ts +2 -1
  118. package/src/download/postDownloadProcessing.ts +24 -1
  119. package/src/enhancement/index.ts +120 -58
  120. package/src/enhancement/streaming.ts +105 -0
  121. package/src/enhancement/streamingTypes.ts +14 -0
  122. package/src/enhancement/types.ts +36 -0
  123. package/src/extraction/extractTarBz2.ts +7 -2
  124. package/src/extraction/extractTarZst.ts +7 -2
  125. package/src/extraction/index.ts +29 -6
  126. package/src/extraction/types.ts +16 -0
  127. package/src/licenses.ts +13 -2
  128. package/src/stt/index.ts +8 -7
  129. package/src/stt/streaming.ts +7 -1
  130. package/src/stt/types.ts +18 -0
  131. package/src/tts/index.ts +7 -7
  132. package/src/tts/streaming.ts +6 -3
  133. package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -1
  134. package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -1
@@ -0,0 +1,102 @@
1
+ package com.sherpaonnx
2
+
3
+ import android.app.NotificationChannel
4
+ import android.app.NotificationManager
5
+ import android.content.Context
6
+ import android.os.Build
7
+ import android.util.Log
8
+ import androidx.core.app.NotificationCompat
9
+
10
+ /**
11
+ * Android-only progress notification for archive extraction (mirrors background download visibility).
12
+ * Safe no-ops if posting fails (e.g. POST_NOTIFICATIONS denied).
13
+ */
14
+ class SherpaOnnxExtractionNotificationHelper private constructor(
15
+ private val context: Context,
16
+ private val notificationId: Int,
17
+ private val title: String,
18
+ private val baseText: String,
19
+ ) {
20
+ private val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
21
+ @Volatile private var lastBucket: Int = -1
22
+
23
+ companion object {
24
+ private const val TAG = "SherpaOnnxExtractNotif"
25
+ const val CHANNEL_ID = "sherpa_onnx_extraction"
26
+ private val nextNotificationId = java.util.concurrent.atomic.AtomicInteger(9_200_000)
27
+
28
+ private const val DEFAULT_TITLE = "Model extraction"
29
+ private const val DEFAULT_TEXT = "Extracting archive…"
30
+
31
+ fun maybeCreate(
32
+ context: Context,
33
+ showNotificationsEnabled: Boolean?,
34
+ titleOverride: String?,
35
+ textOverride: String?,
36
+ ): SherpaOnnxExtractionNotificationHelper? {
37
+ if (showNotificationsEnabled == false) return null
38
+ val title = titleOverride?.trim()?.takeIf { it.isNotEmpty() } ?: DEFAULT_TITLE
39
+ val text = textOverride?.trim()?.takeIf { it.isNotEmpty() } ?: DEFAULT_TEXT
40
+ val id = nextNotificationId.getAndIncrement()
41
+ return SherpaOnnxExtractionNotificationHelper(context.applicationContext, id, title, text)
42
+ }
43
+
44
+ fun ensureChannel(ctx: Context) {
45
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
46
+ val nm = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
47
+ val existing = nm.getNotificationChannel(CHANNEL_ID)
48
+ if (existing != null) return
49
+ val ch = NotificationChannel(
50
+ CHANNEL_ID,
51
+ "Model extraction",
52
+ NotificationManager.IMPORTANCE_LOW,
53
+ ).apply {
54
+ setShowBadge(false)
55
+ }
56
+ nm.createNotificationChannel(ch)
57
+ }
58
+ }
59
+
60
+ private fun buildProgress(percentInt: Int): NotificationCompat.Builder {
61
+ val p = percentInt.coerceIn(0, 100)
62
+ val line = "$baseText $p%"
63
+ return NotificationCompat.Builder(context, CHANNEL_ID)
64
+ .setSmallIcon(android.R.drawable.stat_sys_download)
65
+ .setContentTitle(title)
66
+ .setContentText(line)
67
+ .setStyle(NotificationCompat.BigTextStyle().bigText(line))
68
+ .setOnlyAlertOnce(true)
69
+ .setPriority(NotificationCompat.PRIORITY_LOW)
70
+ .setOngoing(true)
71
+ .setProgress(100, p, false)
72
+ }
73
+
74
+ fun start() {
75
+ try {
76
+ ensureChannel(context)
77
+ nm.notify(notificationId, buildProgress(0).build())
78
+ } catch (e: Exception) {
79
+ Log.w(TAG, "start: ${e.message}")
80
+ }
81
+ }
82
+
83
+ fun updateProgress(percent: Double) {
84
+ val p = percent.toInt().coerceIn(0, 100)
85
+ val bucket = p / 4
86
+ if (bucket == lastBucket && p != 0 && p != 100) return
87
+ lastBucket = bucket
88
+ try {
89
+ nm.notify(notificationId, buildProgress(p).build())
90
+ } catch (e: Exception) {
91
+ Log.w(TAG, "updateProgress: ${e.message}")
92
+ }
93
+ }
94
+
95
+ fun finish() {
96
+ try {
97
+ nm.cancel(notificationId)
98
+ } catch (e: Exception) {
99
+ Log.w(TAG, "finish: ${e.message}")
100
+ }
101
+ }
102
+ }
@@ -56,6 +56,10 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
56
56
  { instanceId, requestId, message -> emitTtsStreamError(instanceId, requestId, message) },
57
57
  { instanceId, requestId, cancelled -> emitTtsStreamEnd(instanceId, requestId, cancelled) }
58
58
  )
59
+ private val enhancementHelper = SherpaOnnxEnhancementHelper(
60
+ reactApplicationContext,
61
+ { modelDir, modelType -> Companion.nativeDetectEnhancementModel(modelDir, modelType) }
62
+ )
59
63
  private val archiveHelper = SherpaOnnxArchiveHelper()
60
64
  private var pcmCapture: SherpaOnnxPcmCapture? = null
61
65
 
@@ -69,6 +73,7 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
69
73
  pcmCapture = null
70
74
  onlineSttHelper.shutdown()
71
75
  ttsHelper.shutdown()
76
+ enhancementHelper.shutdown()
72
77
  }
73
78
 
74
79
  /**
@@ -293,10 +298,30 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
293
298
  assetHelper.resolveModelPath(config, promise)
294
299
  }
295
300
 
296
- override fun extractTarBz2(sourcePath: String, targetPath: String, force: Boolean, promise: Promise) {
297
- archiveHelper.extractTarBz2(sourcePath, targetPath, force, promise) { bytes, total, percent ->
298
- emitExtractProgress(sourcePath, bytes, total, percent)
299
- }
301
+ override fun extractTarBz2(
302
+ sourcePath: String,
303
+ targetPath: String,
304
+ force: Boolean,
305
+ showNotificationsEnabled: Boolean?,
306
+ notificationTitle: String?,
307
+ notificationText: String?,
308
+ promise: Promise,
309
+ ) {
310
+ val notif = extractionNotificationOrNull(
311
+ showNotificationsEnabled,
312
+ notificationTitle,
313
+ notificationText,
314
+ )
315
+ archiveHelper.extractTarBz2(
316
+ sourcePath,
317
+ targetPath,
318
+ force,
319
+ promise,
320
+ { bytes, total, percent ->
321
+ emitExtractProgress(sourcePath, bytes, total, percent)
322
+ },
323
+ notif,
324
+ )
300
325
  }
301
326
 
302
327
  override fun cancelExtractTarBz2(promise: Promise) {
@@ -304,10 +329,30 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
304
329
  promise.resolve(null)
305
330
  }
306
331
 
307
- override fun extractTarZst(sourcePath: String, targetPath: String, force: Boolean, promise: Promise) {
308
- archiveHelper.extractTarZst(sourcePath, targetPath, force, promise) { bytes, total, percent ->
309
- emitExtractTarZstProgress(sourcePath, bytes, total, percent)
310
- }
332
+ override fun extractTarZst(
333
+ sourcePath: String,
334
+ targetPath: String,
335
+ force: Boolean,
336
+ showNotificationsEnabled: Boolean?,
337
+ notificationTitle: String?,
338
+ notificationText: String?,
339
+ promise: Promise,
340
+ ) {
341
+ val notif = extractionNotificationOrNull(
342
+ showNotificationsEnabled,
343
+ notificationTitle,
344
+ notificationText,
345
+ )
346
+ archiveHelper.extractTarZst(
347
+ sourcePath,
348
+ targetPath,
349
+ force,
350
+ promise,
351
+ { bytes, total, percent ->
352
+ emitExtractTarZstProgress(sourcePath, bytes, total, percent)
353
+ },
354
+ notif,
355
+ )
311
356
  }
312
357
 
313
358
  override fun cancelExtractTarZst(promise: Promise) {
@@ -346,6 +391,20 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
346
391
  eventEmitter.emit("extractTarZstProgress", payload)
347
392
  }
348
393
 
394
+ /** Null when extraction notifications are disabled (`showNotificationsEnabled == false`). */
395
+ private fun extractionNotificationOrNull(
396
+ showNotificationsEnabled: Boolean?,
397
+ notificationTitle: String?,
398
+ notificationText: String?,
399
+ ): SherpaOnnxExtractionNotificationHelper? {
400
+ return SherpaOnnxExtractionNotificationHelper.maybeCreate(
401
+ reactApplicationContext,
402
+ showNotificationsEnabled,
403
+ notificationTitle,
404
+ notificationText,
405
+ )
406
+ }
407
+
349
408
  /**
350
409
  * Resolve asset path - copy from assets to internal storage if needed
351
410
  * Preserves the directory structure from assets (e.g., test_wavs/ stays as test_wavs/)
@@ -1005,6 +1064,103 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
1005
1064
  ttsHelper.unloadTts(instanceId, promise)
1006
1065
  }
1007
1066
 
1067
+ // ==================== Speech Enhancement Methods ====================
1068
+
1069
+ override fun detectEnhancementModel(
1070
+ modelDir: String,
1071
+ modelType: String?,
1072
+ promise: Promise
1073
+ ) {
1074
+ enhancementHelper.detectEnhancementModel(modelDir, modelType, promise)
1075
+ }
1076
+
1077
+ override fun initializeEnhancement(
1078
+ instanceId: String,
1079
+ modelDir: String,
1080
+ modelType: String?,
1081
+ numThreads: Double?,
1082
+ provider: String?,
1083
+ debug: Boolean?,
1084
+ promise: Promise
1085
+ ) {
1086
+ enhancementHelper.initializeEnhancement(
1087
+ instanceId,
1088
+ modelDir,
1089
+ modelType,
1090
+ numThreads,
1091
+ provider,
1092
+ debug,
1093
+ promise
1094
+ )
1095
+ }
1096
+
1097
+ override fun enhanceFile(
1098
+ instanceId: String,
1099
+ inputPath: String,
1100
+ outputPath: String?,
1101
+ promise: Promise
1102
+ ) {
1103
+ enhancementHelper.enhanceFile(instanceId, inputPath, outputPath, promise)
1104
+ }
1105
+
1106
+ override fun enhanceSamples(
1107
+ instanceId: String,
1108
+ samples: ReadableArray,
1109
+ sampleRate: Double,
1110
+ promise: Promise
1111
+ ) {
1112
+ enhancementHelper.enhanceSamples(instanceId, samples, sampleRate, promise)
1113
+ }
1114
+
1115
+ override fun getEnhancementSampleRate(instanceId: String, promise: Promise) {
1116
+ enhancementHelper.getSampleRate(instanceId, promise)
1117
+ }
1118
+
1119
+ override fun unloadEnhancement(instanceId: String, promise: Promise) {
1120
+ enhancementHelper.unloadEnhancement(instanceId, promise)
1121
+ }
1122
+
1123
+ override fun initializeOnlineEnhancement(
1124
+ instanceId: String,
1125
+ modelDir: String,
1126
+ modelType: String?,
1127
+ numThreads: Double?,
1128
+ provider: String?,
1129
+ debug: Boolean?,
1130
+ promise: Promise
1131
+ ) {
1132
+ enhancementHelper.initializeOnlineEnhancement(
1133
+ instanceId,
1134
+ modelDir,
1135
+ modelType,
1136
+ numThreads,
1137
+ provider,
1138
+ debug,
1139
+ promise
1140
+ )
1141
+ }
1142
+
1143
+ override fun feedEnhancementSamples(
1144
+ instanceId: String,
1145
+ samples: ReadableArray,
1146
+ sampleRate: Double,
1147
+ promise: Promise
1148
+ ) {
1149
+ enhancementHelper.feedSamples(instanceId, samples, sampleRate, promise)
1150
+ }
1151
+
1152
+ override fun flushOnlineEnhancement(instanceId: String, promise: Promise) {
1153
+ enhancementHelper.flushOnline(instanceId, promise)
1154
+ }
1155
+
1156
+ override fun resetOnlineEnhancement(instanceId: String, promise: Promise) {
1157
+ enhancementHelper.resetOnline(instanceId, promise)
1158
+ }
1159
+
1160
+ override fun unloadOnlineEnhancement(instanceId: String, promise: Promise) {
1161
+ enhancementHelper.unloadOnline(instanceId, promise)
1162
+ }
1163
+
1008
1164
  /**
1009
1165
  * Save TTS audio samples to a WAV file.
1010
1166
  */
@@ -1101,34 +1257,54 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
1101
1257
  assetPath: String,
1102
1258
  targetPath: String,
1103
1259
  force: Boolean,
1104
- promise: Promise
1260
+ showNotificationsEnabled: Boolean?,
1261
+ notificationTitle: String?,
1262
+ notificationText: String?,
1263
+ promise: Promise,
1105
1264
  ) {
1265
+ val notif = extractionNotificationOrNull(
1266
+ showNotificationsEnabled,
1267
+ notificationTitle,
1268
+ notificationText,
1269
+ )
1106
1270
  archiveHelper.extractTarZstFromAsset(
1107
1271
  reactApplicationContext,
1108
1272
  assetPath,
1109
1273
  targetPath,
1110
1274
  force,
1111
- promise
1112
- ) { bytes, total, percent ->
1113
- emitExtractTarZstProgress(assetPath, bytes, total, percent)
1114
- }
1275
+ promise,
1276
+ { bytes, total, percent ->
1277
+ emitExtractTarZstProgress(assetPath, bytes, total, percent)
1278
+ },
1279
+ notif,
1280
+ )
1115
1281
  }
1116
1282
 
1117
1283
  override fun extractTarBz2FromAsset(
1118
1284
  assetPath: String,
1119
1285
  targetPath: String,
1120
1286
  force: Boolean,
1121
- promise: Promise
1287
+ showNotificationsEnabled: Boolean?,
1288
+ notificationTitle: String?,
1289
+ notificationText: String?,
1290
+ promise: Promise,
1122
1291
  ) {
1292
+ val notif = extractionNotificationOrNull(
1293
+ showNotificationsEnabled,
1294
+ notificationTitle,
1295
+ notificationText,
1296
+ )
1123
1297
  archiveHelper.extractTarBz2FromAsset(
1124
1298
  reactApplicationContext,
1125
1299
  assetPath,
1126
1300
  targetPath,
1127
1301
  force,
1128
- promise
1129
- ) { bytes, total, percent ->
1130
- emitExtractProgress(assetPath, bytes, total, percent)
1131
- }
1302
+ promise,
1303
+ { bytes, total, percent ->
1304
+ emitExtractProgress(assetPath, bytes, total, percent)
1305
+ },
1306
+ notif,
1307
+ )
1132
1308
  }
1133
1309
 
1134
1310
  override fun readAssetFileAsUtf8(assetPath: String, promise: Promise) {
@@ -1182,6 +1358,10 @@ class SherpaOnnxModule(reactContext: ReactApplicationContext) :
1182
1358
  @JvmStatic
1183
1359
  private external fun nativeDetectTtsModel(modelDir: String, modelType: String): HashMap<String, Any>?
1184
1360
 
1361
+ /** Model detection for speech enhancement: returns HashMap with success, error, detectedModels, modelType, paths. */
1362
+ @JvmStatic
1363
+ private external fun nativeDetectEnhancementModel(modelDir: String, modelType: String): HashMap<String, Any>?
1364
+
1185
1365
  /** Convert arbitrary audio file to requested format (e.g. "mp3", "flac", "wav").
1186
1366
  * outputSampleRateHz: for MP3 use 32000/44100/48000, 0 = default 44100. Ignored for WAV/FLAC.
1187
1367
  * Returns empty string on success, or an error message otherwise. Requires FFmpeg prebuilts when called on Android.
@@ -22,6 +22,7 @@ import com.k2fsa.sherpa.onnx.OfflineSenseVoiceModelConfig
22
22
  import com.k2fsa.sherpa.onnx.OfflineZipformerCtcModelConfig
23
23
  import com.k2fsa.sherpa.onnx.OfflineWenetCtcModelConfig
24
24
  import com.k2fsa.sherpa.onnx.OfflineFunAsrNanoModelConfig
25
+ import com.k2fsa.sherpa.onnx.OfflineQwen3AsrModelConfig
25
26
  import com.k2fsa.sherpa.onnx.OfflineMoonshineModelConfig
26
27
  import com.k2fsa.sherpa.onnx.OfflineDolphinModelConfig
27
28
  import com.k2fsa.sherpa.onnx.OfflineFireRedAsrModelConfig
@@ -541,6 +542,10 @@ internal class SherpaOnnxSttHelper(
541
542
  val hasHotwords = fn.hasKey("hotwords") && fn.getString("hotwords")?.isNotBlank() == true
542
543
  parts.add("funasrNano:lang=$lang,hotwords=$hasHotwords")
543
544
  }
545
+ modelOptions.getMap("qwen3Asr")?.let { q ->
546
+ val mnt = if (q.hasKey("maxNewTokens")) q.getInt("maxNewTokens") else null
547
+ parts.add("qwen3Asr:maxNewTokens=$mnt")
548
+ }
544
549
  return parts.joinToString(";").take(200)
545
550
  }
546
551
 
@@ -699,6 +704,23 @@ internal class SherpaOnnxSttHelper(
699
704
  tokens = ""
700
705
  )
701
706
  }
707
+ "qwen3_asr" -> {
708
+ val q3 = modelOptions?.getMap("qwen3Asr")
709
+ OfflineModelConfig(
710
+ qwen3Asr = OfflineQwen3AsrModelConfig(
711
+ convFrontend = path(paths, "qwen3ConvFrontend"),
712
+ encoder = path(paths, "qwen3Encoder"),
713
+ decoder = path(paths, "qwen3Decoder"),
714
+ tokenizer = path(paths, "qwen3Tokenizer"),
715
+ maxTotalLen = if (q3?.hasKey("maxTotalLen") == true) q3.getInt("maxTotalLen") else 512,
716
+ maxNewTokens = if (q3?.hasKey("maxNewTokens") == true) q3.getInt("maxNewTokens") else 128,
717
+ temperature = if (q3?.hasKey("temperature") == true) q3.getDouble("temperature").toFloat() else 1e-6f,
718
+ topP = if (q3?.hasKey("topP") == true) q3.getDouble("topP").toFloat() else 0.8f,
719
+ seed = if (q3?.hasKey("seed") == true) q3.getInt("seed") else 42
720
+ ),
721
+ tokens = ""
722
+ )
723
+ }
702
724
  else -> {
703
725
  val tokens = path(paths, "tokens")
704
726
  when {
@@ -397,6 +397,7 @@ sherpa-onnx-rk3576-streaming-zipformer-en-2023-06-26.tar.bz2,apache-2.0,yes,high
397
397
  sherpa-onnx-rk3568-streaming-zipformer-en-2023-06-26.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/csukuangfj/sherpa-onnx-streaming-zipformer-en-2023-06-26
398
398
  sherpa-onnx-rk3566-streaming-zipformer-en-2023-06-26.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/csukuangfj/sherpa-onnx-streaming-zipformer-en-2023-06-26
399
399
  sherpa-onnx-rk3562-streaming-zipformer-en-2023-06-26.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/csukuangfj/sherpa-onnx-streaming-zipformer-en-2023-06-26
400
+ sherpa-onnx-qwen3-asr-0.6B-int8-2026-03-25.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/Qwen/Qwen3-ASR-0.6B
400
401
  sherpa-onnx-rk3588-streaming-zipformer-small-bilingual-zh-en-2023-02-16.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/csukuangfj/k2fsa-zipformer-bilingual-zh-en-t
401
402
  sherpa-onnx-rk3588-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/csukuangfj/k2fsa-zipformer-bilingual-zh-en-t
402
403
  sherpa-onnx-rk3576-streaming-zipformer-small-bilingual-zh-en-2023-02-16.tar.bz2,apache-2.0,yes,high,manual,https://huggingface.co/csukuangfj/k2fsa-zipformer-bilingual-zh-en-t
@@ -0,0 +1,7 @@
1
+ asset_name,license_type,commercial_use,confidence,detection_source,license_file
2
+ dpdfnet2.onnx,apache-2.0,yes,high,manual,https://huggingface.co/Ceva-IP/DPDFNet/tree/main/onnx
3
+ dpdfnet2_48khz_hr.onnx,apache-2.0,yes,high,manual,https://huggingface.co/Ceva-IP/DPDFNet/tree/main/onnx
4
+ dpdfnet4.onnx,apache-2.0,yes,high,manual,https://huggingface.co/Ceva-IP/DPDFNet/tree/main/onnx
5
+ dpdfnet8.onnx,apache-2.0,yes,high,manual,https://huggingface.co/Ceva-IP/DPDFNet/tree/main/onnx
6
+ dpdfnet_baseline.onnx,apache-2.0,yes,high,manual,https://huggingface.co/Ceva-IP/DPDFNet/tree/main/onnx
7
+ gtcrn_simple.onnx,mit,yes,high,manual,https://github.com/Xiaobin-Rong/gtcrn/tree/main
@@ -319,6 +319,11 @@ static void collectModelFolderNames(NSFileManager *fileManager, NSString *path,
319
319
  return @"tts";
320
320
  }
321
321
 
322
+ BOOL isEnhancement = [name containsString:@"gtcrn"] || [name containsString:@"dpdfnet"];
323
+ if (isEnhancement) {
324
+ return @"enhancement";
325
+ }
326
+
322
327
  return @"unknown";
323
328
  }
324
329