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.
Files changed (228) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +92 -21
  3. package/SherpaOnnx.podspec +3 -0
  4. package/THIRD_PARTY_LICENSES/README.md +62 -0
  5. package/THIRD_PARTY_LICENSES/ffmpeg.txt +502 -0
  6. package/THIRD_PARTY_LICENSES/libarchive.txt +65 -0
  7. package/THIRD_PARTY_LICENSES/nvidia_omla.txt +181 -0
  8. package/THIRD_PARTY_LICENSES/onnxruntime.txt +21 -0
  9. package/THIRD_PARTY_LICENSES/opus.txt +44 -0
  10. package/THIRD_PARTY_LICENSES/sherpa-onnx.txt +201 -0
  11. package/THIRD_PARTY_LICENSES/shine.txt +482 -0
  12. package/THIRD_PARTY_LICENSES/zstd.txt +30 -0
  13. package/android/build.gradle +7 -3
  14. package/android/prebuilt-download.gradle +344 -152
  15. package/android/prebuilt-versions.gradle +1 -1
  16. package/android/src/main/assets/model_licenses/asr-models-license-status.csv +409 -0
  17. package/android/src/main/assets/model_licenses/qnn-asr-models-license-status.csv +695 -0
  18. package/android/src/main/assets/model_licenses/tts-models-license-status.csv +596 -0
  19. package/android/src/main/cpp/CMakeLists.txt +28 -10
  20. package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-helper.cpp +2 -2
  21. package/android/src/main/cpp/jni/audio/sherpa-onnx-audio-convert-jni.cpp +268 -2
  22. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-tts.cpp +37 -6
  23. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect.h +9 -1
  24. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-tts-wrapper.cpp +7 -0
  25. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-tts.cpp +18 -2
  26. package/android/src/main/java/com/sherpaonnx/SherpaOnnxArchiveHelper.kt +40 -10
  27. package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +99 -0
  28. package/android/src/main/java/com/sherpaonnx/SherpaOnnxOnlineSttHelper.kt +4 -1
  29. package/android/src/main/java/com/sherpaonnx/SherpaOnnxTtsHelper.kt +127 -97
  30. package/ios/Resources/model_licenses/asr-models-license-status.csv +409 -0
  31. package/ios/Resources/model_licenses/qnn-asr-models-license-status.csv +695 -0
  32. package/ios/Resources/model_licenses/tts-models-license-status.csv +596 -0
  33. package/ios/SherpaOnnx+OnlineSTT.mm +2 -0
  34. package/ios/SherpaOnnx+PcmLiveStream.mm +2 -29
  35. package/ios/SherpaOnnx+TTS.mm +179 -20
  36. package/ios/SherpaOnnx.mm +54 -0
  37. package/ios/SherpaOnnxAudioConvert.h +10 -0
  38. package/ios/SherpaOnnxAudioConvert.mm +257 -1
  39. package/ios/archive/sherpa-onnx-archive-helper.h +3 -0
  40. package/ios/archive/sherpa-onnx-archive-helper.mm +39 -6
  41. package/ios/model_detect/sherpa-onnx-model-detect-tts.mm +49 -6
  42. package/ios/model_detect/sherpa-onnx-model-detect.h +9 -1
  43. package/ios/model_detect/sherpa-onnx-validate-tts.mm +18 -2
  44. package/ios/online_stt/sherpa-onnx-online-stt-wrapper.h +1 -0
  45. package/ios/online_stt/sherpa-onnx-online-stt-wrapper.mm +4 -0
  46. package/ios/tts/sherpa-onnx-tts-wrapper.h +37 -0
  47. package/ios/tts/sherpa-onnx-tts-wrapper.mm +158 -3
  48. package/lib/module/NativeSherpaOnnx.js.map +1 -1
  49. package/lib/module/audio/index.js +8 -0
  50. package/lib/module/audio/index.js.map +1 -1
  51. package/lib/module/download/ModelDownloadManager.js +10 -929
  52. package/lib/module/download/ModelDownloadManager.js.map +1 -1
  53. package/lib/module/download/activeModelOperations.js +26 -0
  54. package/lib/module/download/activeModelOperations.js.map +1 -0
  55. package/lib/module/download/background-downloader-types.js +2 -0
  56. package/lib/module/download/background-downloader-types.js.map +1 -0
  57. package/lib/module/download/bulkPurge.js +72 -0
  58. package/lib/module/download/bulkPurge.js.map +1 -0
  59. package/lib/module/download/checksumPrompt.js +19 -0
  60. package/lib/module/download/checksumPrompt.js.map +1 -0
  61. package/lib/module/download/constants.js +7 -0
  62. package/lib/module/download/constants.js.map +1 -0
  63. package/lib/module/download/downloadEvents.js +35 -0
  64. package/lib/module/download/downloadEvents.js.map +1 -0
  65. package/lib/module/download/downloadTask.js +438 -0
  66. package/lib/module/download/downloadTask.js.map +1 -0
  67. package/lib/module/download/ensureModel.js +89 -0
  68. package/lib/module/download/ensureModel.js.map +1 -0
  69. package/lib/module/download/index.js +4 -4
  70. package/lib/module/download/index.js.map +1 -1
  71. package/lib/module/download/localModels.js +151 -0
  72. package/lib/module/download/localModels.js.map +1 -0
  73. package/lib/module/download/modelExtraction.js +174 -0
  74. package/lib/module/download/modelExtraction.js.map +1 -0
  75. package/lib/module/download/paths.js +98 -0
  76. package/lib/module/download/paths.js.map +1 -0
  77. package/lib/module/download/postDownloadProcessing.js +206 -0
  78. package/lib/module/download/postDownloadProcessing.js.map +1 -0
  79. package/lib/module/download/protectedModelKeys.js +31 -0
  80. package/lib/module/download/protectedModelKeys.js.map +1 -0
  81. package/lib/module/download/registry.js +268 -0
  82. package/lib/module/download/registry.js.map +1 -0
  83. package/lib/module/download/retry.js +59 -0
  84. package/lib/module/download/retry.js.map +1 -0
  85. package/lib/module/download/types.js +17 -0
  86. package/lib/module/download/types.js.map +1 -0
  87. package/lib/module/download/validation.js +101 -5
  88. package/lib/module/download/validation.js.map +1 -1
  89. package/lib/module/{download → extraction}/extractTarBz2.js +3 -1
  90. package/lib/module/extraction/extractTarBz2.js.map +1 -0
  91. package/lib/module/{download → extraction}/extractTarZst.js +3 -1
  92. package/lib/module/extraction/extractTarZst.js.map +1 -0
  93. package/lib/module/extraction/index.js +3 -4
  94. package/lib/module/extraction/index.js.map +1 -1
  95. package/lib/module/index.js +1 -1
  96. package/lib/module/index.js.map +1 -1
  97. package/lib/module/licenses.js +63 -0
  98. package/lib/module/licenses.js.map +1 -0
  99. package/lib/module/stt/index.js +16 -2
  100. package/lib/module/stt/index.js.map +1 -1
  101. package/lib/module/stt/streaming.js +2 -0
  102. package/lib/module/stt/streaming.js.map +1 -1
  103. package/lib/module/stt/streamingTypes.js.map +1 -1
  104. package/lib/module/stt/types.js.map +1 -1
  105. package/lib/module/tts/index.js +21 -3
  106. package/lib/module/tts/index.js.map +1 -1
  107. package/lib/module/tts/streaming.js +5 -1
  108. package/lib/module/tts/streaming.js.map +1 -1
  109. package/lib/module/tts/types.js +4 -1
  110. package/lib/module/tts/types.js.map +1 -1
  111. package/lib/module/utils.js +16 -1
  112. package/lib/module/utils.js.map +1 -1
  113. package/lib/typescript/src/NativeSherpaOnnx.d.ts +34 -6
  114. package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
  115. package/lib/typescript/src/audio/index.d.ts +10 -0
  116. package/lib/typescript/src/audio/index.d.ts.map +1 -1
  117. package/lib/typescript/src/download/ModelDownloadManager.d.ts +11 -108
  118. package/lib/typescript/src/download/ModelDownloadManager.d.ts.map +1 -1
  119. package/lib/typescript/src/download/activeModelOperations.d.ts +6 -0
  120. package/lib/typescript/src/download/activeModelOperations.d.ts.map +1 -0
  121. package/lib/typescript/src/download/background-downloader-types.d.ts +64 -0
  122. package/lib/typescript/src/download/background-downloader-types.d.ts.map +1 -0
  123. package/lib/typescript/src/download/bulkPurge.d.ts +14 -0
  124. package/lib/typescript/src/download/bulkPurge.d.ts.map +1 -0
  125. package/lib/typescript/src/download/checksumPrompt.d.ts +3 -0
  126. package/lib/typescript/src/download/checksumPrompt.d.ts.map +1 -0
  127. package/lib/typescript/src/download/constants.d.ts +5 -0
  128. package/lib/typescript/src/download/constants.d.ts.map +1 -0
  129. package/lib/typescript/src/download/downloadEvents.d.ts +6 -0
  130. package/lib/typescript/src/download/downloadEvents.d.ts.map +1 -0
  131. package/lib/typescript/src/download/downloadTask.d.ts +30 -0
  132. package/lib/typescript/src/download/downloadTask.d.ts.map +1 -0
  133. package/lib/typescript/src/download/ensureModel.d.ts +26 -0
  134. package/lib/typescript/src/download/ensureModel.d.ts.map +1 -0
  135. package/lib/typescript/src/download/index.d.ts +7 -7
  136. package/lib/typescript/src/download/index.d.ts.map +1 -1
  137. package/lib/typescript/src/download/localModels.d.ts +15 -0
  138. package/lib/typescript/src/download/localModels.d.ts.map +1 -0
  139. package/lib/typescript/src/download/modelExtraction.d.ts +36 -0
  140. package/lib/typescript/src/download/modelExtraction.d.ts.map +1 -0
  141. package/lib/typescript/src/download/paths.d.ts +28 -0
  142. package/lib/typescript/src/download/paths.d.ts.map +1 -0
  143. package/lib/typescript/src/download/postDownloadProcessing.d.ts +19 -0
  144. package/lib/typescript/src/download/postDownloadProcessing.d.ts.map +1 -0
  145. package/lib/typescript/src/download/protectedModelKeys.d.ts +6 -0
  146. package/lib/typescript/src/download/protectedModelKeys.d.ts.map +1 -0
  147. package/lib/typescript/src/download/registry.d.ts +14 -0
  148. package/lib/typescript/src/download/registry.d.ts.map +1 -0
  149. package/lib/typescript/src/download/retry.d.ts +15 -0
  150. package/lib/typescript/src/download/retry.d.ts.map +1 -0
  151. package/lib/typescript/src/download/types.d.ts +96 -0
  152. package/lib/typescript/src/download/types.d.ts.map +1 -0
  153. package/lib/typescript/src/download/validation.d.ts +19 -0
  154. package/lib/typescript/src/download/validation.d.ts.map +1 -1
  155. package/lib/typescript/src/extraction/extractTarBz2.d.ts.map +1 -0
  156. package/lib/typescript/src/extraction/extractTarZst.d.ts.map +1 -0
  157. package/lib/typescript/src/index.d.ts +1 -0
  158. package/lib/typescript/src/index.d.ts.map +1 -1
  159. package/lib/typescript/src/licenses.d.ts +10 -0
  160. package/lib/typescript/src/licenses.d.ts.map +1 -0
  161. package/lib/typescript/src/stt/index.d.ts +4 -1
  162. package/lib/typescript/src/stt/index.d.ts.map +1 -1
  163. package/lib/typescript/src/stt/streaming.d.ts.map +1 -1
  164. package/lib/typescript/src/stt/streamingTypes.d.ts +5 -0
  165. package/lib/typescript/src/stt/streamingTypes.d.ts.map +1 -1
  166. package/lib/typescript/src/stt/types.d.ts +3 -1
  167. package/lib/typescript/src/stt/types.d.ts.map +1 -1
  168. package/lib/typescript/src/tts/index.d.ts +4 -2
  169. package/lib/typescript/src/tts/index.d.ts.map +1 -1
  170. package/lib/typescript/src/tts/streaming.d.ts.map +1 -1
  171. package/lib/typescript/src/tts/types.d.ts +12 -6
  172. package/lib/typescript/src/tts/types.d.ts.map +1 -1
  173. package/lib/typescript/src/utils.d.ts +5 -0
  174. package/lib/typescript/src/utils.d.ts.map +1 -1
  175. package/package.json +6 -1
  176. package/scripts/{check-model-csvs.sh → ci/check-model-csvs.sh} +9 -2
  177. package/scripts/ci/collect_all_sherpa_model_streams.sh +101 -0
  178. package/scripts/ci/collect_one_sherpa_release_stream.sh +189 -0
  179. package/scripts/ci/sherpa_asr_model_release_streams.json +21 -0
  180. package/scripts/ci/sherpa_tts_model_release_streams.json +13 -0
  181. package/scripts/ci/update_model_license_csv.sh +765 -0
  182. package/scripts/setup-ios-framework.sh +14 -11
  183. package/scripts/update_commercial_use.js +73 -0
  184. package/src/NativeSherpaOnnx.ts +37 -6
  185. package/src/audio/index.ts +20 -0
  186. package/src/download/ModelDownloadManager.ts +57 -1343
  187. package/src/download/activeModelOperations.ts +38 -0
  188. package/src/download/background-downloader-types.ts +73 -0
  189. package/src/download/bulkPurge.ts +102 -0
  190. package/src/download/checksumPrompt.ts +25 -0
  191. package/src/download/constants.ts +5 -0
  192. package/src/download/downloadEvents.ts +55 -0
  193. package/src/download/downloadTask.ts +565 -0
  194. package/src/download/ensureModel.ts +124 -0
  195. package/src/download/index.ts +21 -4
  196. package/src/download/localModels.ts +234 -0
  197. package/src/download/modelExtraction.ts +244 -0
  198. package/src/download/paths.ts +134 -0
  199. package/src/download/postDownloadProcessing.ts +292 -0
  200. package/src/download/protectedModelKeys.ts +30 -0
  201. package/src/download/registry.ts +405 -0
  202. package/src/download/retry.ts +76 -0
  203. package/src/download/types.ts +120 -0
  204. package/src/download/validation.ts +114 -8
  205. package/src/{download → extraction}/extractTarBz2.ts +3 -1
  206. package/src/{download → extraction}/extractTarZst.ts +3 -1
  207. package/src/extraction/index.ts +3 -7
  208. package/src/index.tsx +1 -0
  209. package/src/licenses.ts +100 -0
  210. package/src/stt/index.ts +20 -2
  211. package/src/stt/streaming.ts +3 -0
  212. package/src/stt/streamingTypes.ts +5 -0
  213. package/src/stt/types.ts +3 -1
  214. package/src/tts/index.ts +33 -2
  215. package/src/tts/streaming.ts +12 -0
  216. package/src/tts/types.ts +15 -5
  217. package/src/utils.ts +22 -1
  218. package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -1
  219. package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -1
  220. package/android/src/main/cpp/jni/tts/sherpa-onnx-tts-zipvoice-jni.cpp +0 -301
  221. package/android/src/main/java/com/sherpaonnx/ZipvoiceTtsWrapper.kt +0 -187
  222. package/lib/module/download/extractTarBz2.js.map +0 -1
  223. package/lib/module/download/extractTarZst.js.map +0 -1
  224. package/lib/typescript/src/download/extractTarBz2.d.ts.map +0 -1
  225. package/lib/typescript/src/download/extractTarZst.d.ts.map +0 -1
  226. package/scripts/check-qnn-support.sh +0 -78
  227. /package/lib/typescript/src/{download → extraction}/extractTarBz2.d.ts +0 -0
  228. /package/lib/typescript/src/{download → extraction}/extractTarZst.d.ts +0 -0
@@ -1,6 +1,13 @@
1
1
  // Prebuilt download and check logic. Applied after android {} and configurations.
2
2
  // Depends on: sherpaOnnxVersion, ffmpegVersion, libarchiveVersion, ortVersion (from prebuilt-versions.gradle)
3
3
  // and configurations.sherpaOnnxAar, ffmpegAar, libarchiveAar, onnxruntimeAar (from build.gradle).
4
+ //
5
+ // Resolution order per artifact (see docs/PREBUILT_RESOLUTION.md):
6
+ // (1) THIRD_PARTY — prebuilt files under third_party/<bundle>/android/ (no network)
7
+ // (2) LOCAL_SDK — reuse files already in android/src/main/jniLibs + cpp/include, stamp OK
8
+ // (3) MAVEN_AAR — extracted from resolved Gradle AAR configuration
9
+ // (4) GITHUB_RELEASE — downloaded release ZIP (curl) using ANDROID_RELEASE_TAG + GitHub repo
10
+ // (5) ERROR — build failure if artifact still missing
4
11
  // When sherpaOnnxDisableFfmpeg=true (gradle.properties), FFmpeg is not required; see docs/disable-ffmpeg.md.
5
12
  // When sherpaOnnxDisableLibarchive=true (gradle.properties), libarchive is not required; see docs/disable-libarchive.md.
6
13
 
@@ -21,6 +28,12 @@ def jniLibsDir = file("${project.projectDir}/src/main/jniLibs")
21
28
  def sherpaOnnxClassesDir = file("${project.buildDir}/sherpa-onnx-classes")
22
29
  def onnxruntimeClassesDir = file("${project.buildDir}/onnxruntime-classes")
23
30
 
31
+ def thirdPartyDir = file("${project.projectDir.parent}/third_party")
32
+ def thirdPartySherpaDir = new File(thirdPartyDir, "sherpa-onnx-prebuilt/android")
33
+ def thirdPartyFfmpegDir = new File(thirdPartyDir, "ffmpeg_prebuilt/android")
34
+ def thirdPartyLibarchiveDir = new File(thirdPartyDir, "libarchive_prebuilt/android")
35
+ def thirdPartyOrtDir = new File(thirdPartyDir, "onnxruntime_prebuilt/android")
36
+
24
37
  def hasAllFfmpegLibs = {
25
38
  for (abi in requiredAbis) {
26
39
  def dir = new File(jniLibsDir, abi)
@@ -77,6 +90,18 @@ def hasAllOnnxruntimeJniLibs = {
77
90
  return true
78
91
  }
79
92
 
93
+ /** Check whether a base dir has all required .so for all ABIs under <baseDir>/jni/<abi>/. */
94
+ def hasAllLibsUnder = { File baseDir, List<String> requiredSo ->
95
+ for (abi in requiredAbis) {
96
+ def dir = new File(baseDir, "jni/${abi}")
97
+ if (!dir.exists()) return false
98
+ for (soName in requiredSo) {
99
+ if (!new File(dir, soName).exists()) return false
100
+ }
101
+ }
102
+ return true
103
+ }
104
+
80
105
  def getGitHubRepo = {
81
106
  try {
82
107
  def proc = ['git', 'remote', 'get-url', 'origin'].execute(null, project.rootDir)
@@ -96,189 +121,336 @@ def readReleaseTag = { File tagFile ->
96
121
  }
97
122
  }
98
123
 
124
+ /** Which .so files are missing under jniLibs for one ABI (for diagnostics). */
125
+ def listMissingSoInAbi = { File abiDir, List<String> required ->
126
+ if (!abiDir.exists()) return required
127
+ required.findAll { soName -> !new File(abiDir, soName).exists() }
128
+ }
129
+
130
+ /** First ABI dir that is incomplete for the given required list, or null if all OK. */
131
+ def firstAbiWithMissingLibs = { List<String> required ->
132
+ for (abi in requiredAbis) {
133
+ def abiDir = new File(jniLibsDir, abi)
134
+ def missing = listMissingSoInAbi(abiDir, required)
135
+ if (!missing.isEmpty()) return [abi, missing]
136
+ }
137
+ return null
138
+ }
139
+
99
140
  project.tasks.register("downloadNativeLibsIfNeeded") {
100
141
  doLast {
101
142
  def downloadDir = file("${project.buildDir}/prebuilt-downloads")
143
+ def jniLibsHuman = "${project.projectDir}/src/main/jniLibs"
144
+
102
145
  def currentSherpaVersion = project.ext.sherpaOnnxVersion
103
146
  def sherpaVersionFile = new File(downloadDir, "sherpa-onnx-version.txt")
104
147
  def storedSherpaVersion = (sherpaVersionFile.exists() ? sherpaVersionFile.text.trim() : null)
105
- def sherpaNeedsUpdate = !hasAllSherpaLibs() || !hasSherpaHeaders() || storedSherpaVersion == null || storedSherpaVersion != currentSherpaVersion
148
+ def sherpaLibsOk = hasAllSherpaLibs()
149
+ def sherpaHdrsOk = hasSherpaHeaders()
150
+ def sherpaNeedsUpdate = !sherpaLibsOk || !sherpaHdrsOk || storedSherpaVersion == null || storedSherpaVersion != currentSherpaVersion
106
151
 
107
152
  def currentFfmpegVersion = project.ext.ffmpegVersion
108
153
  def ffmpegVersionFile = new File(downloadDir, "ffmpeg-version.txt")
109
154
  def storedFfmpegVersion = (ffmpegVersionFile.exists() ? ffmpegVersionFile.text.trim() : null)
110
- def ffmpegNeedsUpdate = !hasAllFfmpegLibs() || !hasFfmpegHeaders() || storedFfmpegVersion == null || storedFfmpegVersion != currentFfmpegVersion
155
+ def ffmpegLibsOk = hasAllFfmpegLibs()
156
+ def ffmpegHdrsOk = hasFfmpegHeaders()
157
+ def ffmpegNeedsUpdate = !ffmpegLibsOk || !ffmpegHdrsOk || storedFfmpegVersion == null || storedFfmpegVersion != currentFfmpegVersion
111
158
 
112
159
  def currentLibarchiveVersion = project.ext.libarchiveVersion
113
160
  def libarchiveVersionFile = new File(downloadDir, "libarchive-version.txt")
114
161
  def storedLibarchiveVersion = (libarchiveVersionFile.exists() ? libarchiveVersionFile.text.trim() : null)
115
- def libarchiveNeedsUpdate = !hasAllLibarchiveLibs() || !hasLibarchiveHeaders() || storedLibarchiveVersion == null || storedLibarchiveVersion != currentLibarchiveVersion
162
+ def libarchiveLibsOk = hasAllLibarchiveLibs()
163
+ def libarchiveHdrsOk = hasLibarchiveHeaders()
164
+ def libarchiveNeedsUpdate = !libarchiveLibsOk || !libarchiveHdrsOk || storedLibarchiveVersion == null || storedLibarchiveVersion != currentLibarchiveVersion
116
165
 
117
- if (hasAllSherpaLibs() && hasSherpaHeaders() && !sherpaNeedsUpdate) {
118
- println "[sherpa-onnx] Native libs + headers: (1) already present, version ${currentSherpaVersion}"
119
- }
120
- if (sherpaNeedsUpdate && storedSherpaVersion != null && storedSherpaVersion != currentSherpaVersion) {
121
- println "[sherpa-onnx] Version change detected (${storedSherpaVersion} -> ${currentSherpaVersion}), refreshing libs and headers"
122
- }
123
- if (ffmpegNeedsUpdate && storedFfmpegVersion != null && storedFfmpegVersion != currentFfmpegVersion) {
124
- println "[FFmpeg] Version change detected (${storedFfmpegVersion} -> ${currentFfmpegVersion}), refreshing libs and headers"
125
- }
126
- if (libarchiveNeedsUpdate && storedLibarchiveVersion != null && storedLibarchiveVersion != currentLibarchiveVersion) {
127
- println "[libarchive] Version change detected (${storedLibarchiveVersion} -> ${currentLibarchiveVersion}), refreshing libs and headers"
128
- }
166
+ def ortJniOk = hasAllOnnxruntimeJniLibs()
167
+
168
+ println "[prebuilt] Resolution order: (1) THIRD_PARTY (2) LOCAL_SDK (3) MAVEN_AAR (4) GITHUB_RELEASE — see docs/PREBUILT_RESOLUTION.md"
129
169
 
130
- def sherpaUpdatedFromAar = [false]
131
- def ffmpegUpdatedFromAar = [false]
132
- def libarchiveUpdatedFromAar = [false]
170
+ def sherpaResolved = false
171
+ def ffmpegResolved = false
172
+ def libarchiveResolved = false
173
+ def ortJniResolved = ortJniOk
174
+
175
+ // =====================================================================
176
+ // sherpa-onnx: JNI (.so) + C headers
177
+ // =====================================================================
133
178
  if (sherpaNeedsUpdate) {
134
- try {
135
- def aarFiles = project.configurations.sherpaOnnxAar.files
136
- if (!aarFiles.isEmpty()) {
137
- downloadDir.mkdirs()
138
- def aar = aarFiles.iterator().next()
139
- def aarExtractDir = new File(downloadDir, "sherpa-onnx-aar-extract")
140
- if (aarExtractDir.exists()) aarExtractDir.deleteDir()
141
- aarExtractDir.mkdirs()
142
- copy { from zipTree(aar); into aarExtractDir }
143
- requiredAbis.each { abi ->
144
- def aarJniDir = new File(aarExtractDir, "jni/${abi}")
145
- if (aarJniDir.exists()) {
146
- copy { from aarJniDir; into new File(jniLibsDir, abi) }
179
+ // Stage 1: THIRD_PARTY
180
+ def tpJni = hasAllLibsUnder(thirdPartySherpaDir, requiredSherpaOnnxSoFiles)
181
+ def tpHdr = new File(thirdPartySherpaDir, "include/sherpa-onnx/c-api/c-api.h").exists()
182
+ if (tpJni && tpHdr) {
183
+ requiredAbis.each { abi ->
184
+ copy { from new File(thirdPartySherpaDir, "jni/${abi}"); into new File(jniLibsDir, abi) }
185
+ }
186
+ def includeSherpaDir = file("${project.projectDir}/src/main/cpp/include/sherpa-onnx")
187
+ includeSherpaDir.mkdirs()
188
+ copy { from new File(thirdPartySherpaDir, "include/sherpa-onnx"); into includeSherpaDir }
189
+ downloadDir.mkdirs()
190
+ sherpaVersionFile.text = currentSherpaVersion
191
+ sherpaResolved = true
192
+ println "[sherpa-onnx] jniLibs + C headers ................. THIRD_PARTY ${thirdPartySherpaDir}"
193
+ println "[sherpa-onnx] version stamp ...................... written ${sherpaVersionFile.name}=${currentSherpaVersion}"
194
+ }
195
+
196
+ // Stage 3: MAVEN_AAR
197
+ if (!sherpaResolved) {
198
+ try {
199
+ def aarFiles = project.configurations.sherpaOnnxAar.files
200
+ if (!aarFiles.isEmpty()) {
201
+ downloadDir.mkdirs()
202
+ def aar = aarFiles.iterator().next()
203
+ def aarExtractDir = new File(downloadDir, "sherpa-onnx-aar-extract")
204
+ if (aarExtractDir.exists()) aarExtractDir.deleteDir()
205
+ aarExtractDir.mkdirs()
206
+ copy { from zipTree(aar); into aarExtractDir }
207
+ requiredAbis.each { abi ->
208
+ def aarJniDir = new File(aarExtractDir, "jni/${abi}")
209
+ if (aarJniDir.exists()) {
210
+ copy { from aarJniDir; into new File(jniLibsDir, abi) }
211
+ }
147
212
  }
213
+ def includeSherpaDir = file("${project.projectDir}/src/main/cpp/include/sherpa-onnx")
214
+ def aarCapiDir = new File(aarExtractDir, "c-api")
215
+ def copiedHeaders = false
216
+ if (aarCapiDir.exists()) {
217
+ includeSherpaDir.mkdirs()
218
+ copy { from fileTree(aarExtractDir) { include 'c-api/**' }; into includeSherpaDir }
219
+ copiedHeaders = true
220
+ }
221
+ downloadDir.mkdirs()
222
+ sherpaVersionFile.text = currentSherpaVersion
223
+ sherpaResolved = true
224
+ println "[sherpa-onnx] jniLibs (*.so per ABI) .............. MAVEN_AAR ${aar.name}"
225
+ println "[sherpa-onnx] install: jni/<abi>/*.so → ${jniLibsHuman}/<abi>/"
226
+ println "[sherpa-onnx] C headers (sherpa-onnx) ............. ${copiedHeaders ? 'MAVEN_AAR c-api/** → ' + includeSherpaDir : 'unchanged (no c-api/ in AAR; existing tree kept)'}"
227
+ println "[sherpa-onnx] version stamp ...................... written ${sherpaVersionFile.name}=${currentSherpaVersion}"
228
+ } else {
229
+ println "[sherpa-onnx] MAVEN_AAR: sherpaOnnxAar empty → trying GITHUB_RELEASE"
148
230
  }
149
- def includeSherpaDir = file("${project.projectDir}/src/main/cpp/include/sherpa-onnx")
150
- def aarCapiDir = new File(aarExtractDir, "c-api")
151
- if (aarCapiDir.exists()) {
152
- includeSherpaDir.mkdirs()
153
- copy { from fileTree(aarExtractDir) { include 'c-api/**' }; into includeSherpaDir }
154
- println "Extracted sherpa-onnx C-API headers from Maven AAR"
155
- }
156
- downloadDir.mkdirs()
157
- sherpaVersionFile.text = currentSherpaVersion
158
- sherpaUpdatedFromAar[0] = true
159
- println "[sherpa-onnx] Native libs + headers: (2) Maven AAR (${aar.name})"
231
+ } catch (Exception e) {
232
+ println "[sherpa-onnx] MAVEN_AAR failed: ${e.message} → trying GITHUB_RELEASE"
160
233
  }
161
- } catch (Exception e) {
162
- println "Could not resolve sherpa-onnx Maven AAR: ${e.message}"
163
234
  }
235
+ } else {
236
+ sherpaResolved = true
237
+ println "[sherpa-onnx] jniLibs + C headers ................. LOCAL_SDK version=${currentSherpaVersion}"
164
238
  }
165
239
 
166
- if (!sherpaOnnxDisableFfmpeg && ffmpegNeedsUpdate) {
167
- try {
168
- def aarFiles = project.configurations.ffmpegAar.files
169
- if (!aarFiles.isEmpty()) {
170
- downloadDir.mkdirs()
171
- def aar = aarFiles.iterator().next()
172
- def aarExtractDir = new File(downloadDir, "ffmpeg-aar-extract")
173
- if (aarExtractDir.exists()) aarExtractDir.deleteDir()
174
- aarExtractDir.mkdirs()
175
- copy { from zipTree(aar); into aarExtractDir }
176
- requiredAbis.each { abi ->
177
- def aarJniDir = new File(aarExtractDir, "jni/${abi}")
178
- if (aarJniDir.exists()) {
179
- copy { from aarJniDir; into new File(jniLibsDir, abi) }
240
+ // =====================================================================
241
+ // FFmpeg: JNI (.so) + C headers
242
+ // =====================================================================
243
+ if (sherpaOnnxDisableFfmpeg) {
244
+ ffmpegResolved = true
245
+ println "[FFmpeg] .................................... skipped (sherpaOnnxDisableFfmpeg=true)"
246
+ } else if (ffmpegNeedsUpdate) {
247
+ // Stage 1: THIRD_PARTY
248
+ def tpJni = hasAllLibsUnder(thirdPartyFfmpegDir, requiredFfmpegSoFiles)
249
+ def tpHdr = new File(thirdPartyFfmpegDir, "include/libavcodec/avcodec.h").exists()
250
+ if (tpJni && tpHdr) {
251
+ requiredAbis.each { abi ->
252
+ copy { from new File(thirdPartyFfmpegDir, "jni/${abi}"); into new File(jniLibsDir, abi) }
253
+ }
254
+ def ffmpegIncludeDir = file("${project.projectDir}/src/main/cpp/include/ffmpeg")
255
+ ffmpegIncludeDir.mkdirs()
256
+ copy { from new File(thirdPartyFfmpegDir, "include"); into ffmpegIncludeDir }
257
+ downloadDir.mkdirs()
258
+ ffmpegVersionFile.text = currentFfmpegVersion
259
+ ffmpegResolved = true
260
+ println "[FFmpeg] jniLibs + C headers ...................... THIRD_PARTY ${thirdPartyFfmpegDir}"
261
+ println "[FFmpeg] version stamp .......................... written ${ffmpegVersionFile.name}=${currentFfmpegVersion}"
262
+ }
263
+
264
+ // Stage 3: MAVEN_AAR
265
+ if (!ffmpegResolved) {
266
+ try {
267
+ def aarFiles = project.configurations.ffmpegAar.files
268
+ if (!aarFiles.isEmpty()) {
269
+ downloadDir.mkdirs()
270
+ def aar = aarFiles.iterator().next()
271
+ def aarExtractDir = new File(downloadDir, "ffmpeg-aar-extract")
272
+ if (aarExtractDir.exists()) aarExtractDir.deleteDir()
273
+ aarExtractDir.mkdirs()
274
+ copy { from zipTree(aar); into aarExtractDir }
275
+ requiredAbis.each { abi ->
276
+ def aarJniDir = new File(aarExtractDir, "jni/${abi}")
277
+ if (aarJniDir.exists()) {
278
+ copy { from aarJniDir; into new File(jniLibsDir, abi) }
279
+ }
180
280
  }
281
+ def ffmpegIncludeDir = file("${project.projectDir}/src/main/cpp/include/ffmpeg")
282
+ def aarIncludeDir = new File(aarExtractDir, "include")
283
+ def copiedHdr = false
284
+ if (aarIncludeDir.exists()) {
285
+ ffmpegIncludeDir.mkdirs()
286
+ copy { from aarIncludeDir; into ffmpegIncludeDir }
287
+ copiedHdr = true
288
+ }
289
+ downloadDir.mkdirs()
290
+ ffmpegVersionFile.text = currentFfmpegVersion
291
+ ffmpegResolved = true
292
+ println "[FFmpeg] jniLibs .................................. MAVEN_AAR ${aar.name}"
293
+ println "[FFmpeg] install: jni/<abi>/*.so → ${jniLibsHuman}/<abi>/"
294
+ println "[FFmpeg] C headers ................................ ${copiedHdr ? 'MAVEN_AAR include/** → ' + ffmpegIncludeDir : 'unchanged (no include/ in AAR)'}"
295
+ println "[FFmpeg] version stamp ............................ written ${ffmpegVersionFile.name}=${currentFfmpegVersion}"
296
+ } else {
297
+ println "[FFmpeg] MAVEN_AAR: ffmpegAar empty → trying GITHUB_RELEASE"
181
298
  }
182
- def ffmpegIncludeDir = file("${project.projectDir}/src/main/cpp/include/ffmpeg")
183
- def aarIncludeDir = new File(aarExtractDir, "include")
184
- if (aarIncludeDir.exists()) {
185
- ffmpegIncludeDir.mkdirs()
186
- copy { from aarIncludeDir; into ffmpegIncludeDir }
187
- println "Extracted FFmpeg headers from Maven AAR"
188
- }
189
- downloadDir.mkdirs()
190
- ffmpegVersionFile.text = currentFfmpegVersion
191
- ffmpegUpdatedFromAar[0] = true
192
- println "[FFmpeg] Native libs + headers: (2) Maven AAR (${aar.name})"
299
+ } catch (Exception e) {
300
+ println "[FFmpeg] MAVEN_AAR failed: ${e.message} → trying GITHUB_RELEASE"
193
301
  }
194
- } catch (Exception e) {
195
- println "Could not resolve FFmpeg Maven AAR: ${e.message}"
196
302
  }
303
+ } else {
304
+ ffmpegResolved = true
305
+ println "[FFmpeg] jniLibs + C headers ........................ LOCAL_SDK version=${currentFfmpegVersion}"
197
306
  }
198
307
 
199
- if (!sherpaOnnxDisableLibarchive && libarchiveNeedsUpdate) {
200
- try {
201
- def aarFiles = project.configurations.libarchiveAar.files
202
- if (!aarFiles.isEmpty()) {
203
- downloadDir.mkdirs()
204
- def aar = aarFiles.iterator().next()
205
- def aarExtractDir = new File(downloadDir, "libarchive-aar-extract")
206
- if (aarExtractDir.exists()) aarExtractDir.deleteDir()
207
- aarExtractDir.mkdirs()
208
- copy { from zipTree(aar); into aarExtractDir }
209
- requiredAbis.each { abi ->
210
- def aarJniDir = new File(aarExtractDir, "jni/${abi}")
211
- if (aarJniDir.exists()) {
212
- copy { from aarJniDir; into new File(jniLibsDir, abi) }
308
+ // =====================================================================
309
+ // libarchive: JNI (.so) + C headers
310
+ // =====================================================================
311
+ if (sherpaOnnxDisableLibarchive) {
312
+ libarchiveResolved = true
313
+ println "[libarchive] .............................. skipped (sherpaOnnxDisableLibarchive=true)"
314
+ } else if (libarchiveNeedsUpdate) {
315
+ // Stage 1: THIRD_PARTY
316
+ def tpJni = hasAllLibsUnder(thirdPartyLibarchiveDir, requiredLibarchiveSoFiles)
317
+ def tpHdr = new File(thirdPartyLibarchiveDir, "include/archive.h").exists()
318
+ if (tpJni && tpHdr) {
319
+ requiredAbis.each { abi ->
320
+ copy { from new File(thirdPartyLibarchiveDir, "jni/${abi}"); into new File(jniLibsDir, abi) }
321
+ }
322
+ def libarchiveIncludeDir = file("${project.projectDir}/src/main/cpp/include/libarchive")
323
+ libarchiveIncludeDir.mkdirs()
324
+ copy { from new File(thirdPartyLibarchiveDir, "include"); into libarchiveIncludeDir }
325
+ downloadDir.mkdirs()
326
+ libarchiveVersionFile.text = currentLibarchiveVersion
327
+ libarchiveResolved = true
328
+ println "[libarchive] jniLibs + C headers ..................... THIRD_PARTY ${thirdPartyLibarchiveDir}"
329
+ println "[libarchive] version stamp .......................... written ${libarchiveVersionFile.name}=${currentLibarchiveVersion}"
330
+ }
331
+
332
+ // Stage 3: MAVEN_AAR
333
+ if (!libarchiveResolved) {
334
+ try {
335
+ def aarFiles = project.configurations.libarchiveAar.files
336
+ if (!aarFiles.isEmpty()) {
337
+ downloadDir.mkdirs()
338
+ def aar = aarFiles.iterator().next()
339
+ def aarExtractDir = new File(downloadDir, "libarchive-aar-extract")
340
+ if (aarExtractDir.exists()) aarExtractDir.deleteDir()
341
+ aarExtractDir.mkdirs()
342
+ copy { from zipTree(aar); into aarExtractDir }
343
+ requiredAbis.each { abi ->
344
+ def aarJniDir = new File(aarExtractDir, "jni/${abi}")
345
+ if (aarJniDir.exists()) {
346
+ copy { from aarJniDir; into new File(jniLibsDir, abi) }
347
+ }
213
348
  }
349
+ def libarchiveIncludeDir = file("${project.projectDir}/src/main/cpp/include/libarchive")
350
+ def aarIncludeDir = new File(aarExtractDir, "include")
351
+ def copiedHdr = false
352
+ if (aarIncludeDir.exists()) {
353
+ libarchiveIncludeDir.mkdirs()
354
+ copy { from aarIncludeDir; into libarchiveIncludeDir }
355
+ copiedHdr = true
356
+ }
357
+ downloadDir.mkdirs()
358
+ libarchiveVersionFile.text = currentLibarchiveVersion
359
+ libarchiveResolved = true
360
+ println "[libarchive] jniLibs .............................. MAVEN_AAR ${aar.name}"
361
+ println "[libarchive] install: jni/<abi>/*.so → ${jniLibsHuman}/<abi>/"
362
+ println "[libarchive] C headers ............................ ${copiedHdr ? 'MAVEN_AAR include/** → ' + libarchiveIncludeDir : 'unchanged (no include/ in AAR)'}"
363
+ println "[libarchive] version stamp ........................ written ${libarchiveVersionFile.name}=${currentLibarchiveVersion}"
364
+ } else {
365
+ println "[libarchive] MAVEN_AAR: libarchiveAar empty → trying GITHUB_RELEASE"
214
366
  }
215
- def libarchiveIncludeDir = file("${project.projectDir}/src/main/cpp/include/libarchive")
216
- def aarIncludeDir = new File(aarExtractDir, "include")
217
- if (aarIncludeDir.exists()) {
218
- libarchiveIncludeDir.mkdirs()
219
- copy { from aarIncludeDir; into libarchiveIncludeDir }
220
- println "Extracted libarchive headers from Maven AAR"
221
- }
222
- downloadDir.mkdirs()
223
- libarchiveVersionFile.text = currentLibarchiveVersion
224
- libarchiveUpdatedFromAar[0] = true
225
- println "[libarchive] Native libs + headers: (2) Maven AAR (${aar.name})"
367
+ } catch (Exception e) {
368
+ println "[libarchive] MAVEN_AAR failed: ${e.message} → trying GITHUB_RELEASE"
226
369
  }
227
- } catch (Exception e) {
228
- println "Could not resolve libarchive Maven AAR: ${e.message}"
229
370
  }
371
+ } else {
372
+ libarchiveResolved = true
373
+ println "[libarchive] jniLibs + C headers ....................... LOCAL_SDK version=${currentLibarchiveVersion}"
230
374
  }
231
375
 
232
- // onnxruntime AAR: extract only libonnxruntime4j_jni.so (the Java↔C bridge)
233
- // into jniLibs. We do NOT extract libonnxruntime.so from this AAR because
234
- // jniLibs already has it from the sherpa-onnx prebuilts avoids duplicates.
235
- if (!hasAllOnnxruntimeJniLibs()) {
236
- try {
237
- def aarFiles = project.configurations.onnxruntimeAar.files
238
- if (!aarFiles.isEmpty()) {
239
- downloadDir.mkdirs()
240
- def aar = aarFiles.iterator().next()
241
- def aarExtractDir = new File(downloadDir, "onnxruntime-aar-extract")
242
- if (aarExtractDir.exists()) aarExtractDir.deleteDir()
243
- aarExtractDir.mkdirs()
244
- copy { from zipTree(aar); into aarExtractDir }
245
- requiredAbis.each { abi ->
246
- def aarJniDir = new File(aarExtractDir, "jni/${abi}")
247
- if (aarJniDir.exists()) {
248
- copy {
249
- from aarJniDir
250
- include 'libonnxruntime4j_jni.so'
251
- into new File(jniLibsDir, abi)
376
+ // =====================================================================
377
+ // onnxruntime: JNI bridge only (libonnxruntime4j_jni.so)
378
+ // libonnxruntime.so comes from sherpa-onnx prebuilts; not extracted here.
379
+ // =====================================================================
380
+ if (!ortJniOk) {
381
+ // Stage 1: THIRD_PARTY
382
+ def tpJni = hasAllLibsUnder(thirdPartyOrtDir, requiredOnnxruntimeJniSoFiles)
383
+ if (tpJni) {
384
+ requiredAbis.each { abi ->
385
+ copy {
386
+ from new File(thirdPartyOrtDir, "jni/${abi}")
387
+ include 'libonnxruntime4j_jni.so'
388
+ into new File(jniLibsDir, abi)
389
+ }
390
+ }
391
+ ortJniResolved = true
392
+ println "[onnxruntime] libonnxruntime4j_jni.so .......... THIRD_PARTY ${thirdPartyOrtDir}"
393
+ }
394
+
395
+ // Stage 3: MAVEN_AAR
396
+ if (!ortJniResolved) {
397
+ try {
398
+ def aarFiles = project.configurations.onnxruntimeAar.files
399
+ if (!aarFiles.isEmpty()) {
400
+ downloadDir.mkdirs()
401
+ def aar = aarFiles.iterator().next()
402
+ def aarExtractDir = new File(downloadDir, "onnxruntime-aar-extract")
403
+ if (aarExtractDir.exists()) aarExtractDir.deleteDir()
404
+ aarExtractDir.mkdirs()
405
+ copy { from zipTree(aar); into aarExtractDir }
406
+ requiredAbis.each { abi ->
407
+ def aarJniDir = new File(aarExtractDir, "jni/${abi}")
408
+ if (aarJniDir.exists()) {
409
+ copy {
410
+ from aarJniDir
411
+ include 'libonnxruntime4j_jni.so'
412
+ into new File(jniLibsDir, abi)
413
+ }
252
414
  }
253
415
  }
416
+ ortJniResolved = true
417
+ println "[onnxruntime] libonnxruntime4j_jni.so .......... MAVEN_AAR ${aar.name}"
418
+ println "[onnxruntime] install: per ABI → ${jniLibsHuman}/<abi>/ (only JNI bridge; libonnxruntime.so from sherpa prebuilts)"
419
+ } else {
420
+ println "[onnxruntime] MAVEN_AAR: onnxruntimeAar empty — libonnxruntime4j_jni.so still missing"
254
421
  }
255
- println "[onnxruntime] JNI bridge: Maven AAR (${aar.name})"
422
+ } catch (Exception e) {
423
+ println "[onnxruntime] MAVEN_AAR failed: ${e.message}"
256
424
  }
257
- } catch (Exception e) {
258
- println "Could not resolve onnxruntime Maven AAR: ${e.message}"
259
425
  }
426
+ } else {
427
+ println "[onnxruntime] libonnxruntime4j_jni.so (per ABI) .... LOCAL_SDK"
260
428
  }
261
429
 
430
+ // =====================================================================
431
+ // Stage 4: GITHUB_RELEASE fallback for sherpa / FFmpeg / libarchive
432
+ // =====================================================================
262
433
  def repo = project.findProperty('prebuiltGitHubRepo') ?: getGitHubRepo()
263
434
  if (!repo) {
264
- def needFfmpeg = !sherpaOnnxDisableFfmpeg && ffmpegNeedsUpdate && !ffmpegUpdatedFromAar[0]
265
- def needLibarchive = !sherpaOnnxDisableLibarchive && libarchiveNeedsUpdate && !libarchiveUpdatedFromAar[0]
266
- def needSherpa = sherpaNeedsUpdate && !sherpaUpdatedFromAar[0]
435
+ def needFfmpeg = !sherpaOnnxDisableFfmpeg && !ffmpegResolved
436
+ def needLibarchive = !sherpaOnnxDisableLibarchive && !libarchiveResolved
437
+ def needSherpa = !sherpaResolved
267
438
  if (needFfmpeg || needLibarchive || needSherpa) {
439
+ println "[prebuilt] GITHUB_RELEASE: skipped (no repo). Set -PprebuiltGitHubRepo=owner/repo or git remote origin → github.com"
440
+ println "[prebuilt] still need: sherpa=${needSherpa}, ffmpeg=${needFfmpeg}, libarchive=${needLibarchive}"
268
441
  def diag = [
269
442
  "prebuiltGitHubRepo=${project.findProperty('prebuiltGitHubRepo') ?: '(not set)'}",
270
443
  "git remote origin=${getGitHubRepo() ?: '(not a GitHub URL or git unavailable)'}",
271
444
  "sherpaOnnxDisableFfmpeg=${sherpaOnnxDisableFfmpeg}",
272
445
  "sherpaOnnxDisableLibarchive=${sherpaOnnxDisableLibarchive}",
273
- "sherpaNeedsUpdate=${sherpaNeedsUpdate} sherpaUpdatedFromAar=${sherpaUpdatedFromAar[0]}",
274
- "ffmpegNeedsUpdate=${ffmpegNeedsUpdate} ffmpegUpdatedFromAar=${ffmpegUpdatedFromAar[0]}",
275
- "libarchiveNeedsUpdate=${libarchiveNeedsUpdate} libarchiveUpdatedFromAar=${libarchiveUpdatedFromAar[0]}",
276
- "needFfmpeg=${needFfmpeg} needLibarchive=${needLibarchive} needSherpa=${needSherpa}"
446
+ "sherpaResolved=${sherpaResolved}",
447
+ "ffmpegResolved=${ffmpegResolved}",
448
+ "libarchiveResolved=${libarchiveResolved}",
277
449
  ].join(", ")
278
450
  throw new RuntimeException(
279
451
  "Native libs/headers still missing and GitHub repo unknown. " +
280
452
  "Set -PprebuiltGitHubRepo=owner/repo or ensure git remote origin is a GitHub URL. " +
281
- "Alternatively run third_party/ffmpeg_prebuilt/copy_prebuilts_to_sdk.js, third_party/sherpa-onnx-prebuilt/copy_prebuilts_to_sdk.js, third_party/libarchive_prebuilt/copy_prebuilts_to_sdk.js, or use Maven (com.xdcobra.sherpa:ffmpeg / sherpa-onnx / libarchive), or ensure ANDROID_RELEASE_TAG releases exist. " +
453
+ "Use Maven (com.xdcobra.sherpa:ffmpeg / sherpa-onnx / libarchive), run a Gradle Android build so prebuilts download, or ensure ANDROID_RELEASE_TAG GitHub releases exist. " +
282
454
  (sherpaOnnxDisableFfmpeg ? "(FFmpeg disabled via sherpaOnnxDisableFfmpeg=true.) " : "") +
283
455
  (sherpaOnnxDisableLibarchive ? "(libarchive disabled via sherpaOnnxDisableLibarchive=true.) " : "") +
284
456
  "Diagnostics: [${diag}]"
@@ -286,10 +458,16 @@ project.tasks.register("downloadNativeLibsIfNeeded") {
286
458
  }
287
459
  return
288
460
  }
461
+ def willUseGithub = !sherpaResolved ||
462
+ (!sherpaOnnxDisableFfmpeg && !ffmpegResolved) ||
463
+ (!sherpaOnnxDisableLibarchive && !libarchiveResolved)
464
+ if (willUseGithub) {
465
+ println "[prebuilt] GITHUB_RELEASE: repo=${repo} (ZIPs under releases/download/<tag>/ from third_party/*/ANDROID_RELEASE_TAG)"
466
+ }
289
467
  def baseUrl = "https://github.com/${repo}/releases/download"
290
468
  downloadDir.mkdirs()
291
469
 
292
- if (!sherpaOnnxDisableFfmpeg && ffmpegNeedsUpdate && !ffmpegUpdatedFromAar[0]) {
470
+ if (!sherpaOnnxDisableFfmpeg && !ffmpegResolved) {
293
471
  def tagFile = file("${project.projectDir.parent}/third_party/ffmpeg_prebuilt/ANDROID_RELEASE_TAG")
294
472
  def tag = readReleaseTag(tagFile)
295
473
  if (!tag) throw new RuntimeException("Missing or empty third_party/ffmpeg_prebuilt/ANDROID_RELEASE_TAG")
@@ -312,10 +490,13 @@ project.tasks.register("downloadNativeLibsIfNeeded") {
312
490
  }
313
491
  downloadDir.mkdirs()
314
492
  ffmpegVersionFile.text = currentFfmpegVersion
315
- println "Downloaded and extracted FFmpeg prebuilts (libs + include) from ${tag}"
493
+ println "[FFmpeg] jniLibs + C headers ...................... GITHUB_RELEASE tag=${tag}"
494
+ println "[FFmpeg] url: ${url}"
495
+ println "[FFmpeg] install: <abi>/*.so → ${jniLibsHuman}/"
496
+ println "[FFmpeg] version stamp .......................... written ${ffmpegVersionFile.name}=${currentFfmpegVersion}"
316
497
  }
317
498
 
318
- if (!sherpaOnnxDisableLibarchive && libarchiveNeedsUpdate && !libarchiveUpdatedFromAar[0]) {
499
+ if (!sherpaOnnxDisableLibarchive && !libarchiveResolved) {
319
500
  def tagFile = file("${project.projectDir.parent}/third_party/libarchive_prebuilt/ANDROID_RELEASE_TAG")
320
501
  def tag = readReleaseTag(tagFile)
321
502
  if (!tag) throw new RuntimeException("Missing or empty third_party/libarchive_prebuilt/ANDROID_RELEASE_TAG")
@@ -339,10 +520,13 @@ project.tasks.register("downloadNativeLibsIfNeeded") {
339
520
  }
340
521
  downloadDir.mkdirs()
341
522
  libarchiveVersionFile.text = currentLibarchiveVersion
342
- println "Downloaded and extracted libarchive prebuilts (libs + include) from ${tag}"
523
+ println "[libarchive] jniLibs + C headers .................. GITHUB_RELEASE tag=${tag}"
524
+ println "[libarchive] url: ${url}"
525
+ println "[libarchive] install: <abi>/*.so → ${jniLibsHuman}/"
526
+ println "[libarchive] version stamp ........................ written ${libarchiveVersionFile.name}=${currentLibarchiveVersion}"
343
527
  }
344
528
 
345
- if (sherpaNeedsUpdate && !sherpaUpdatedFromAar[0]) {
529
+ if (!sherpaResolved) {
346
530
  def tagFile = file("${project.projectDir.parent}/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG")
347
531
  def tag = readReleaseTag(tagFile)
348
532
  if (!tag) throw new RuntimeException("Missing or empty third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG")
@@ -366,6 +550,7 @@ project.tasks.register("downloadNativeLibsIfNeeded") {
366
550
  from fileTree(sherpaExtractDir) { include 'c-api/**' }
367
551
  into includeSherpaDir
368
552
  }
553
+ // Side-effect: extract classes.jar if present in the ZIP (saves extractSherpaOnnxClasses a trip)
369
554
  def sherpaJavaJar = new File(sherpaExtractDir, "java/classes.jar")
370
555
  if (sherpaJavaJar.exists()) {
371
556
  sherpaOnnxClassesDir.mkdirs()
@@ -373,15 +558,13 @@ project.tasks.register("downloadNativeLibsIfNeeded") {
373
558
  }
374
559
  downloadDir.mkdirs()
375
560
  sherpaVersionFile.text = currentSherpaVersion
376
- println "[sherpa-onnx] Native libs + headers: (3) GitHub release (${tag})"
377
- } else {
378
- def sherpaClassesJar = file("${project.projectDir.parent}/third_party/sherpa-onnx-prebuilt/android/java/classes.jar")
379
- if (sherpaClassesJar.exists() && !sherpaOnnxClassesDir.listFiles()?.any { it.name.endsWith('.jar') }) {
380
- sherpaOnnxClassesDir.mkdirs()
381
- copy { from sherpaClassesJar; into sherpaOnnxClassesDir }
382
- println "Copied sherpa-onnx classes.jar from local prebuilts into sherpa-onnx-classes"
383
- }
561
+ println "[sherpa-onnx] jniLibs + C headers ................. GITHUB_RELEASE tag=${tag}"
562
+ println "[sherpa-onnx] url: ${url}"
563
+ println "[sherpa-onnx] install: <abi>/*.so ${jniLibsHuman}/"
564
+ println "[sherpa-onnx] classes.jar ......................... ${sherpaJavaJar.exists() ? 'GITHUB_RELEASE → ' + sherpaOnnxClassesDir : 'not in zip (use extractSherpaOnnxClasses)'}"
565
+ println "[sherpa-onnx] version stamp ...................... written ${sherpaVersionFile.name}=${currentSherpaVersion}"
384
566
  }
567
+ println ""
385
568
  }
386
569
  }
387
570
 
@@ -391,27 +574,27 @@ project.tasks.register("checkJniLibs") {
391
574
  requiredAbis.each { abi ->
392
575
  def dir = file("${project.projectDir}/src/main/jniLibs/${abi}")
393
576
  if (!dir.exists()) {
394
- throw new RuntimeException("Missing native libs for ABI ${abi} in ${dir}. Run third_party/ffmpeg_prebuilt/copy_prebuilts_to_sdk.js, third_party/sherpa-onnx-prebuilt/copy_prebuilts_to_sdk.js, third_party/libarchive_prebuilt/copy_prebuilts_to_sdk.js, or use Maven (com.xdcobra.sherpa:ffmpeg / sherpa-onnx / libarchive), or ensure ANDROID_RELEASE_TAG releases exist.")
577
+ throw new RuntimeException("Missing native libs for ABI ${abi} in ${dir}. Run a Gradle Android build (downloadNativeLibsIfNeeded), use Maven com.xdcobra.sherpa:{ffmpeg,sherpa-onnx,libarchive}, or ensure ANDROID_RELEASE_TAG GitHub releases exist.")
395
578
  }
396
579
  if (!sherpaOnnxDisableFfmpeg) {
397
580
  requiredFfmpegSoFiles.each { soName ->
398
581
  def soFile = new File(dir, soName)
399
582
  if (!soFile.exists()) {
400
- throw new RuntimeException("Missing required FFmpeg library '${soName}' for ABI ${abi}. Run third_party/ffmpeg_prebuilt/copy_prebuilts_to_sdk.js or ensure Maven com.xdcobra.sherpa:ffmpeg is available. Or set sherpaOnnxDisableFfmpeg=true in gradle.properties (see docs/disable-ffmpeg.md).")
583
+ throw new RuntimeException("Missing required FFmpeg library '${soName}' for ABI ${abi}. Run a Gradle Android build so prebuilts download, or ensure Maven com.xdcobra.sherpa:ffmpeg resolves. Or set sherpaOnnxDisableFfmpeg=true in gradle.properties (see docs/disable-ffmpeg.md).")
401
584
  }
402
585
  }
403
586
  }
404
587
  requiredSherpaOnnxSoFiles.each { soName ->
405
588
  def soFile = new File(dir, soName)
406
589
  if (!soFile.exists()) {
407
- throw new RuntimeException("Missing required sherpa-onnx library '${soName}' for ABI ${abi}. Run third_party/sherpa-onnx-prebuilt/copy_prebuilts_to_sdk.js")
590
+ throw new RuntimeException("Missing required sherpa-onnx library '${soName}' for ABI ${abi}. Run a Gradle Android build so prebuilts download, or ensure Maven com.xdcobra.sherpa:sherpa-onnx resolves.")
408
591
  }
409
592
  }
410
593
  if (!sherpaOnnxDisableLibarchive) {
411
594
  requiredLibarchiveSoFiles.each { soName ->
412
595
  def soFile = new File(dir, soName)
413
596
  if (!soFile.exists()) {
414
- throw new RuntimeException("Missing required libarchive library '${soName}' for ABI ${abi}. Run third_party/libarchive_prebuilt/copy_prebuilts_to_sdk.js or ensure Maven com.xdcobra.sherpa:libarchive is available. Or set sherpaOnnxDisableLibarchive=true in gradle.properties (see docs/disable-libarchive.md).")
597
+ throw new RuntimeException("Missing required libarchive library '${soName}' for ABI ${abi}. Run a Gradle Android build so prebuilts download, or ensure Maven com.xdcobra.sherpa:libarchive resolves. Or set sherpaOnnxDisableLibarchive=true in gradle.properties (see docs/disable-libarchive.md).")
415
598
  }
416
599
  }
417
600
  }
@@ -429,6 +612,7 @@ project.afterEvaluate {
429
612
  project.tasks.findByName('preBuild')?.dependsOn(project.tasks.findByName('checkJniLibs'))
430
613
  }
431
614
 
615
+ // sherpa-onnx classes.jar: resolution order THIRD_PARTY → MAVEN_AAR → GITHUB_EXTRACT
432
616
  def sherpaLocalJar = file("${project.projectDir.parent}/third_party/sherpa-onnx-prebuilt/android/java/classes.jar")
433
617
  def sherpaExtractedJar = file("${project.buildDir}/prebuilt-downloads/sherpa-onnx-extract/java/classes.jar")
434
618
 
@@ -441,7 +625,9 @@ project.tasks.register("extractSherpaOnnxClasses") {
441
625
  file(sherpaOnnxClassesDir).listFiles()?.findAll { it.name.endsWith('.jar') }?.each { it.delete() }
442
626
  if (sherpaLocalJar.exists()) {
443
627
  copy { from sherpaLocalJar; into sherpaOnnxClassesDir }
444
- println "[sherpa-onnx] classes.jar: (1) local third_party"
628
+ println "[prebuilt] extractSherpaOnnxClasses"
629
+ println "[sherpa-onnx] classes.jar (Kotlin API) .......... THIRD_PARTY"
630
+ println "[sherpa-onnx] ${sherpaLocalJar.absolutePath} → ${sherpaOnnxClassesDir}"
445
631
  return
446
632
  }
447
633
  def aarFiles = project.configurations.sherpaOnnxAar.files
@@ -452,16 +638,20 @@ project.tasks.register("extractSherpaOnnxClasses") {
452
638
  include 'classes.jar'
453
639
  into sherpaOnnxClassesDir
454
640
  }
455
- println "[sherpa-onnx] classes.jar: (2) Maven AAR Kotlin (${aar.name})"
641
+ println "[prebuilt] extractSherpaOnnxClasses"
642
+ println "[sherpa-onnx] classes.jar (Kotlin API) .......... MAVEN_AAR ${aar.name}"
643
+ println "[sherpa-onnx] classes.jar → ${sherpaOnnxClassesDir}"
456
644
  return
457
645
  }
458
646
  if (sherpaExtractedJar.exists()) {
459
647
  copy { from sherpaExtractedJar; into sherpaOnnxClassesDir }
460
- println "[sherpa-onnx] classes.jar: (3) GitHub release extract"
648
+ println "[prebuilt] extractSherpaOnnxClasses"
649
+ println "[sherpa-onnx] classes.jar (Kotlin API) .......... GITHUB_EXTRACT"
650
+ println "[sherpa-onnx] ${sherpaExtractedJar.absolutePath} → ${sherpaOnnxClassesDir}"
461
651
  return
462
652
  }
463
653
  throw new RuntimeException(
464
- "Missing sherpa-onnx classes.jar (Kotlin API). Use (1) local build_sherpa_onnx.sh, (2) Maven com.xdcobra.sherpa:sherpa-onnx, or (3) a GitHub release with java/classes.jar.")
654
+ "Missing sherpa-onnx classes.jar (Kotlin API). Tried: THIRD_PARTY (third_party/.../classes.jar), MAVEN_AAR (sherpaOnnxAar), GITHUB_EXTRACT (build/prebuilt-downloads/sherpa-onnx-extract/java/classes.jar after GitHub zip).")
465
655
  }
466
656
  }
467
657
 
@@ -486,10 +676,12 @@ project.tasks.register("extractOnnxruntimeClasses") {
486
676
  def renamed = new File(onnxruntimeClassesDir, "onnxruntime-classes.jar")
487
677
  extractedJar.renameTo(renamed)
488
678
  }
489
- println "[onnxruntime] classes.jar: Maven AAR (${aar.name})"
679
+ println "[prebuilt] extractOnnxruntimeClasses"
680
+ println "[onnxruntime] classes.jar (Java API) ........... MAVEN_AAR ${aar.name}"
681
+ println "[onnxruntime] renamed to onnxruntime-classes.jar → ${onnxruntimeClassesDir}"
490
682
  return
491
683
  }
492
684
  throw new RuntimeException(
493
- "Missing onnxruntime classes.jar. Ensure Maven com.xdcobra.sherpa:onnxruntime is available.")
685
+ "Missing onnxruntime classes.jar. Only source is MAVEN_AAR (configuration onnxruntimeAar / com.xdcobra.sherpa:onnxruntime).")
494
686
  }
495
687
  }