Skip to content

Add Paraformer Rust API example add rust paraformer example - #3707

Merged
csukuangfj merged 6 commits into
k2-fsa:masterfrom
nati2405:add-rust-paraformer-example
Jul 29, 2026
Merged

csukuangfj merged 6 commits into
k2-fsa:masterfrom
nati2405:add-rust-paraformer-example

Conversation

@nati2405

@nati2405 nati2405 commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR adds a non-streaming Paraformer example for the Rust API in sherpa-onnx. The example shows how to load the Paraformer model, tokens file, and a WAV file, then run offline speech recognition and print the decoded text. I also added a small performance summary so users can see the audio duration, recognition time, and real-time factor.

Why was this PR needed?

The project already had a Paraformer example for the C API, but I noticed there was not a matching non-streaming Paraformer example in the Rust API examples folder. Since issue #3210 asks for more Rust API examples, I focused on the Paraformer part and used c-api-examples/paraformer-c-api.c as my main reference.

This should make it easier for Rust users to understand how to run a Paraformer ASR model with sherpa-onnx.

Relevant issue

Addresses part of #3210.

What changed?

  • Added rust-api-examples/examples/paraformer.rs
  • Added rust-api-examples/run-paraformer.sh
  • Updated rust-api-examples/README.md to include the new Paraformer example
  • Added run-paraformer.sh to .github/scripts/test-rust.sh
  • Updated the run script so it works from its own directory and supports both wget and curl
  • Added safer handling for zero-duration audio and missing recognition results

Testing

I tested that the new example compiles with:

cargo check --example paraformer

I also tested it locally with the Paraformer model package using:

cargo run --example paraformer -- --model ./sherpa-onnx-paraformer-zh-small-2024-03-09/model.int8.onnx --tokens ./sherpa-onnx-paraformer-zh-small-2024-03-09/tokens.txt --wav ./sherpa-onnx-paraformer-zh-small-2024-03-09/test_wavs/0.wav

The example ran successfully and produced decoded text along with the performance summary.

Checklist

  • New Rust example added
  • Helper run script added
  • Example compiles with cargo check --example paraformer
  • Example runs locally with the Paraformer model and WAV file
  • README updated
  • Test script updated
  • Review feedback addressed
  • No downloaded model files included

Summary by CodeRabbit

  • New Features
    • Added an offline (non-streaming) Rust Paraformer speech recognition example that runs from WAV input and reports decoded text plus performance metrics (including real-time factor).
    • Included command-line options for audio, model, and token paths, execution provider, debug mode, and thread count.
  • Documentation
    • Updated the Rust examples README with instructions for running the Paraformer example.
  • Tests
    • Extended the Rust test workflow to run the Paraformer script and clean up downloaded model artifacts.
  • Chores
    • Added a helper script to download the required Paraformer model and execute the example.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 906585f7-afe3-44c1-bfcb-2900ad20bd3c

📥 Commits

Reviewing files that changed from the base of the PR and between ed767b9 and da4f4a2.

📒 Files selected for processing (1)
  • rust-api-examples/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • rust-api-examples/README.md

📝 Walkthrough

Walkthrough

Adds an offline Paraformer speech-recognition Rust example, a model-download runner script, README usage documentation, and Rust test-script integration with cleanup.

Changes

Paraformer Rust Example

Layer / File(s) Summary
CLI, recognizer setup, and recognition output
rust-api-examples/examples/paraformer.rs
Adds CLI options, loads audio, configures the offline recognizer, runs recognition, and prints decoded text with timing and RTF metrics.
Model download and example invocation
rust-api-examples/run-paraformer.sh
Downloads and extracts the Paraformer model when absent, then runs the Rust example with model files and test audio.
Documentation and test integration
rust-api-examples/README.md, .github/scripts/test-rust.sh
Documents the Paraformer example and runs it in the Rust test script with artifact cleanup.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RunScript
  participant ParaformerExample
  participant OfflineRecognizer
  RunScript->>ParaformerExample: pass WAV, model, and tokens paths
  ParaformerExample->>OfflineRecognizer: create configured recognizer
  ParaformerExample->>OfflineRecognizer: accept waveform and decode
  OfflineRecognizer-->>ParaformerExample: return recognition result
Loading

Possibly related PRs

Suggested reviewers: csukuangfj

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding a Paraformer Rust API example.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@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

This pull request introduces a new Rust example (paraformer.rs) and an accompanying runner script (run-paraformer.sh) to demonstrate offline speech recognition using the Paraformer model with the sherpa-onnx Rust API. The feedback highlights a few key improvements: updating the main README.md to document this new example, handling a potential division-by-zero error when calculating the Real-Time Factor (RTF) with zero-duration audio, and improving the portability of the download script by supporting both wget and curl.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

// This file demonstrates how to use non-streaming Paraformer with
// sherpa-onnx's Rust API for offline speech recognition.
//
// See ../README.md for how to run it.

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 comment mentions See ../README.md for how to run it., but rust-api-examples/README.md has not been updated in this pull request to include the new Paraformer example. Please update rust-api-examples/README.md to add this example to the table of examples and the 'Run it' section.

println!("Decoded text: {}", result.text);

let total_time = creation_elapsed + recognition_elapsed;
let rtf = recognition_elapsed / audio_duration;

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

If audio_duration is 0.0 (e.g., if the WAV file contains no samples or has an invalid sample rate of 0), dividing recognition_elapsed by audio_duration will result in a division by zero, producing NaN or Infinity. Consider adding a guard to handle this case safely.

Suggested change
let rtf = recognition_elapsed / audio_duration;
let rtf = if audio_duration > 0.0 {
recognition_elapsed / audio_duration
} else {
0.0
};

Comment thread rust-api-examples/run-paraformer.sh Outdated
model=sherpa-onnx-paraformer-zh-small-2024-03-09

if [ ! -d $model ]; then
wget $repo_url/$model.tar.bz2

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

Using only wget can cause the script to fail on systems where wget is not installed by default (such as macOS). Consider checking for both wget and curl to make the script more portable.

Suggested change
wget $repo_url/$model.tar.bz2
if command -v wget &>/dev/null; then
wget $repo_url/$model.tar.bz2
elif command -v curl &>/dev/null; then
curl -OL $repo_url/$model.tar.bz2
else
echo "Error: Neither wget nor curl found. Please install one of them."
exit 1
fi

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rust-api-examples/examples/paraformer.rs`:
- Around line 97-99: The failure branch in paraformer.rs only logs the missing
recognition result and then allows the example to exit successfully. Update the
error path in the recognition result handling block so it terminates the process
with a non-zero exit code when decoding returns no result. Use the existing
result-handling logic around the Paraformer recognition flow to ensure the
failure is propagated to run-paraformer.sh.

In `@rust-api-examples/run-paraformer.sh`:
- Around line 8-17: Anchor the run-paraformer.sh script to its own directory
before using any relative paths, since the current $model, wget, tar, and cargo
run references are resolved from the caller’s CWD instead of the script
location. Update the script to determine its directory first and then build all
model, download, and example paths relative to that location so running the
script from anywhere still downloads/extracts into rust-api-examples and passes
correct paths to cargo run. Refer to the existing $model setup and the final
cargo run invocation when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 61e24793-8aad-4a59-b2ff-4a161dca9eb9

📥 Commits

Reviewing files that changed from the base of the PR and between 49ebd5b and 9f1b0a1.

📒 Files selected for processing (2)
  • rust-api-examples/examples/paraformer.rs
  • rust-api-examples/run-paraformer.sh

Comment thread rust-api-examples/examples/paraformer.rs
Comment thread rust-api-examples/run-paraformer.sh Outdated
Comment thread rust-api-examples/examples/paraformer.rs Outdated
// This file demonstrates how to use non-streaming Paraformer with
// sherpa-onnx's Rust API for offline speech recognition.
//
// See ../README.md for how to run it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

../README.md is not updated for your changes. Can you update it?

@@ -0,0 +1,17 @@
#!/usr/bin/env bash

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@csukuangfj

Copy link
Copy Markdown
Collaborator

@nati2405

Could you fix the comments?

@LauraGPT

LauraGPT commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

I checked the review comments against the current head and they still look actionable. A small update should be enough to unblock this PR:

  1. Make the no-result path fail the example instead of exiting successfully.
  2. Guard RTF calculation against zero-duration WAV input.
  3. Anchor run-paraformer.sh to the script directory and support curl when wget is unavailable.
  4. Add the new example to rust-api-examples/README.md so it appears in the examples table and command list.

For the Rust file, the smallest style-compatible change is probably:

if audio_duration <= 0.0 {
    eprintln!("WAV file has no samples");
    std::process::exit(1);
}

// ... after decode
let Some(result) = stream.get_result() else {
    eprintln!("Failed to get recognition result");
    std::process::exit(1);
};

println!("Decoded text: {}", result.text);

For the runner script, this pattern would address the CWD and downloader comments:

#!/usr/bin/env bash
set -ex

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$script_dir"

repo_url=https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models
model=sherpa-onnx-paraformer-zh-small-2024-03-09
archive="$model.tar.bz2"

if [ ! -d "$model" ]; then
  if command -v wget >/dev/null 2>&1; then
    wget -O "$archive" "$repo_url/$archive"
  elif command -v curl >/dev/null 2>&1; then
    curl -L -o "$archive" "$repo_url/$archive"
  else
    echo "Please install wget or curl" >&2
    exit 1
  fi
  tar xvf "$archive"
  rm "$archive"
fi

cargo run --example paraformer --   --model "./$model/model.int8.onnx"   --tokens "./$model/tokens.txt"   --wav "./$model/test_wavs/0.wav"

README placement: add paraformer near the other non-streaming ASR examples, e.g. after FireRedASR CTC or before SenseVoice, and add a section with:

./run-paraformer.sh

That should cover the maintainer's "fix the comments" request without changing the example's core API usage.

@nati2405

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I updated the Rust API README to include the Paraformer example, added a guard for zero-duration audio before calculating RTF, made the no-result path exit with a non-zero status, updated run-paraformer.sh to resolve paths from the script directory while supporting both wget and curl, and added run-paraformer.sh to .github/scripts/test-rust.sh. And I fixed the comment.

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rust-api-examples/README.md`:
- Line 94: Add a blank line immediately after the examples table entry ending
with the paraformer row and before the following README content, resolving the
markdownlint MD058 violation without changing the table content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 61219ce4-3dba-41e9-8b89-4998c6f3c2ce

📥 Commits

Reviewing files that changed from the base of the PR and between 9f1b0a1 and 7e46b86.

📒 Files selected for processing (4)
  • .github/scripts/test-rust.sh
  • rust-api-examples/README.md
  • rust-api-examples/examples/paraformer.rs
  • rust-api-examples/run-paraformer.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • rust-api-examples/run-paraformer.sh
  • rust-api-examples/examples/paraformer.rs

Comment thread rust-api-examples/README.md Outdated
@csukuangfj

Copy link
Copy Markdown
Collaborator

Can you fix the merge conflicts?

@nati2405
nati2405 force-pushed the add-rust-paraformer-example branch from ac045c4 to ed767b9 Compare July 27, 2026 22:38
@nati2405

Copy link
Copy Markdown
Contributor Author

Thanks, I rebased my branch on the latest upstream master and resolved the README merge conflict. I kept the new upstream README entries and updated the Paraformer entry/section numbering so it does not conflict with the newer examples.

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rust-api-examples/README.md`:
- Line 96: Update the Paraformer index row to link to the Example 51 heading
anchor, replacing the incorrect example-49 anchor while preserving the existing
label and description.
- Around line 94-97: Resolve the merge conflict in the README Examples table by
removing the literal conflict markers and retaining the intended Paraformer
entry as a valid Markdown table row. Ensure the surrounding table remains
correctly formatted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 174def7b-975a-4758-ae44-fd99acc5847b

📥 Commits

Reviewing files that changed from the base of the PR and between ac045c4 and ed767b9.

📒 Files selected for processing (4)
  • .github/scripts/test-rust.sh
  • rust-api-examples/README.md
  • rust-api-examples/examples/paraformer.rs
  • rust-api-examples/run-paraformer.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/scripts/test-rust.sh
  • rust-api-examples/run-paraformer.sh
  • rust-api-examples/examples/paraformer.rs

Comment thread rust-api-examples/README.md Outdated
Comment thread rust-api-examples/README.md Outdated
@csukuangfj

Copy link
Copy Markdown
Collaborator

Thanks!

@csukuangfj
csukuangfj merged commit 88bbc82 into k2-fsa:master Jul 29, 2026
1 check passed
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.

3 participants