Repository navigation
Add Swift API for Moonshine v2 models - #3240
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds Moonshine v2 ASR support for Swift: a new example and runner script, CI/test invocation and cleanup, a .gitignore entry, and an added Changes
Sequence DiagramsequenceDiagram
participant App as Swift App
participant Config as SherpaOnnx Config
participant Recognizer as SherpaOnnx OfflineRecognizer
participant Audio as WAV File
participant Result as Decode Result
App->>Config: build Moonshine model config\n(encoder, mergedDecoder)
App->>Config: build model & feature configs
App->>Recognizer: initialize(recognizerConfig)
App->>Audio: readWave(filePath)
Audio-->>App: samples, sampleRate
App->>Recognizer: decode(samples, sampleRate)
Recognizer-->>Result: recognition result (text, timestamps)
App->>Result: print output
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces Swift API support for Moonshine v2 automatic speech recognition (ASR) models. It includes updates to the core Swift API to accommodate new model configurations, a new example demonstrating how to use Moonshine v2 models, and corresponding build and test scripts to integrate these changes into the existing CI/CD pipeline. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
The pull request successfully integrates Swift API support for Moonshine v2 models. This includes adding a mergedDecoder parameter to the sherpaOnnxOfflineMoonshineModelConfig function, updating the .gitignore file to exclude generated Moonshine v2 artifacts, and introducing a new shell script and Swift example for testing the Moonshine v2 ASR model. The changes are well-contained and directly address the objective of adding this new model support.
| uncachedDecoder: String = "", | ||
| cachedDecoder: String = "" | ||
| cachedDecoder: String = "", | ||
| mergedDecoder: String = "" |
There was a problem hiding this comment.
The addition of mergedDecoder: String = "" to the function signature is correct for supporting Moonshine v2 models. However, for clarity and to align with the dual model support (v1 with uncachedDecoder and cachedDecoder, or v2 with mergedDecoder), consider adding a comment explaining that either the v1 decoders or the v2 merged decoder should be provided, but not both, to guide future usage.
|
|
||
| let modelConfig = sherpaOnnxOfflineModelConfig( | ||
| tokens: tokens, | ||
| debug: 1, |
There was a problem hiding this comment.
| if [ ! -f ./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/encoder_model.ort ]; then | ||
| echo "Please download the pre-trained model for testing." | ||
| echo "You can refer to" | ||
| echo "" | ||
| echo "https://k2-fsa.github.io/sherpa/onnx/moonshine/index.html" | ||
| echo "" | ||
| echo "for help" | ||
|
|
||
| curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2 | ||
| tar xvf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2 | ||
| rm sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2 | ||
| ls -lh sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27 |
There was a problem hiding this comment.
The model name sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27 is hardcoded in multiple places within this script (e.g., in the if condition, curl command, tar command, and ls command). This makes it cumbersome to update the model version or switch to a different model in the future. Consider defining this as a shell variable at the top of the script to centralize its definition.
| if [ ! -e ./moonshine-v2-asr ]; then | ||
| # Note: We use -lc++ to link against libc++ instead of libstdc++ | ||
| swiftc \ | ||
| -lc++ \ | ||
| -I ../build-swift-macos/install/include \ | ||
| -import-objc-header ./SherpaOnnx-Bridging-Header.h \ | ||
| ./moonshine-v2-asr.swift ./SherpaOnnx.swift \ | ||
| -L ../build-swift-macos/install/lib/ \ | ||
| -l sherpa-onnx \ | ||
| -l onnxruntime \ | ||
| -o moonshine-v2-asr | ||
|
|
||
| strip moonshine-v2-asr | ||
| else | ||
| echo "./moonshine-v2-asr exists - skip building" | ||
| fi |
There was a problem hiding this comment.
The Swift compilation and stripping logic (swiftc ... -o moonshine-v2-asr and strip moonshine-v2-asr) is duplicated across several run-*.sh scripts (e.g., run-fire-red-asr.sh). To improve maintainability and reduce redundancy, consider extracting this common build process into a shared shell function or a separate utility script that can be called by all example scripts.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
swift-api-examples/run-moonshine-v2-asr.sh (1)
18-20: Add artifact integrity verification for downloaded model archives.The script downloads and extracts a release artifact without checksum validation. Please verify SHA-256 before extraction to reduce supply-chain risk in CI/local runs.
🔐 Suggested hardening patch
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2 + # Please replace with the official SHA-256 from the release notes + expected_sha256="REPLACE_WITH_OFFICIAL_SHA256" + actual_sha256="$(shasum -a 256 sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2 | awk '{print $1}')" + [ "$actual_sha256" = "$expected_sha256" ] || { + echo "Checksum mismatch for moonshine model archive" + exit 1 + } tar xvf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@swift-api-examples/run-moonshine-v2-asr.sh` around lines 18 - 20, Add SHA-256 integrity verification for the downloaded artifact before extracting: after the curl that fetches sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2, obtain or define the expected SHA-256 (e.g., from a .sha256 file or an ENV variable), verify the blob using sha256sum -c or echo "<expected> sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2" | sha256sum -c --status, and only run tar xvf and rm if the checksum check succeeds; update the script flow around the curl/tar/rm commands to fail early with a clear error when verification fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@swift-api-examples/moonshine-v2-asr.swift`:
- Around line 28-31: Add a guard after calling SherpaOnnxWaveWrapper.readWave to
validate the returned audio before calling recognizer.decode: check that the
returned "audio" is non-nil (or that audio.samples is non-empty and
audio.sampleRate > 0), and if the check fails log/print a clear error mentioning
"filePath" and return/throw early instead of calling recognizer.decode(samples:
audio.samples, sampleRate: audio.sampleRate) to avoid an opaque crash.
---
Nitpick comments:
In `@swift-api-examples/run-moonshine-v2-asr.sh`:
- Around line 18-20: Add SHA-256 integrity verification for the downloaded
artifact before extracting: after the curl that fetches
sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2, obtain or define the
expected SHA-256 (e.g., from a .sha256 file or an ENV variable), verify the blob
using sha256sum -c or echo "<expected>
sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2" | sha256sum -c
--status, and only run tar xvf and rm if the checksum check succeeds; update the
script flow around the curl/tar/rm commands to fail early with a clear error
when verification fails.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.github/scripts/test-swift.shswift-api-examples/.gitignoreswift-api-examples/SherpaOnnx.swiftswift-api-examples/moonshine-v2-asr.swiftswift-api-examples/run-fire-red-asr.shswift-api-examples/run-moonshine-v2-asr.sh
| let filePath = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/test_wavs/0.wav" | ||
| let audio = SherpaOnnxWaveWrapper.readWave(filename: filePath) | ||
|
|
||
| let result = recognizer.decode(samples: audio.samples, sampleRate: audio.sampleRate) |
There was a problem hiding this comment.
Add a guard before decoding to avoid opaque crash behavior on missing input WAV.
At Line 29, reading the wave file is assumed to succeed. A simple pre-check gives a clearer failure message and avoids harder-to-debug crashes.
🩹 Suggested reliability guard
let filePath = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/test_wavs/0.wav"
+ guard FileManager.default.fileExists(atPath: filePath) else {
+ fatalError("Audio file not found: \(filePath)")
+ }
let audio = SherpaOnnxWaveWrapper.readWave(filename: filePath)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let filePath = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/test_wavs/0.wav" | |
| let audio = SherpaOnnxWaveWrapper.readWave(filename: filePath) | |
| let result = recognizer.decode(samples: audio.samples, sampleRate: audio.sampleRate) | |
| let filePath = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/test_wavs/0.wav" | |
| guard FileManager.default.fileExists(atPath: filePath) else { | |
| fatalError("Audio file not found: \(filePath)") | |
| } | |
| let audio = SherpaOnnxWaveWrapper.readWave(filename: filePath) | |
| let result = recognizer.decode(samples: audio.samples, sampleRate: audio.sampleRate) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@swift-api-examples/moonshine-v2-asr.swift` around lines 28 - 31, Add a guard
after calling SherpaOnnxWaveWrapper.readWave to validate the returned audio
before calling recognizer.decode: check that the returned "audio" is non-nil (or
that audio.samples is non-empty and audio.sampleRate > 0), and if the check
fails log/print a clear error mentioning "filePath" and return/throw early
instead of calling recognizer.decode(samples: audio.samples, sampleRate:
audio.sampleRate) to avoid an opaque crash.
There was a problem hiding this comment.
Pull request overview
Adds a Swift example and build/run script to exercise Moonshine v2 offline ASR models from the existing Swift C-API wrapper, and wires it into the Swift CI script.
Changes:
- Add
moonshine-v2-asr.swiftplus a correspondingrun-moonshine-v2-asr.shhelper that downloads the Moonshine v2 model bundle and runs decoding. - Extend
sherpaOnnxOfflineMoonshineModelConfig(...)inSherpaOnnx.swiftwith amergedDecoderfield to support Moonshine v2 configs. - Update Swift CI script to run the new Moonshine v2 example and adjust a FireRed ASR help URL.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
swift-api-examples/run-moonshine-v2-asr.sh |
New runnable script to download Moonshine v2 tiny model and build/run the Swift example. |
swift-api-examples/moonshine-v2-asr.swift |
New Swift offline ASR example using Moonshine v2 merged decoder. |
swift-api-examples/SherpaOnnx.swift |
Adds mergedDecoder support to the Moonshine offline model config builder. |
swift-api-examples/run-fire-red-asr.sh |
Updates the printed documentation URL for FireRed ASR. |
swift-api-examples/.gitignore |
Ignores the newly built moonshine-v2-asr binary. |
.github/scripts/test-swift.sh |
Runs the Moonshine v2 Swift example in CI and cleans up downloaded artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary by CodeRabbit
New Features
Tests
Documentation
Chores