Skip to content

Add Dart API for FunASR Nano - #3055

Merged
csukuangfj merged 3 commits into
k2-fsa:masterfrom
csukuangfj:dart-api-funasr-nano
Jan 15, 2026
Merged

csukuangfj merged 3 commits into
k2-fsa:masterfrom
csukuangfj:dart-api-funasr-nano

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Jan 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added support for FunASR Nano offline speech recognition model to the Dart API with full configuration options
    • Provided example scripts demonstrating FunASR Nano model initialization and usage
  • Tests

    • Reorganized test script execution to include expanded model test coverage

✏️ Tip: You can customize this high-level summary in your review settings.

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

coderabbitai Bot commented Jan 15, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This change adds FunASR Nano offline speech recognition model support to the Dart/Flutter bindings. It introduces new configuration structs with JSON serialization, native conversion logic, and memory management across multiple layers. New example code and test scripts are provided to demonstrate usage.

Changes

Cohort / File(s) Summary
Test Infrastructure
.github/scripts/test-dart.sh
Reorganizes test execution order: moves non-streaming-asr, tts, and vad blocks into a dedicated section, then reintroduces them later in streaming context. Replaces previous zh-tts section with FunASR Nano invocation.
Dart Example Code
dart-api-examples/non-streaming-asr/bin/funasr-nano.dart
New CLI script that initializes FunASR Nano model configuration, parses encoder-adaptor, llm, embedding, and tokenizer file paths from command-line args, creates OfflineRecognizer, performs decoding on input WAV, and cleans up resources.
Dart Run Script
dart-api-examples/non-streaming-asr/run-funasr-nano.sh
New Bash script for environment setup and execution. Conditionally downloads sherpa-onnx-funasr-nano model bundle, runs dart pub get, and executes the FunASR Nano Dart binary with model artifacts.
Flutter FFI Config Struct
flutter/sherpa_onnx/lib/src/offline_recognizer.dart
Introduces OfflineFunAsrNanoModelConfig class with encoder-adaptor, llm, embedding, tokenizer, system/user prompts, and model hyperparameters. Extends OfflineModelConfig to include funasrNano field with JSON serialization, native conversion (convertConfig), and memory freeing (freeConfig).
Flutter FFI Bindings
flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart
Adds SherpaOnnxOfflineFunAsrNanoModelConfig FFI struct with external pointers and typed fields. Extends SherpaOnnxOfflineModelConfig with funasrNano field for FFI interop.
C API Header
sherpa-onnx/c-api/c-api.h
Adds blank line separator between struct declarations (formatting only).

Sequence Diagram(s)

sequenceDiagram
    participant App as Dart App
    participant Config as OfflineFunAsrNanoModelConfig
    participant Offline as OfflineModelConfig
    participant Recognizer as OfflineRecognizer
    participant FFI as Native C-API
    
    App->>Config: Create with encoder-adaptor,<br/>llm, embedding, tokenizer
    App->>Offline: Create with funasrNano
    App->>Recognizer: Initialize with OfflineModelConfig
    Recognizer->>FFI: convertConfig() - populate<br/>SherpaOnnxOfflineFunAsrNanoModelConfig
    FFI-->>Recognizer: Native config ready
    App->>Recognizer: Decode audio stream
    Recognizer->>FFI: Process & transcribe
    FFI-->>Recognizer: Transcription result
    App->>Recognizer: Cleanup
    Recognizer->>FFI: freeConfig() - deallocate<br/>native pointers
    FFI-->>Recognizer: Resources freed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

size:L

Poem

🐰 Nano dreams with whispered words,
Through Dart and FFI layers blur'd,
Config cascades in structs so neat,
From Dart to C, a speech-to-text feat! 🎤✨
Memory dances, freed with care,
FunASR flies through digital air!

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eeab397 and 263d343.

📒 Files selected for processing (6)
  • .github/scripts/test-dart.sh
  • dart-api-examples/non-streaming-asr/bin/funasr-nano.dart
  • dart-api-examples/non-streaming-asr/run-funasr-nano.sh
  • flutter/sherpa_onnx/lib/src/offline_recognizer.dart
  • flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart
  • sherpa-onnx/c-api/c-api.h

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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 @csukuangfj, 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 significantly enhances the Dart API of the sherpa-onnx library by adding comprehensive support for the FunASR Nano model. It provides the necessary Dart-side configuration classes, a practical example demonstrating its usage for offline speech recognition, and integrates this new functionality into the project's automated testing pipeline. This allows Dart developers to seamlessly incorporate the FunASR Nano model into their applications, broadening the capabilities of the sherpa-onnx Dart package.

Highlights

  • New Dart API for FunASR Nano: Introduced the OfflineFunAsrNanoModelConfig class within the Dart sherpa_onnx package, enabling Dart applications to configure and utilize the FunASR Nano model for speech recognition.
  • Example Usage Script: Added a new Dart example script (funasr-nano.dart) that demonstrates how to load, configure, and perform offline speech recognition using the FunASR Nano model with a sample audio file.
  • Automated Testing Integration: Integrated the FunASR Nano example into the .github/scripts/test-dart.sh CI script, ensuring that its functionality is automatically tested and validated as part of the continuous integration process.
  • FFI Bindings and Memory Management: Updated the FFI bindings (sherpa_onnx_bindings.dart) to expose the FunASR Nano model configuration to Dart, and modified offline_recognizer.dart to correctly handle the initialization and memory deallocation of its native C API parameters.
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. ↩

@csukuangfj
csukuangfj merged commit 67b2254 into k2-fsa:master Jan 15, 2026
2 of 21 checks passed
@csukuangfj
csukuangfj deleted the dart-api-funasr-nano branch January 15, 2026 07:54

@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 Dart API support for FunASR Nano, including a new example application and updates to the core Dart bindings. The changes are well-structured and follow the existing patterns for adding new models. I have a couple of suggestions for the new example file to improve argument handling and ensure robust resource management. Overall, this is a great addition.

Comment on lines +49 to +64
final recognizer = sherpa_onnx.OfflineRecognizer(config);

final waveData = sherpa_onnx.readWave(inputWav);
final stream = recognizer.createStream();

stream.acceptWaveform(
samples: waveData.samples,
sampleRate: waveData.sampleRate,
);
recognizer.decode(stream);

final result = recognizer.getResult(stream);
print(result.text);

stream.free();
recognizer.free();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The recognizer and stream resources are manually freed at the end of the main function. If an exception occurs during processing (e.g., while reading the wave file or during decoding), these resources will not be freed, leading to a memory leak. It's safer to use a try...finally block to ensure resources are always released.

  sherpa_onnx.OfflineRecognizer? recognizer;
  sherpa_onnx.OfflineStream? stream;
  try {
    recognizer = sherpa_onnx.OfflineRecognizer(config);

    final waveData = sherpa_onnx.readWave(inputWav);
    stream = recognizer.createStream();

    stream.acceptWaveform(
      samples: waveData.samples,
      sampleRate: waveData.sampleRate,
    );
    recognizer.decode(stream);

    final result = recognizer.getResult(stream);
    print(result.text);
  } finally {
    stream?.free();
    recognizer?.free();
  }

Comment on lines +20 to +27
if (res['encoder-adaptor'] == null ||
res['llm'] == null ||
res['embedding'] == null ||
res['tokenizer'] == null ||
res['input-wav'] == null) {
print(parser.usage);
exit(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 current argument validation works, but it could be improved to provide more specific feedback to the user about which required option is missing. This would enhance the command-line usability of this example.

Suggested change
if (res['encoder-adaptor'] == null ||
res['llm'] == null ||
res['embedding'] == null ||
res['tokenizer'] == null ||
res['input-wav'] == null) {
print(parser.usage);
exit(1);
}
const requiredOptions = [
'encoder-adaptor',
'llm',
'embedding',
'tokenizer',
'input-wav',
];
var optionsOk = true;
for (final opt in requiredOptions) {
if (res[opt] == null) {
print('Missing required argument: --$opt');
optionsOk = false;
}
}
if (!optionsOk) {
print(parser.usage);
exit(1);
}

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.

1 participant