Skip to content

Add Swift API for Moonshine v2 models - #3240

Merged
csukuangfj merged 2 commits into
k2-fsa:masterfrom
csukuangfj:swift-api-moonshine-v2
Feb 28, 2026
Merged

csukuangfj merged 2 commits into
k2-fsa:masterfrom
csukuangfj:swift-api-moonshine-v2

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Feb 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added Moonshine v2 ASR Swift example and a script to build/run the offline ASR demo.
  • Tests

    • Added a CI test step to run the Moonshine v2 ASR workflow and cleanup artifacts.
  • Documentation

    • Updated the Fire Red ASR help link.
  • Chores

    • Expanded .gitignore to exclude Moonshine v2 ASR artifacts.

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Feb 28, 2026
@csukuangfj
csukuangfj requested a review from Copilot February 28, 2026 03:52
@coderabbitai

coderabbitai Bot commented Feb 28, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58e5c63 and a36aa23.

📒 Files selected for processing (1)
  • swift-api-examples/SherpaOnnx.swift

📝 Walkthrough

Walkthrough

Adds Moonshine v2 ASR support for Swift: a new example and runner script, CI/test invocation and cleanup, a .gitignore entry, and an added mergedDecoder parameter in the Moonshine model config.

Changes

Cohort / File(s) Summary
CI & Scripts
/.github/scripts/test-swift.sh
Invoke the new run-moonshine-v2-asr.sh during Swift tests and remove sherpa-onnx-moonshine-* artifacts after running.
Example ignore
swift-api-examples/.gitignore
Add moonshine-v2-asr to the gitignore.
Swift API config
swift-api-examples/SherpaOnnx.swift
Add mergedDecoder: String = "" parameter to sherpaOnnxOfflineMoonshineModelConfig and propagate it to the underlying C config (merged_decoder).
Moonshine v2 example & runner
swift-api-examples/moonshine-v2-asr.swift, swift-api-examples/run-moonshine-v2-asr.sh
Add a new Swift example that configures and runs offline Moonshine/ONNX ASR and a shell script to download model artifacts, build the example, set runtime library path, and execute it.
Help text update
swift-api-examples/run-fire-red-asr.sh
Update help URL from pretrained_models/FireRedAsr/index.html to onnx/FireRedAsr/index.html.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size:M

Poem

🐰 Moonshine v2 hops into play,
Swift ears listen, decode the day,
Binaries built and scripts that sing,
Timestamps hop and text takes wing,
A rabbit cheers—ASR on its way!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: adding Swift API support for Moonshine v2 models, which is evidenced by the new example file, config updates, and build script.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, 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

  • Moonshine v2 Swift API: Added support for Moonshine v2 ASR models within the Swift API, specifically by introducing a 'mergedDecoder' parameter in the 'sherpaOnnxOfflineMoonshineModelConfig' function.
  • New Swift Example: Implemented a new Swift example ('moonshine-v2-asr.swift') to showcase the usage of Moonshine v2 models for offline speech recognition.
  • Automated Testing: Integrated the new Moonshine v2 example into the Swift test script ('test-swift.sh') and added a dedicated 'run-moonshine-v2-asr.sh' script for building and executing the example.
Changelog
  • .github/scripts/test-swift.sh
    • Added execution of 'run-moonshine-v2-asr.sh'.
    • Added cleanup for 'sherpa-onnx-moonshine-*' files.
  • swift-api-examples/.gitignore
    • Added 'moonshine-v2-asr' to the ignore list.
  • swift-api-examples/SherpaOnnx.swift
    • Modified 'sherpaOnnxOfflineMoonshineModelConfig' to accept a 'mergedDecoder' parameter.
  • swift-api-examples/moonshine-v2-asr.swift
    • Added a new Swift example file for Moonshine v2 ASR.
  • swift-api-examples/run-fire-red-asr.sh
    • Updated the URL for FireRed ASR pretrained models.
  • swift-api-examples/run-moonshine-v2-asr.sh
    • Added a new shell script to download Moonshine v2 models, build the Swift example, and run it.
Activity
  • No human activity recorded for this pull request.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 = ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The value 1 for the debug parameter is a magic number. It would improve readability and maintainability to use a named constant or an enum, or if debug is intended as a boolean, pass true or false directly if the underlying C API supports it, or define a constant like let debugEnabled = 1.

Comment on lines +10 to +21
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Comment on lines +24 to +39
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 66c4512 and 58e5c63.

📒 Files selected for processing (6)
  • .github/scripts/test-swift.sh
  • swift-api-examples/.gitignore
  • swift-api-examples/SherpaOnnx.swift
  • swift-api-examples/moonshine-v2-asr.swift
  • swift-api-examples/run-fire-red-asr.sh
  • swift-api-examples/run-moonshine-v2-asr.sh

Comment on lines +28 to +31
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.swift plus a corresponding run-moonshine-v2-asr.sh helper that downloads the Moonshine v2 model bundle and runs decoding.
  • Extend sherpaOnnxOfflineMoonshineModelConfig(...) in SherpaOnnx.swift with a mergedDecoder field 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.

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Feb 28, 2026
@csukuangfj
csukuangfj merged commit 8519d61 into k2-fsa:master Feb 28, 2026
1 check was pending
@csukuangfj
csukuangfj deleted the swift-api-moonshine-v2 branch February 28, 2026 04:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants