react-native-sherpa-onnx 0.3.2 → 0.3.4

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 (83) hide show
  1. package/README.md +84 -77
  2. package/SherpaOnnx.podspec +79 -45
  3. package/android/build.gradle +8 -2
  4. package/android/prebuilt-download.gradle +70 -16
  5. package/android/prebuilt-versions.gradle +14 -6
  6. package/android/src/main/cpp/CMakeLists.txt +2 -0
  7. package/android/src/main/cpp/jni/audio/sherpa-onnx-audio-convert-jni.cpp +202 -328
  8. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-detect-jni-common.cpp +22 -0
  9. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-detect-jni-common.h +2 -0
  10. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.cpp +96 -142
  11. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.h +40 -4
  12. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-stt.cpp +774 -316
  13. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-tts.cpp +208 -122
  14. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect.h +92 -0
  15. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-stt-wrapper.cpp +3 -0
  16. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-tts-wrapper.cpp +14 -2
  17. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-stt.cpp +229 -0
  18. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-stt.h +38 -0
  19. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-tts.cpp +144 -0
  20. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-validate-tts.h +38 -0
  21. package/android/src/main/cpp/jni/module/sherpa-onnx-module-jni.cpp +1 -1
  22. package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +157 -11
  23. package/android/src/main/java/com/sherpaonnx/SherpaOnnxPcmCapture.kt +150 -0
  24. package/android/src/main/java/com/sherpaonnx/SherpaOnnxSttHelper.kt +75 -24
  25. package/android/src/main/java/com/sherpaonnx/SherpaOnnxTtsHelper.kt +52 -1
  26. package/ios/SherpaOnnx+PcmLiveStream.mm +288 -0
  27. package/ios/SherpaOnnx+STT.mm +2 -0
  28. package/ios/SherpaOnnx+TTS.mm +17 -0
  29. package/ios/SherpaOnnx.mm +27 -3
  30. package/ios/SherpaOnnxAudioConvert.h +28 -0
  31. package/ios/SherpaOnnxAudioConvert.mm +698 -0
  32. package/ios/archive/sherpa-onnx-archive-helper.mm +12 -0
  33. package/ios/model_detect/sherpa-onnx-model-detect-helper.h +37 -3
  34. package/ios/model_detect/sherpa-onnx-model-detect-helper.mm +80 -45
  35. package/ios/model_detect/sherpa-onnx-model-detect-stt.mm +629 -267
  36. package/ios/model_detect/sherpa-onnx-model-detect-tts.mm +148 -56
  37. package/ios/model_detect/sherpa-onnx-model-detect.h +72 -0
  38. package/ios/model_detect/sherpa-onnx-validate-stt.h +38 -0
  39. package/ios/model_detect/sherpa-onnx-validate-stt.mm +229 -0
  40. package/ios/model_detect/sherpa-onnx-validate-tts.h +38 -0
  41. package/ios/model_detect/sherpa-onnx-validate-tts.mm +144 -0
  42. package/ios/stt/sherpa-onnx-stt-wrapper.mm +4 -0
  43. package/lib/module/NativeSherpaOnnx.js.map +1 -1
  44. package/lib/module/audio/index.js +55 -1
  45. package/lib/module/audio/index.js.map +1 -1
  46. package/lib/module/download/ModelDownloadManager.js +14 -0
  47. package/lib/module/download/ModelDownloadManager.js.map +1 -1
  48. package/lib/module/index.js +10 -0
  49. package/lib/module/index.js.map +1 -1
  50. package/lib/module/stt/streaming.js +6 -3
  51. package/lib/module/stt/streaming.js.map +1 -1
  52. package/lib/module/tts/index.js +13 -1
  53. package/lib/module/tts/index.js.map +1 -1
  54. package/lib/typescript/src/NativeSherpaOnnx.d.ts +32 -3
  55. package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
  56. package/lib/typescript/src/audio/index.d.ts +20 -1
  57. package/lib/typescript/src/audio/index.d.ts.map +1 -1
  58. package/lib/typescript/src/download/ModelDownloadManager.d.ts +2 -1
  59. package/lib/typescript/src/download/ModelDownloadManager.d.ts.map +1 -1
  60. package/lib/typescript/src/index.d.ts +10 -0
  61. package/lib/typescript/src/index.d.ts.map +1 -1
  62. package/lib/typescript/src/stt/streaming.d.ts.map +1 -1
  63. package/lib/typescript/src/stt/streamingTypes.d.ts +1 -1
  64. package/lib/typescript/src/stt/streamingTypes.d.ts.map +1 -1
  65. package/lib/typescript/src/tts/index.d.ts +12 -1
  66. package/lib/typescript/src/tts/index.d.ts.map +1 -1
  67. package/package.json +6 -1
  68. package/scripts/check-model-csvs.sh +72 -0
  69. package/scripts/setup-ios-framework.sh +272 -191
  70. package/src/NativeSherpaOnnx.ts +37 -3
  71. package/src/audio/index.ts +84 -1
  72. package/src/download/ModelDownloadManager.ts +19 -0
  73. package/src/index.tsx +15 -0
  74. package/src/stt/streaming.ts +10 -5
  75. package/src/stt/streamingTypes.ts +1 -1
  76. package/src/tts/index.ts +25 -1
  77. package/third_party/ffmpeg_prebuilt/ANDROID_RELEASE_TAG +1 -1
  78. package/third_party/libarchive_prebuilt/ANDROID_RELEASE_TAG +1 -1
  79. package/third_party/libarchive_prebuilt/IOS_RELEASE_TAG +1 -1
  80. package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -1
  81. package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -1
  82. package/ios/scripts/patch-libarchive-includes.sh +0 -61
  83. package/ios/scripts/setup-ios-libarchive.sh +0 -98
@@ -1,12 +1,12 @@
1
1
  #!/bin/bash
2
2
 
3
- # Script to download and manage iOS Framework
3
+ # Script to download and manage iOS Frameworks (sherpa-onnx, FFmpeg)
4
4
  # Can be called manually or by Podfile during pod install
5
5
  # Usage:
6
- # ./scripts/setup-ios-framework.sh # Downloads/updates framework (auto mode, no interactive)
7
- # ./scripts/setup-ios-framework.sh 1.12.24 # Downloads specific version
8
- # ./scripts/setup-ios-framework.sh --force # Remove local cache and re-download (same version from IOS_RELEASE_TAG)
9
- # ./scripts/setup-ios-framework.sh --interactive # Interactive mode with prompts
6
+ # ./scripts/setup-ios-framework.sh # Downloads/updates both frameworks (auto mode, no interactive)
7
+ # ./scripts/setup-ios-framework.sh 1.12.24 # Downloads specific sherpa-onnx version (ffmpeg from its TAG)
8
+ # ./scripts/setup-ios-framework.sh --force # Remove local caches and re-download both
9
+ # ./scripts/setup-ios-framework.sh --interactive # Interactive mode with prompts
10
10
  # To force re-download during pod install: SHERPA_ONNX_IOS_FORCE_DOWNLOAD=1 pod install
11
11
 
12
12
  set -e
@@ -36,7 +36,6 @@ if [ -z "$PROJECT_ROOT" ]; then
36
36
  exit 1
37
37
  fi
38
38
  FRAMEWORKS_DIR="$PROJECT_ROOT/ios/Frameworks"
39
- VERSION_FILE="$FRAMEWORKS_DIR/.framework-version"
40
39
 
41
40
  # Colors for output
42
41
  RED='\033[0;31m'
@@ -73,162 +72,256 @@ fi
73
72
  # Create frameworks directory if it doesn't exist
74
73
  mkdir -p "$FRAMEWORKS_DIR"
75
74
 
76
- # Helper: check if a framework path is valid for building (has library + required headers for compiler)
75
+ # Framework slugs to manage (order: sherpa-onnx first, then libarchive, then ffmpeg)
76
+ FRAMEWORK_SLUGS=(sherpa-onnx)
77
+
78
+ if [ "${SHERPA_ONNX_DISABLE_LIBARCHIVE:-0}" != "1" ] && [ "${SHERPA_ONNX_DISABLE_LIBARCHIVE:-false}" != "true" ]; then
79
+ FRAMEWORK_SLUGS+=(libarchive)
80
+ else
81
+ [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}SHERPA_ONNX_DISABLE_LIBARCHIVE is set. Skipping libarchive framework download.${NC}" >&2
82
+ fi
83
+
84
+ if [ "${SHERPA_ONNX_DISABLE_FFMPEG:-0}" != "1" ] && [ "${SHERPA_ONNX_DISABLE_FFMPEG:-false}" != "true" ]; then
85
+ FRAMEWORK_SLUGS+=(ffmpeg)
86
+ else
87
+ [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}SHERPA_ONNX_DISABLE_FFMPEG is set. Skipping FFmpeg framework download.${NC}" >&2
88
+ fi
89
+
90
+ # Set config variables for a given framework slug. Call before using TAG_* XCFRAMEWORK_* etc.
91
+ get_framework_config() {
92
+ local slug="$1"
93
+ case "$slug" in
94
+ sherpa-onnx)
95
+ TAG_FILE="$PROJECT_ROOT/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG"
96
+ TAG_PREFIX="framework-v"
97
+ XCFRAMEWORK_NAME="sherpa_onnx.xcframework"
98
+ ZIP_ASSET_NAME="sherpa_onnx.xcframework.zip"
99
+ VERSION_FILE="$FRAMEWORKS_DIR/.framework-version-sherpa-onnx"
100
+ LIB_DEVICE="libsherpa-onnx.a"
101
+ LIB_SIMULATOR="libsherpa-onnx.a"
102
+ HEADER_CHECK="Headers/sherpa-onnx/c-api/cxx-api.h"
103
+ DISPLAY_NAME="SherpaOnnx"
104
+ ;;
105
+ ffmpeg)
106
+ TAG_FILE="$PROJECT_ROOT/third_party/ffmpeg_prebuilt/IOS_RELEASE_TAG"
107
+ TAG_PREFIX="ffmpeg-ios-v"
108
+ XCFRAMEWORK_NAME="FFmpeg.xcframework"
109
+ ZIP_ASSET_NAME="ffmpeg-ios-framework.zip"
110
+ VERSION_FILE="$FRAMEWORKS_DIR/.framework-version-ffmpeg"
111
+ LIB_DEVICE="libffmpeg.a"
112
+ LIB_SIMULATOR="libffmpeg.a"
113
+ HEADER_CHECK="Headers/libavcodec/avcodec.h"
114
+ DISPLAY_NAME="FFmpeg"
115
+ ;;
116
+ libarchive)
117
+ TAG_FILE="$PROJECT_ROOT/third_party/libarchive_prebuilt/IOS_RELEASE_TAG"
118
+ TAG_PREFIX="libarchive-ios-v"
119
+ XCFRAMEWORK_NAME="libarchive.xcframework"
120
+ ZIP_ASSET_NAME="libarchive-ios.zip"
121
+ VERSION_FILE="$FRAMEWORKS_DIR/.framework-version-libarchive"
122
+ LIB_DEVICE="libarchive.a"
123
+ LIB_SIMULATOR="libarchive.a"
124
+ HEADER_CHECK="Headers/archive.h"
125
+ DISPLAY_NAME="libarchive"
126
+ ;;
127
+ *)
128
+ echo "Unknown framework: $slug" >&2
129
+ return 1
130
+ ;;
131
+ esac
132
+ }
133
+
134
+ # Helper: check if a framework path is valid for building (has library + required headers)
135
+ # Usage: framework_valid <slug> <fw_root>
77
136
  framework_valid() {
78
- local fw_root="$1"
79
- [ -f "$fw_root/ios-arm64/libsherpa-onnx.a" ] || return 1
80
- [ -f "$fw_root/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h" ] || return 1
137
+ local slug="$1"
138
+ local fw_root="$2"
139
+ get_framework_config "$slug" || return 1
140
+ [ -f "$fw_root/ios-arm64/$LIB_DEVICE" ] || return 1
141
+ [ -f "$fw_root/ios-arm64_x86_64-simulator/$LIB_SIMULATOR" ] || return 1
142
+ [ -f "$fw_root/ios-arm64_x86_64-simulator/$HEADER_CHECK" ] || return 1
81
143
  return 0
82
144
  }
83
145
 
84
- # When run as Xcode build phase (prepare_command): if framework is already present and valid, exit successfully.
85
- # Avoids network/TAG-file dependency during build and prevents "PhaseScriptExecution failed" when nothing is needed.
86
- # We require both the library and the Headers (sherpa-onnx/c-api/cxx-api.h) so an incomplete framework triggers a re-download.
87
- if [ "$FORCE_DOWNLOAD" != true ]; then
88
- if [ -d "$FRAMEWORKS_DIR/sherpa_onnx.xcframework" ] && framework_valid "$FRAMEWORKS_DIR/sherpa_onnx.xcframework"; then
89
- echo "[SherpaOnnx] Framework already present at $FRAMEWORKS_DIR/sherpa_onnx.xcframework, skipping download." >&2
90
- exit 0
146
+ # Helper: get installed framework version (from version file or xcframework VERSION.txt)
147
+ # Usage: get_installed_version <slug>
148
+ # Backward compat: for sherpa-onnx, also checks legacy .framework-version
149
+ get_installed_version() {
150
+ local slug="$1"
151
+ get_framework_config "$slug" || return 1
152
+ # Backward compat: sherpa-onnx used to use .framework-version
153
+ if [ "$slug" = "sherpa-onnx" ] && [ -f "$FRAMEWORKS_DIR/.framework-version" ]; then
154
+ cat "$FRAMEWORKS_DIR/.framework-version" 2>/dev/null | tr -d '\r\n'
155
+ return 0
91
156
  fi
92
- if [ -d "$FRAMEWORKS_DIR/sherpa-onnx.xcframework" ] && framework_valid "$FRAMEWORKS_DIR/sherpa-onnx.xcframework"; then
93
- echo "[SherpaOnnx] Framework already present at $FRAMEWORKS_DIR/sherpa-onnx.xcframework, skipping download." >&2
94
- exit 0
157
+ if [ -f "$VERSION_FILE" ]; then
158
+ cat "$VERSION_FILE" 2>/dev/null | tr -d '\r\n'
159
+ return 0
95
160
  fi
96
- fi
161
+ if [ -f "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME/VERSION.txt" ]; then
162
+ grep -Eo '([0-9]+\.)+[0-9]+([-a-zA-Z0-9.]*)?' "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME/VERSION.txt" | head -n1 | tr -d '\r\n'
163
+ return 0
164
+ fi
165
+ echo ""
166
+ }
97
167
 
98
- # Prepare GitHub auth header if GITHUB_TOKEN is provided (helps avoid API rate limits)
168
+ # Get desired version from a framework's IOS_RELEASE_TAG file.
169
+ # Usage: get_desired_version_from_tag <slug>
170
+ # Output: version (e.g. 1.12.28 or 8.0.1) or empty if file/tag missing.
171
+ get_desired_version_from_tag() {
172
+ local slug="$1"
173
+ get_framework_config "$slug" || return 1
174
+ if [ ! -f "$TAG_FILE" ]; then
175
+ echo ""
176
+ return 0
177
+ fi
178
+ local tag
179
+ tag=$(grep -v '^#' "$TAG_FILE" | grep -v '^[[:space:]]*$' | head -1 | tr -d '\r\n')
180
+ if [ -z "$tag" ] || [ "${tag#$TAG_PREFIX}" = "$tag" ]; then
181
+ echo ""
182
+ return 0
183
+ fi
184
+ echo "${tag#$TAG_PREFIX}"
185
+ }
186
+
187
+ # When run as Xcode build phase: if all frameworks are present, valid, AND match their IOS_RELEASE_TAG, exit successfully.
188
+ need_download() {
189
+ local slug="$1"
190
+ local desired="$2"
191
+ get_framework_config "$slug" || return 1
192
+ local fw_path="$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME"
193
+ if [ ! -d "$fw_path" ]; then
194
+ return 0
195
+ fi
196
+ if ! framework_valid "$slug" "$fw_path"; then
197
+ return 0
198
+ fi
199
+ # Backfill version file from xcframework if missing
200
+ if [ ! -f "$VERSION_FILE" ] && [ -f "$fw_path/VERSION.txt" ]; then
201
+ local ver
202
+ ver=$(grep -Eo '([0-9]+\.)+[0-9]+([-a-zA-Z0-9.]*)?' "$fw_path/VERSION.txt" | head -n1 || true)
203
+ [ -n "$ver" ] && echo "$ver" > "$VERSION_FILE" 2>/dev/null || true
204
+ fi
205
+ local installed
206
+ installed=$(get_installed_version "$slug")
207
+ if [ -n "$desired" ] && [ -n "$installed" ] && [ "$installed" = "$desired" ]; then
208
+ return 1
209
+ fi
210
+ return 0
211
+ }
212
+
213
+ # Prepare GitHub auth header if GITHUB_TOKEN is provided
99
214
  AUTH_ARGS=()
100
215
  if [ -n "$GITHUB_TOKEN" ]; then
101
216
  AUTH_ARGS+=("-H" "Authorization: Bearer $GITHUB_TOKEN")
102
217
  fi
103
218
 
104
- # If SHERPA_ONNX_VERSION is set, treat it as the desired framework version
105
- # and do not perform the usual "auto-upgrade to latest" behavior. This helps
106
- # prevent accidental upgrades during CI or automated installs.
107
- if [ -n "$SHERPA_ONNX_VERSION" ]; then
108
- DESIRED_VERSION="$SHERPA_ONNX_VERSION"
219
+ # Explicit version on command line overrides sherpa-onnx only (backward compat)
220
+ SHERPA_DESIRED_OVERRIDE=""
221
+ if [ -n "$1" ] && [[ "$1" =~ ^[0-9]+\.([0-9]+\.)*[0-9]+$ ]]; then
222
+ SHERPA_DESIRED_OVERRIDE="$1"
109
223
  fi
110
- # If no env var was provided, use repo-level IOS_RELEASE_TAG (single source of truth for iOS framework version).
111
- # Format: framework-vX.Y.Z (e.g. framework-v1.12.24). Do not use ANDROID_RELEASE_TAG for iOS.
112
- if [ -z "$DESIRED_VERSION" ]; then
113
- IOS_TAG_FILE="$PROJECT_ROOT/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG"
114
- if [ -f "$IOS_TAG_FILE" ]; then
115
- TAG=$(grep -v '^#' "$IOS_TAG_FILE" | grep -v '^[[:space:]]*$' | head -1 | tr -d '\r\n')
116
- if [ -n "$TAG" ] && [ "${TAG#framework-v}" != "$TAG" ]; then
117
- DESIRED_VERSION="${TAG#framework-v}"
118
- [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}Using iOS framework version from IOS_RELEASE_TAG: $DESIRED_VERSION${NC}" >&2
119
- fi
224
+
225
+ # Return desired version for a framework slug (from TAG, env, or override). No output = use TAG/env only.
226
+ get_desired_version() {
227
+ local slug="$1"
228
+ if [ "$slug" = "sherpa-onnx" ] && [ -n "$SHERPA_DESIRED_OVERRIDE" ]; then
229
+ echo "$SHERPA_DESIRED_OVERRIDE"
230
+ return
120
231
  fi
121
- if [ -z "$DESIRED_VERSION" ]; then
122
- echo -e "${RED}Error: IOS_RELEASE_TAG not found at $IOS_TAG_FILE. Reinstall the package or run from repo.${NC}" >&2
123
- exit 1
232
+ if [ "$slug" = "sherpa-onnx" ] && [ -n "$SHERPA_ONNX_VERSION" ]; then
233
+ echo "$SHERPA_ONNX_VERSION"
234
+ return
124
235
  fi
125
- fi
236
+ get_desired_version_from_tag "$slug"
237
+ }
126
238
 
127
- # Function to compare semantic versions (e.g., "1.12.23" vs "1.12.24")
128
- compare_versions() {
129
- local v1=$1
130
- local v2=$2
131
-
132
- # Convert to arrays
133
- IFS='.' read -ra v1_parts <<< "$v1"
134
- IFS='.' read -ra v2_parts <<< "$v2"
135
-
136
- # Pad arrays to same length
137
- local max_len=${#v1_parts[@]}
138
- [ ${#v2_parts[@]} -gt $max_len ] && max_len=${#v2_parts[@]}
139
-
140
- # Compare each part
141
- for ((i=0; i<max_len; i++)); do
142
- local v1_num=${v1_parts[$i]:-0}
143
- local v2_num=${v2_parts[$i]:-0}
144
-
145
- if [ "$v1_num" -lt "$v2_num" ]; then
146
- echo "-1" # v1 < v2
147
- return 0
148
- elif [ "$v1_num" -gt "$v2_num" ]; then
149
- echo "1" # v1 > v2
150
- return 0
239
+ # Check early exit: all frameworks present, valid, and matching their desired version
240
+ SKIP_ALL=true
241
+ for slug in "${FRAMEWORK_SLUGS[@]}"; do
242
+ desired=$(get_desired_version "$slug")
243
+ if [ -z "$desired" ] && [ "$slug" = "sherpa-onnx" ]; then
244
+ SKIP_ALL=false
245
+ break
246
+ fi
247
+ if [ -n "$desired" ] && need_download "$slug" "$desired"; then
248
+ SKIP_ALL=false
249
+ break
250
+ fi
251
+ done
252
+
253
+ if [ "$FORCE_DOWNLOAD" != true ] && [ "$SKIP_ALL" = true ]; then
254
+ for slug in "${FRAMEWORK_SLUGS[@]}"; do
255
+ get_framework_config "$slug" || exit 1
256
+ desired=$(get_desired_version "$slug")
257
+ if [ -n "$desired" ]; then
258
+ installed=$(get_installed_version "$slug")
259
+ echo "[$DISPLAY_NAME] Framework already present at $FRAMEWORKS_DIR/$XCFRAMEWORK_NAME (v$installed), skipping download." >&2
151
260
  fi
152
261
  done
153
262
 
154
- echo "0" # v1 == v2
155
- }
156
-
157
- # Function to get latest framework version from GitHub
158
- get_latest_framework_version() {
159
- echo -e "${YELLOW}Fetching latest framework release from GitHub...${NC}" >&2
160
-
161
- local releases_json=$(curl -s "${AUTH_ARGS[@]}" -H "Accept: application/vnd.github+json" "https://api.github.com/repos/XDcobra/react-native-sherpa-onnx/releases" 2>/dev/null || echo "")
162
-
163
- if [ -z "$releases_json" ]; then
164
- echo -e "${RED}Error: Could not fetch releases from GitHub API${NC}" >&2
165
- return 1
166
- fi
167
-
168
- # Avoid jq errors on rate-limit HTML or plain-text responses
169
- if ! echo "$releases_json" | grep -q '"tag_name"'; then
170
- echo -e "${RED}Error: GitHub API response did not contain release data (possible rate limit).${NC}" >&2
171
- echo "Response (truncated):" >&2
172
- echo "$releases_json" | head -5 >&2
173
- return 1
263
+ # Fix CocoaPods header flattening: delete FFmpeg's time.h so it doesn't shadow system time.h
264
+ if [ -d "$FRAMEWORKS_DIR/FFmpeg.xcframework" ]; then
265
+ find "$FRAMEWORKS_DIR/FFmpeg.xcframework" -name "time.h" -path "*/libavutil/time.h" -delete 2>/dev/null || true
174
266
  fi
175
267
 
176
- local version=""
268
+ exit 0
269
+ fi
177
270
 
178
- if command -v jq &> /dev/null; then
179
- if echo "$releases_json" | jq -e . > /dev/null 2>&1; then
180
- version=$(echo "$releases_json" | jq -r '.[] | select(.tag_name | startswith("framework-v")) | .tag_name' | head -1 | sed 's/framework-v//')
181
- else
182
- echo -e "${RED}Error: GitHub releases response is not valid JSON${NC}" >&2
183
- echo "$releases_json" | head -5 >&2
184
- return 1
271
+ if [ "$FORCE_DOWNLOAD" != true ]; then
272
+ for slug in "${FRAMEWORK_SLUGS[@]}"; do
273
+ get_framework_config "$slug" || exit 1
274
+ desired=$(get_desired_version "$slug")
275
+ if [ -n "$desired" ] && need_download "$slug" "$desired"; then
276
+ installed=$(get_installed_version "$slug")
277
+ [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}[$DISPLAY_NAME] Installed v${installed} does not match TAG ($desired), will re-download.${NC}" >&2
185
278
  fi
186
- else
187
- version=$(echo "$releases_json" | grep -o '"tag_name": "framework-v[0-9.]*' | head -1 | sed 's/.*framework-v//')
188
- fi
189
-
190
- if [ -z "$version" ]; then
191
- echo -e "${RED}Error: No framework releases found with tag format 'framework-vX.Y.Z'${NC}" >&2
192
- return 1
193
- fi
279
+ done
280
+ fi
194
281
 
195
- echo "$version"
196
- }
282
+ # Require desired version for sherpa-onnx (main dependency)
283
+ if [ -z "$(get_desired_version sherpa-onnx)" ]; then
284
+ get_framework_config "sherpa-onnx" || true
285
+ echo -e "${RED}Error: IOS_RELEASE_TAG not found at $TAG_FILE or invalid format (expected ${TAG_PREFIX}X.Y.Z). Reinstall the package or run from repo.${NC}" >&2
286
+ exit 1
287
+ fi
197
288
 
198
- # Function to get local framework version
289
+ # Function to get local framework version (for display / compare)
199
290
  get_local_framework_version() {
200
- # Prefer explicit version file written by this script
291
+ local slug="$1"
292
+ get_framework_config "$slug" || return 1
201
293
  if [ -f "$VERSION_FILE" ]; then
202
294
  cat "$VERSION_FILE"
203
295
  return 0
204
296
  fi
205
-
206
- # If .framework-version missing, try to read VERSION.txt from the XCFramework
207
- for f in "sherpa_onnx.xcframework" "sherpa-onnx.xcframework"; do
208
- if [ -f "$FRAMEWORKS_DIR/$f/VERSION.txt" ]; then
209
- # Extract first semantic version-like token (e.g. 1.12.24)
210
- ver=$(grep -Eo '([0-9]+\.)+[0-9]+' "$FRAMEWORKS_DIR/$f/VERSION.txt" | head -n1 || true)
211
- if [ -n "$ver" ]; then
212
- # Cache it for future runs
213
- echo "$ver" > "$VERSION_FILE" 2>/dev/null || true
214
- echo "$ver"
215
- return 0
216
- fi
297
+ if [ "$slug" = "sherpa-onnx" ] && [ -f "$FRAMEWORKS_DIR/.framework-version" ]; then
298
+ cat "$FRAMEWORKS_DIR/.framework-version"
299
+ return 0
300
+ fi
301
+ if [ -f "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME/VERSION.txt" ]; then
302
+ local ver
303
+ ver=$(grep -Eo '([0-9]+\.)+[0-9]+([-a-zA-Z0-9.]*)?' "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME/VERSION.txt" | head -n1 || true)
304
+ if [ -n "$ver" ]; then
305
+ echo "$ver" > "$VERSION_FILE" 2>/dev/null || true
306
+ echo "$ver"
307
+ return 0
217
308
  fi
218
- done
219
-
309
+ fi
220
310
  echo ""
221
311
  }
222
312
 
223
- # Function to download and extract framework
313
+ # Function to download and extract a framework
314
+ # Usage: download_and_extract_framework <slug> <version>
224
315
  download_and_extract_framework() {
225
- local version=$1
226
- local tag="framework-v$version"
316
+ local slug="$1"
317
+ local version="$2"
318
+ get_framework_config "$slug" || return 1
319
+ local tag="${TAG_PREFIX}${version}"
227
320
 
228
- echo -e "${YELLOW}Downloading framework version $version...${NC}" >&2
321
+ echo -e "${YELLOW}[$DISPLAY_NAME] Downloading framework version $version...${NC}" >&2
229
322
 
230
- # Get download URL from GitHub API
231
- local release_json=$(curl -s "${AUTH_ARGS[@]}" -H "Accept: application/vnd.github+json" "https://api.github.com/repos/XDcobra/react-native-sherpa-onnx/releases/tags/$tag" 2>/dev/null || echo "")
323
+ local release_json
324
+ release_json=$(curl -s "${AUTH_ARGS[@]}" -H "Accept: application/vnd.github+json" "https://api.github.com/repos/XDcobra/react-native-sherpa-onnx/releases/tags/$tag" 2>/dev/null || echo "")
232
325
 
233
326
  if [ -z "$release_json" ]; then
234
327
  echo -e "${RED}Error: Could not fetch release information for tag $tag${NC}" >&2
@@ -242,24 +335,23 @@ download_and_extract_framework() {
242
335
  return 1
243
336
  fi
244
337
 
245
- # Extract download URL using jq if available, otherwise grep/sed
246
338
  local download_url
247
339
  if command -v jq &> /dev/null; then
248
340
  if echo "$release_json" | jq -e . > /dev/null 2>&1; then
249
- download_url=$(echo "$release_json" | jq -r '.assets[] | select(.name == "sherpa_onnx.xcframework.zip") | .browser_download_url' | head -1)
341
+ download_url=$(echo "$release_json" | jq -r --arg name "$ZIP_ASSET_NAME" '.assets[] | select(.name == $name) | .browser_download_url' | head -1)
250
342
  else
251
343
  echo -e "${RED}Error: Release response is not valid JSON${NC}" >&2
252
344
  echo "$release_json" | head -5 >&2
253
345
  return 1
254
346
  fi
255
347
  else
256
- download_url=$(echo "$release_json" | grep -o '"browser_download_url": "[^"]*' | grep 'xcframework.zip' | head -1 | sed 's/.*: "//' | sed 's/"$//')
348
+ download_url=$(echo "$release_json" | grep -o '"browser_download_url": "[^"]*' | grep "$ZIP_ASSET_NAME" | head -1 | sed 's/.*: "//' | sed 's/"$//')
257
349
  fi
258
350
 
259
351
  if [ -z "$download_url" ]; then
260
- echo -e "${RED}Error: Could not find download URL for version $version${NC}" >&2
261
- echo -e "${RED}Available assets:${NC}" >&2
352
+ echo -e "${RED}Error: Could not find download URL for $DISPLAY_NAME version $version (asset: $ZIP_ASSET_NAME)${NC}" >&2
262
353
  if command -v jq &> /dev/null; then
354
+ echo -e "${RED}Available assets:${NC}" >&2
263
355
  echo "$release_json" | jq -r '.assets[].name' | sed 's/^/ - /' >&2 || true
264
356
  fi
265
357
  return 1
@@ -267,8 +359,7 @@ download_and_extract_framework() {
267
359
 
268
360
  echo "Downloading from: $download_url" >&2
269
361
 
270
- # Download the zip file
271
- local zip_path="$FRAMEWORKS_DIR/sherpa_onnx.xcframework.zip"
362
+ local zip_path="$FRAMEWORKS_DIR/$ZIP_ASSET_NAME"
272
363
 
273
364
  if ! curl -L -f "${AUTH_ARGS[@]}" -o "$zip_path" "$download_url" 2>/dev/null; then
274
365
  echo -e "${RED}Error: Failed to download framework from $download_url${NC}" >&2
@@ -276,104 +367,94 @@ download_and_extract_framework() {
276
367
  return 1
277
368
  fi
278
369
 
279
- # Check if zip file is valid
280
370
  if ! file "$zip_path" 2>/dev/null | grep -q "Zip archive"; then
281
371
  echo -e "${RED}Error: Downloaded file is not a valid zip archive${NC}" >&2
282
- echo "File type: $(file "$zip_path" 2>/dev/null || echo "unknown")" >&2
283
372
  rm -f "$zip_path"
284
373
  return 1
285
374
  fi
286
375
 
287
- # Remove old framework if it exists
288
- if [ -d "$FRAMEWORKS_DIR/sherpa_onnx.xcframework" ]; then
289
- echo -e "${YELLOW}Removing old framework...${NC}" >&2
290
- rm -rf "$FRAMEWORKS_DIR/sherpa_onnx.xcframework"
376
+ if [ -d "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME" ]; then
377
+ echo -e "${YELLOW}[$DISPLAY_NAME] Removing old framework...${NC}" >&2
378
+ rm -rf "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME"
291
379
  fi
292
380
 
293
- # Extract the zip
294
- echo -e "${YELLOW}Extracting framework...${NC}" >&2
381
+ echo -e "${YELLOW}[$DISPLAY_NAME] Extracting framework...${NC}" >&2
295
382
  unzip -q -o "$zip_path" -d "$FRAMEWORKS_DIR"
296
383
 
297
- # Normalize name: podspec expects sherpa_onnx.xcframework; zip may contain sherpa-onnx.xcframework
298
- if [ -d "$FRAMEWORKS_DIR/sherpa-onnx.xcframework" ] && [ ! -d "$FRAMEWORKS_DIR/sherpa_onnx.xcframework" ]; then
384
+ # Normalize name: sherpa zip may contain sherpa-onnx.xcframework
385
+ if [ "$slug" = "sherpa-onnx" ] && [ -d "$FRAMEWORKS_DIR/sherpa-onnx.xcframework" ] && [ ! -d "$FRAMEWORKS_DIR/sherpa_onnx.xcframework" ]; then
299
386
  mv "$FRAMEWORKS_DIR/sherpa-onnx.xcframework" "$FRAMEWORKS_DIR/sherpa_onnx.xcframework"
300
387
  fi
301
388
 
302
- if [ ! -d "$FRAMEWORKS_DIR/sherpa_onnx.xcframework" ]; then
303
- echo -e "${RED}Error: Framework extraction failed${NC}" >&2
304
- echo "Contents of $FRAMEWORKS_DIR:" >&2
389
+ if [ ! -d "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME" ]; then
390
+ echo -e "${RED}Error: Framework extraction failed ($XCFRAMEWORK_NAME)${NC}" >&2
305
391
  ls -la "$FRAMEWORKS_DIR" 2>/dev/null | head -20 >&2 || true
306
392
  rm -f "$zip_path"
307
393
  return 1
308
394
  fi
309
395
 
310
- # Verify required headers are present (needed for iOS build: #include "sherpa-onnx/c-api/cxx-api.h")
311
- if ! framework_valid "$FRAMEWORKS_DIR/sherpa_onnx.xcframework"; then
312
- echo -e "${RED}Error: Downloaded framework is missing required headers for building.${NC}" >&2
313
- echo "Expected: $FRAMEWORKS_DIR/sherpa_onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h" >&2
314
- echo "Simulator Headers directory:" >&2
315
- ls -la "$FRAMEWORKS_DIR/sherpa_onnx.xcframework/ios-arm64_x86_64-simulator/Headers" 2>/dev/null || echo " (missing)" >&2
316
- if [ -d "$FRAMEWORKS_DIR/sherpa_onnx.xcframework/ios-arm64_x86_64-simulator/Headers" ]; then
317
- echo "sherpa-onnx/c-api under Headers:" >&2
318
- ls -la "$FRAMEWORKS_DIR/sherpa_onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api" 2>/dev/null || echo " (missing)" >&2
319
- fi
320
- rm -rf "$FRAMEWORKS_DIR/sherpa_onnx.xcframework"
396
+ if ! framework_valid "$slug" "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME"; then
397
+ echo -e "${RED}Error: Downloaded $DISPLAY_NAME framework is missing required libraries or headers.${NC}" >&2
398
+ echo "Expected e.g. $FRAMEWORKS_DIR/$XCFRAMEWORK_NAME/ios-arm64_x86_64-simulator/$HEADER_CHECK" >&2
399
+ rm -rf "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME"
321
400
  rm -f "$zip_path"
322
401
  return 1
323
402
  fi
324
403
 
325
- # Remove zip file
326
404
  rm -f "$zip_path"
327
-
328
- # Write version file
329
405
  echo "$version" > "$VERSION_FILE"
330
-
331
- echo -e "${GREEN}Framework v$version downloaded and extracted successfully${NC}" >&2
406
+ echo -e "${GREEN}[$DISPLAY_NAME] Framework v$version downloaded and extracted successfully${NC}" >&2
332
407
  return 0
333
408
  }
334
409
 
335
- # Force: remove existing framework and version file so we always re-download
410
+ # Force: remove existing frameworks and version files so we always re-download
336
411
  if [ "$FORCE_DOWNLOAD" = true ]; then
337
- [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}Force download: removing local framework and version file${NC}" >&2
338
- rm -rf "$FRAMEWORKS_DIR/sherpa_onnx.xcframework"
339
- rm -f "$VERSION_FILE"
412
+ [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}Force download: removing local frameworks and version files${NC}" >&2
413
+ for slug in "${FRAMEWORK_SLUGS[@]}"; do
414
+ get_framework_config "$slug" || exit 1
415
+ rm -rf "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME"
416
+ rm -f "$VERSION_FILE"
417
+ done
418
+ rm -f "$FRAMEWORKS_DIR/.framework-version"
340
419
  fi
341
420
 
342
- # Main logic
343
- if [ -n "$1" ]; then
344
- # User provided a specific version -> explicit, always honor
345
- download_and_extract_framework "$1"
346
- else
347
- # If env var was set, enforce that version and do not auto-upgrade to latest
348
- if [ -n "$DESIRED_VERSION" ]; then
349
- [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}Using SHERPA_ONNX_VERSION=$DESIRED_VERSION${NC}" >&2
350
- local_version=$(get_local_framework_version)
351
- if [ "$local_version" != "$DESIRED_VERSION" ] || [ "$FORCE_DOWNLOAD" = true ]; then
352
- [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}Downloading v$DESIRED_VERSION...${NC}" >&2
353
- download_and_extract_framework "$DESIRED_VERSION" || exit 1
354
- else
355
- [ "$INTERACTIVE" = true ] && echo -e "${GREEN}Framework is already v$local_version${NC}" >&2
356
- fi
357
- else
358
- # DESIRED_VERSION is set above from IOS_RELEASE_TAG (required).
359
- [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}Using pinned version from IOS_RELEASE_TAG.${NC}" >&2
360
- local_version=$(get_local_framework_version)
361
- if [ "$local_version" != "$DESIRED_VERSION" ] || [ "$FORCE_DOWNLOAD" = true ]; then
362
- download_and_extract_framework "$DESIRED_VERSION" || exit 1
363
- else
364
- [ "$INTERACTIVE" = true ] && echo -e "${GREEN}Framework is already v$local_version${NC}" >&2
365
- fi
421
+ # Main: download each framework that needs updating
422
+ for slug in "${FRAMEWORK_SLUGS[@]}"; do
423
+ get_framework_config "$slug" || exit 1
424
+ desired=$(get_desired_version "$slug")
425
+ # Sherpa: always ensure desired version (from TAG or $1). FFmpeg: only if TAG is set.
426
+ if [ -z "$desired" ]; then
427
+ [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}[$DISPLAY_NAME] No IOS_RELEASE_TAG version, skipping.${NC}" >&2
428
+ continue
366
429
  fi
367
- fi
430
+ local_ver=$(get_local_framework_version "$slug")
431
+ if [ "$local_ver" = "$desired" ] && [ "$FORCE_DOWNLOAD" != true ]; then
432
+ [ "$INTERACTIVE" = true ] && echo -e "${GREEN}[$DISPLAY_NAME] Framework is already v$local_ver${NC}" >&2
433
+ continue
434
+ fi
435
+ [ "$INTERACTIVE" = true ] && echo -e "${YELLOW}[$DISPLAY_NAME] Downloading v$desired...${NC}" >&2
436
+ download_and_extract_framework "$slug" "$desired" || exit 1
437
+ done
368
438
 
369
439
  if [ "$INTERACTIVE" = true ]; then
370
440
  echo "" >&2
371
441
  echo -e "${GREEN}Framework setup complete!${NC}" >&2
372
- echo "Framework location: $FRAMEWORKS_DIR/sherpa_onnx.xcframework" >&2
442
+ for slug in "${FRAMEWORK_SLUGS[@]}"; do
443
+ get_framework_config "$slug" || true
444
+ if [ -d "$FRAMEWORKS_DIR/$XCFRAMEWORK_NAME" ]; then
445
+ echo " $DISPLAY_NAME: $FRAMEWORKS_DIR/$XCFRAMEWORK_NAME" >&2
446
+ fi
447
+ done
373
448
  echo "" >&2
374
449
  echo "Next steps:" >&2
375
450
  echo " 1. cd example" >&2
376
451
  echo " 2. pod install" >&2
377
452
  echo " 3. Open ios/SherpaOnnxExample.xcworkspace in Xcode" >&2
378
453
  fi
454
+
455
+ # Fix CocoaPods header flattening: delete FFmpeg's time.h so it doesn't shadow system time.h
456
+ if [ -d "$FRAMEWORKS_DIR/FFmpeg.xcframework" ]; then
457
+ find "$FRAMEWORKS_DIR/FFmpeg.xcframework" -name "time.h" -path "*/libavutil/time.h" -delete 2>/dev/null || true
458
+ fi
459
+
379
460
  exit 0