sherpa-onnx Flutter 集成入门:hello_world 示例从零跑通 sherpa_onnx 包并验证版本信息
sherpa-onnx Flutter 集成入门hello_world 示例从零跑通 sherpa_onnx 包并验证版本信息【免费下载链接】sherpa-onnxSpeech-to-text, text-to-speech, speaker diarization, speech enhancement, source separation, and VAD using next-gen Kaldi with onnxruntime without Internet connection. Support embedded systems, Android, iOS, HarmonyOS, Raspberry Pi, RISC-V, RK NPU, Axera NPU, Ascend NPU, x86_64 servers, websocket server/client, support 12 programming languages项目地址: https://gitcode.com/GitHub_Trending/sh/sherpa-onnx本文基于仓库中的 hello_world 示例文档带你从零创建一个最小 Flutter 工程接入sherpa_onnx包当前仓库版本 1.13.7在 macOS、iOS、Android、Linux、Windows 和 Web 平台上运行并读懂示例背后initBindings、动态库加载与 WebAssembly 三套初始化路径的真实实现。读完后你能独立搭建一个可复现的 Flutter sherpa-onnx 工程骨架并知道后续接入语音识别、TTS、VAD 等功能时初始化与平台限制该怎么处理。一、这个示例的定位验证 sherpa-onnx 在 Flutter 中“活”起来了hello_world是 flutter-examples 目录下的第一个示例其定位在 flutter-examples/README.md 中写得很明确“Readhello_worldfirst to learn how to initialize sherpa-onnx in a Flutter app”。它不加载任何模型、不采集任何音频只做一件事在界面中央显示四行版本信息——sherpa-onnx 版本号getVersion()编译时的 Git SHA1getGitSha1()编译时的 Git 日期getGitDate()底层 onnxruntime 版本getOnnxruntimeVersion()之所以选择“版本信息”作为首个示例是因为它是最小闭环一旦页面能打印出这四行内容就证明 Dart 侧的 FFI 绑定、原生插件或 Web 下的 WASM 模块、以及底层 C API 三方全部打通。它是接入 ASR/TTS/VAD 等重功能前的冒烟测试。对应的实际工程文件为 lib/main.dart 与 pubspec.yaml二者与下文步骤给出的代码一致可作为交叉验证的对照物。二、四步创建示例工程第一步创建 Flutter 项目cd flutter-examples flutter create --project-name hello_world --org com.k2fsa hello_world--org com.k2fsa决定 Android/iOS 的应用包名前缀。第二步添加 sherpa_onnx 依赖编辑pubspec.yaml将dependencies:段替换为dependencies: flutter: sdk: flutter sherpa_onnx: ^1.13.4然后执行cd hello_world flutter pub get仓库当前示例锁定的是精确版本 pubspec.yamlversion: 1.13.7 environment: sdk: 3.2.0 4.0.0 flutter: 3.24.0 dependencies: flutter: sdk: flutter sherpa_onnx: 1.13.7 # sherpa_onnx: # path: ../../flutter/sherpa_onnx两个细节值得注意环境约束要求 Dart SDK3.2.0 4.0.0、Flutter3.24.0使用更老的 Flutter 版本会在pub get阶段直接失败注释里保留了一条path: ../../flutter/sherpa_onnx的本地依赖写法。从 flutter/README.md 可以看到flutter/目录是包开发者自己用的源码目录“You are not expected to use this directory directly”普通用户应使用 pub.dev 上发布的sherpa_onnx包只有需要修改插件源码时才需要切换到 path 依赖。第三步替换 lib/main.dartimport package:flutter/material.dart; import package:sherpa_onnx/sherpa_onnx.dart; void main() { WidgetsFlutterBinding.ensureInitialized(); initBindings(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); override Widget build(BuildContext context) { return MaterialApp( title: sherpa-onnx hello world, home: const VersionPage(), ); } } class VersionPage extends StatelessWidget { const VersionPage({super.key}); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(sherpa-onnx hello world)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(sherpa-onnx version: ${getVersion()}), Text(Git SHA1: ${getGitSha1()}), Text(Git date: ${getGitDate()}), Text(onnxruntime version: ${getOnnxruntimeVersion()}), ], ), ), ); } }仓库中当前的 lib/main.dart 在此基础上略有演进main()改为async使用await initBindingsAsync()并附带了关键注释——// Works on all platforms: loads native lib on desktop/mobile, WASM on web. // IMPORTANT: You must call initBindingsAsync() in every isolate that uses // sherpa-onnx APIs — including the main isolate and any worker isolates. await initBindingsAsync();这说明初始化 API 有两点设计意图跨平台统一入口同一行代码在桌面/移动端走原生动态库在 Web 走 WASM调用方不需要区分平台每个 isolate 必须单独初始化flutter-examples/README.md 在“Initialization”一节中强调每个 isolate 拥有独立的 FFI 绑定状态在一个 isolate 里调用initBindings()并不会让其他 isolate 可用。这是 Flutter 中 FFI 场景的典型坑后续示例如 vad-from-microphone中的音频工作 isolate 都需要各自初始化一次。第四步运行flutter run运行成功后App 界面会显示 sherpa-onnx 版本、Git SHA1、Git 日期和 onnxruntime 版本四行文本表示绑定链路全部打通。三、版本信息 API 背后从 Dart 到 C 的调用链示例页面调用的四个函数都定义在 flutter/sherpa_onnx/lib/src/version.dart 中实现模式完全一致通过 FFI 调用 C API 返回的PointerUtf8转成 Dart 字符串空指针则返回空串String getVersion() { PointerUtf8 version SherpaOnnxBindings.getVersionStr?.call() ?? nullptr; if (version nullptr) { return ; } return version.toDartString(); }getGitSha1()、getGitDate()、getOnnxruntimeVersion()分别对应SherpaOnnxBindings中的getGitSha1、getGitDate、getOnnxruntimeVersionStr。这些 FFI 签名集中在 sherpa_onnx_bindings.dart全文件约 2900 行覆盖 ASR、TTS、VAD、标点恢复等全部 C API 结构体与函数。因此“版本显示”这个最小示例实际上验证了整条 FFI 绑定链路是否可用这也是它被选为入门示例的原因。四、initBindings 的跨平台真相动态库加载与 WASM 双路径initBindings()在不同编译目标下走完全不同的底层路径源码用条件导入init_native.dart/init_stub.dart区分了这两条世界线。原生平台按操作系统加载不同的动态库flutter/sherpa_onnx/lib/src/init_native.dart 中loadDylib()按平台分支加载平台加载方式macOS无显式路径时走DynamicLibrary.process()符号已链入主可执行文件有路径时打开 xcframework 内的libsherpa-onnx-c-api.dylibiOSDynamicLibrary.process()静态链入 AppAndroid / Linux打开libsherpa-onnx-c-api.soWindows打开sherpa-onnx-c-api.dll其他抛出UnsupportedError加载完成后调用SherpaOnnxBindings.init(dylib)完成所有 C API 符号的查找与绑定。这也解释了 flutter-examples/README.md 中的说法“No path argument is needed. The native library is linked into the app bundle by the Flutter build system.”各平台的原生库分别打包在flutter/下的平台子包中从 flutter/sherpa_onnx/pubspec.yaml 的依赖列表可以确认完整矩阵sherpa_onnx_android_arm64、sherpa_onnx_android_armeabi、sherpa_onnx_android_x86、sherpa_onnx_android_x86_64、sherpa_onnx_ios、sherpa_onnx_linux、sherpa_onnx_macos、sherpa_onnx_web、sherpa_onnx_windows且插件配置将各平台的default_package一一映射到了对应子包。Web 平台Emscripten 编译的 WASM 模块Web 下 init_native.dart 被 init_stub.dart 替代——后者中的SherpaOnnxWeb.loadWasm()是个空壳真正的加载由sherpa_onnx_web插件完成。Web 侧初始化实现在 flutter/sherpa_onnx/lib/src/web/init.dartJSObject getModule() { if (_module ! null) return _module!; final module globalContext.getProperty(Module.toJS); if (module ! null) { _module module as JSObject; return _module!; } throw StateError( WASM module not loaded. Call SherpaOnnxWeb.loadWasm() first., ); }它依赖sherpa_onnx_web插件把 Emscripten 编译出的全局Module对象挂到 JS 全局作用域上Dart 侧通过dart:js_interop取回。也就是说 Web 构建是用 Emscripten 把 sherpa-onnx 的 C API 整体编译成 WebAssembly在浏览器中直接运行不需要任何服务端参与。README 中关于 Web 的三条注意事项仍然成立WASM 二进制约 15–20 MB因为包含 ASR、TTS、VAD 等全部功能首次加载需要数秒下载并编译 WASM 模块。五、平台限制一览文档在 “Platform notes” 一节给出的各平台最低要求如下搭建工程前先对照检查平台最低要求macOS部署目标最低 10.15iOS部署目标最低 13.0Android最低 SDK 21默认Linux支持 x64 与 aarch64Windows支持 x64若 Android 端出现minSdk报错可按 flutter-examples/README.md 的建议修改android/app/build.gradleandroid { defaultConfig { minSdk 23 } }另外若后续示例要使用麦克风iOS 还需要在ios/Runner/Info.plist中添加NSMicrophoneUsageDescriptionhello_world 本身不涉及。六、各平台构建命令# macOS flutter build macos # iOS (no codesign for CI) flutter build ios --no-codesign # Android flutter build apk # Linux flutter build linux # Windows flutter build windows补充各平台的本地运行方式来自 flutter-examples/README.md# macOS flutter run -d macos # iOS真机需有效的 Apple 开发者证书 flutter run -d device-id # Android flutter run -d device-id # Linux需先启用桌面支持 flutter config --enable-linux-desktop flutter run -d linux # Windows flutter run -d windows # Web flutter run -d chrome七、在浏览器中运行与部署本地运行cd flutter-examples/hello_world flutter pub get flutter run -d chrome构建部署产物flutter build web产物输出在build/web/目录用任意静态 HTTP 服务器分发即可cd build/web python3 -m http.server 8080然后浏览器访问http://localhost:8080。说明Web 构建通过 Emscripten 将 sherpa-onnx C API 编译为 WebAssembly 在浏览器中执行无服务端处理WASM 产物约 15–20 MB因为它打包了全部功能ASR、TTS、VAD 等首次打开页面需数秒完成 WASM 的下载与编译之后的版本信息展示逻辑与原生平台完全一致getVersion()等函数在 Web 下经由 JS 互操作调用同一个 WASM 模块内的 C API。八、iOS 模拟器运行与常见故障排查查看可用模拟器xcrun simctl list devices找出已启动Booted的模拟器例如iPhone 16 Plus (UUID) (Booted)在模拟器上运行flutter run -d UUID例如flutter run -d 34FB0674-4ABA-4870-ABF2-D0D6E110A7C2故障排查ld: framework sherpa_onnx not found看到这个链接错误说明 Xcode 工程里残留了过期的 Swift Package ManagerSPM引用。两种处理方式进入ios/目录手动编辑Runner.xcodeproj/project.pbxproj删除FlutterGeneratedPluginSwiftPackage相关条目或者干脆重新生成 iOS 工程flutter clean flutter pub get flutter run -d UUID从源码结构看iOS 端的原生库是静态链入主工程的DynamicLibrary.process()即可解析符号见第四节因此这类问题基本只出现在工程文件被工具反复改写后产生的 SPM 残留引用上而不是库本身缺失。九、从 hello_world 走向完整功能hello_world 只做了“绑定初始化 版本查询”下一步接入真正模型时的两条铁律来自 flutter-examples/README.md建议现在就记住每个 isolate 都要初始化。使用 sherpa-onnx API 的每个 isolate包括主 isolate 与音频工作 isolate都必须调用initBindings()或initBindingsAsync()参考 vad-from-microphone 中的 isolate 写法模型必须走 assets 拷贝。Flutter 应用运行在沙箱中不能直接访问任意文件路径。标准流程是把模型文件加入pubspec.yaml的flutter: assets:运行时用rootBundle.load()读出字节并写入getApplicationDocumentsDirectory()下的可写目录再把拷贝后的路径填进各类 Config。示例代码FutureString copyAsset(String assetPath, String fileName) async { final dir await getApplicationDocumentsDirectory(); final file File(${dir.path}/$fileName); if (!await file.exists()) { final data await rootBundle.load(assetPath); await file.writeAsBytes(data.buffer.asUint8List()); } return file.path; }按 flutter-examples/README.md 的指引掌握这两点后即可继续阅读 streaming_asr流式识别、non_streaming_vad_asrVAD 非流式识别、tts语音合成、vad-from-file 与 vad-from-microphone 等完整示例。十、小结主题要点依据接入方式pub.dev 包sherpa_onnx当前 1.13.7一行依赖 initBindingsAsync()初始化pubspec.yaml、lib/main.dart版本 APIgetVersion()/getGitSha1()/getGitDate()/getOnnxruntimeVersion()经 FFI 调用 C APIversion.dart平台矩阵macOS/iOS/Android/Linux/Windows/Web 六端原生平台 FFI 加载动态库Web 走 Emscripten WASMinit_native.dart、web/init.dart平台下限macOS 10.15 / iOS 13.0 / Android minSdk 21 / Linux x64aarch64 / Windows x64hello_world README常见坑每个 isolate 单独初始化iOS 工程 SPM 残留引用导致 framework not foundflutter clean重建flutter-examples README、hello_world READMEhello_world 的价值在于用不到百行代码打通了 Flutter 与 sherpa-onnx 的全部绑定链路跑通它之后你验证的不只是一个版本页面而是后续所有语音功能所依赖的初始化、FFI 与跨平台库加载基础设施。【免费下载链接】sherpa-onnxSpeech-to-text, text-to-speech, speaker diarization, speech enhancement, source separation, and VAD using next-gen Kaldi with onnxruntime without Internet connection. Support embedded systems, Android, iOS, HarmonyOS, Raspberry Pi, RISC-V, RK NPU, Axera NPU, Ascend NPU, x86_64 servers, websocket server/client, support 12 programming languages项目地址: https://gitcode.com/GitHub_Trending/sh/sherpa-onnx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考