基于 Tauri v2 与 sherpa-onnx 的离线音视频转写桌面应用:非流式文件识别实战指南

发布时间:2026/9/15 18:16:08
基于 Tauri v2 与 sherpa-onnx 的离线音视频转写桌面应用:非流式文件识别实战指南 基于 Tauri v2 与 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本指南围绕 sherpa-onnx 仓库中 tauri-examples/non-streaming-speech-recognition-from-file 示例完整讲解如何构建一款跨平台macOS / Linux / Windows桌面应用用 Tauri v2 承载界面、用纯 Rust 解码音视频、用 Silero VAD 切分语音、再用 sherpa-onnx 离线识别引擎逐段转写。读完本文你将掌握从模型下载、资源打包、开发调试到更换任意 ASR 模型、理解后端并发流水线的全套实战能力。应用概览与核心特性这是一个基于 Tauri v2 的桌面应用使用 sherpa-onnx 的离线非流式ASR 结合 Silero VAD对本地音频与视频文件进行转写全程不需要联网。仓库中该示例的主 README 概括了以下能力62 种 ASR 模型SenseVoice、Paraformer、Whisper、Transducer、Moonshine 等覆盖中、英、日、韩、粤语及多语种场景音频与视频输入MP3、FLAC、AAC、OGG、WAV、AIFF、CAF 及 MP4、MKV、WebM实时字幕叠加转写结果随播放进度实时同步显示在播放器上点击跳转点击结果表格中的任意行播放器立即跳到对应语音片段SRT 字幕导出一键将全部结果保存为.srt字幕文件片段 WAV 导出将任意单个语音段单独导出为 WAV 文件复制结果可复制纯文本或带时间戳文本到剪贴板进度跟踪与取消实时百分比进度条支持中途取消跨平台macOSuniversal、Linuxx64/aarch64、Windowsx64纯 Rust 音频解码通过 symphonia 解码无系统级外部依赖便于 Tauri 打包分发。值得一提的是无系统依赖这一设计解码链路完全由 Rust 生态承担见 src-tauri/Cargo.toml 中 symphonia 的 feature 配置mp3、aac、flac、vorbis、wav、ogg、isomp4、mkv、pcm、adpcm、aiff、caf。这意味着最终产物是自包含的用户机器上无需安装 ffmpeg 等外部解码工具。支持的输入格式任何 symphonia 支持的格式都可以处理示例 README 给出的格式清单如下类型格式音频MP3、FLAC、AAC、OGG/Vorbis、WAV、AIFF、CAF、ADPCM视频MP4/M4A、MKV、WebM自动抽取音轨前端文件选择对话框src/main.js同时给出了常见的文件扩展名列表音频为wav/mp3/flac/ogg/aac/m4a/aiff/caf视频为mp4/mkv/webm/avi/mov。注意具体能否解码取决于编译进二进制的 symphonia feature如果遇到 Unsupported format 报错需要回到 Cargo.toml 的[dependencies.symphonia]一节检查。环境准备在动手之前需要准备以下工具链Ruststable 通道—— 后端与解码库的编译环境Node.js—— 用于运行 Tauri CLITauri v2 平台依赖—— 不同操作系统的系统库要求Linux 需要 webkit2gtk 等Windows 需要 WebView2macOS 需要 Xcode 命令行工具。进入示例目录并安装 npm 依赖cd tauri-examples/non-streaming-speech-recognition-from-file npm installpackage.json 中定义了两个脚本npm run dev开发模式与npm run build构建发布包底层均调用tauri-apps/cli。快速开始模型下载与资源布局示例默认捆绑SenseVoice int8模型对应MODEL_TYPE 15支持中文、英文、日文、韩文和粤语。1. 下载模型与 Silero VAD模型文件托管在 sherpa-onnx 官方发布页的asr-models资产中文件名即上述 SenseVoice int8 模型包Silero VAD 也以单个silero_vad.onnx形式提供。下载并解压以 Bash 为例cd tauri-examples/non-streaming-speech-recognition-from-file # 下载 SenseVoice int8 模型包来源sherpa-onnx 官方 asr-models 发布资产 curl -SL -O asr-models-发布页/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2 tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2 rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2 # 下载 Silero VAD同为 asr-models 发布资产 curl -SL -O asr-models-发布页/silero_vad.onnx2. 将资源拷贝进 src-tauri/assetsTauri 只会把src-tauri/assets/目录下的内容打进安装包bundle.resources配置见 src-tauri/tauri.conf.json。因此需要把模型目录保持原名和silero_vad.onnx放入其中mkdir -p src-tauri/assets cp -a sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17 src-tauri/assets/ cp silero_vad.onnx src-tauri/assets/最终期望的资源布局src-tauri/assets/ ├── silero_vad.onnx └── sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17/ ├── model.int8.onnx └── tokens.txt后端在 src-tauri/src/lib.rs 的resource_dir()中做跨平台资源定位macOS 会向上查找.app包并优先使用Contents/Resources/assetsLinux/Windows 则查找可执行文件同级的assets/目录最后兜底到当前目录。可选启用同音字替换Homophone Replacer部分模型如 SenseVoice支持同音字替换用于纠正易混淆字词。将lexicon.txt与replace.fst直接放入assets/根目录即可curl -SL -O hr-files-发布页/lexicon.txt curl -SL -O hr-files-发布页/replace.fst cp lexicon.txt replace.fst src-tauri/assets/从源码看lib.rsbuild_models()会检查资源目录下是否存在这两个文件存在则写入 ASR 配置的hr.lexicon与hr.rule_fsts字段。没有这两个文件应用也能正常工作只是不做同音字纠正。3. 开发模式运行npm run dev窗口打开后点击Select Audio/Video File选择文件识别会自动开始。注意模型初始化发生在后台线程启动瞬间界面上显示 Models are still loading几秒后就绪大模型更慢。4. 构建发布版npm run build产物输出在src-tauri/target/release/bundle/下包含各平台对应的安装包格式。更换 ASR 模型62 模型一键切换应用通过 src-tauri/src/lib.rs 中的两个常量决定捆绑哪个模型const MODEL_TYPE: u32 15; const MODEL_NAME: str sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17;切换模型只需四步从 src-tauri/src/model_registry.rs 中选择一个模型类型类型 0 到 61同步更新MODEL_TYPE与MODEL_NAME两个常量下载对应模型并放入src-tauri/assets/保持原始目录名不变运行npm run dev验证。model_registry.rs是由脚本自动生成的文件文件头标注 Auto-generated by generate-vad-asr.py. DO NOT EDIT.其内部为每种模型类型构造一个完整的OfflineRecognizerConfig涵盖各模型的专属配置结构体Paraformer / Transducer / Whisper / Zipformer-CTC等经典架构model_type、tokens、num_threads、debug等通用字段SenseVoice类型 15、41 等OfflineSenseVoiceModelConfig { model, use_itn }其中use_itn控制逆文本正则化数字、时间、金额等的口语规范化NeMo CTC / NeMo Transducer / Dolphin / FireRed / Moonshine / Canary / Qwen3-ASR / Omnilingual / MedASR / FunASR-Nano等新模型也有各自配置入口。例如类型 15 对应的 SenseVoice 配置model_registry.rs 附近会加载model.int8.onnx与tokens.txt而类型 41 的更新版 SenseVoice 则显式设置了use_itn: true。这些配置与 sherpa-onnx Rust API 中OfflineRecognizerConfig、OfflineSenseVoiceModelConfig等结构体一一对应。用构建脚本自动化仓库提供了模型注册表生成脚本可一键生成/裁剪模型配置python scripts/tauri/generate-vad-asr.py --gen-registry python scripts/tauri/generate-vad-asr.py --total 1 --index 0--gen-registry重新生成model_registry.rs--total/--index控制最终捆绑的模型数量与索引用于控制最终安装包体积只保留需要的模型。架构与处理流水线示例 README 给出了清晰的前后端架构图┌──────────────────────────────────────────────────┐ │ Frontend (HTML JS) │ │ index.html / main.js / styles.css │ │ │ │ invoke(recognize_file, {path}) │ │ setInterval → invoke(get_recognition_progress)│ └──────────────┬───────────────────────────────────┘ │ Tauri IPC (invoke) ┌──────────────▼───────────────────────────────────┐ │ Backend (Rust) │ │ │ │ lib.rs │ │ ├── recognize_file() → spawns worker thread │ │ ├── run_recognition() → decode → VAD → ASR │ │ ├── get_recognition_progress() → poll state │ │ ├── cancel_recognition() │ │ ├── export_srt() │ │ └── save_segment_as_wav() │ │ │ │ model_registry.rs (auto-generated, 62 models) │ └──────────────────────────────────────────────────┘前端是纯静态页面src/index.html、src/main.js、src/styles.css通过 Tauri 的invoke与后端 Rust 命令通信后端在lib.rs中注册了 8 个 Tauri commandrecognize_file、get_recognition_progress、cancel_recognition、export_srt、save_segment_as_wav、get_init_status、get_settings、apply_settings见 lib.rs。处理流水线源码级README 定义了五步流水线源码中均有对应实现symphonia 流式解码open_audio_file()lib.rs用Hintget_probe()探测格式选取第一个非空音轨创建解码器。随后run_recognition()循环读取 packet、逐包解码——这是流式处理不会把整个文件一次性载入内存大文件数小时视频也能平稳处理。重采样到 16 kHzLinearResampler::create(native_rate, 16000)lib.rs在原生采样率不等于 16 kHz 时启用decode_to_mono_f32()负责把多声道交错数据平均混合为单声道 f32。Silero VAD 切分以 512 样本32 ms窗口喂给VoiceActivityDetectorvad_config.silero_vad.window_size 512内部缓冲区攒够一个窗口即送入 VAD并从队首取出检测到的语音段lib.rs。文件读完后还会vad.flush()冲刷残留样本保证末段语音不被漏掉lib.rs。OfflineRecognizer 逐段转写recognize_segment()lib.rs对每个语音段创建离线流、accept_waveform(16000, samples)、decode()并取结果时长小于 0.1 秒的段直接丢弃纯标点/空白结果也会被过滤。结果累积与轮询结果写入ArcMutexVecSegmentResult前端每 200 ms 通过get_recognition_progress轮询拉取增量结果main.js只追加新行而不是重建整个表格。进度百分比基于音轨的n_frames总帧数推算解码样本数/总帧数 × 100封顶 99%完成后置为 100%若文件未提供总帧数则进度保持 0% 直到结束——这是源码注释中明确说明的行为lib.rs。VAD 参数与运行时热更新VAD 的关键参数定义在VadSettings结构体中默认值如下lib.rs参数默认值含义threshold0.2VAD 判定阈值须在 0.0~1.0 开区间min_silence_duration0.2段内允许的最短静音时长秒min_speech_duration0.2认定为语音段的最短时长秒max_speech_duration10.0单个语音段的最大时长秒num_threads2ASR 推理线程数校验范围为 1~16这些参数在build_models()中被映射到SileroVadModelConfiglib.rs同时asr_config.model_config.num_threads也被覆盖为设置值。界面的设置弹窗main.js可修改这五项apply_settings会在后台线程重建Recognizer 与 VADbuild_models期间init_status回到 0、界面显示 Reloading models...重建完成后自动恢复就绪识别进行中不允许改设置。validate_settings()lib.rs对每个参数做了边界校验越界直接报错。模型初始化状态机应用启动后先构建AppStateRecognizer/VAD 为None随即在后台线程调用build_models()加载模型lib.rs。init_status是一个三态标志0 pending、1 ready、2 error。前端通过get_init_status每 300 ms 轮询直到就绪才放开选择按钮初始化失败时显示具体错误信息main.js。build_models()全程输出[init]、[build_models]等日志到 stderr是排查启动问题的第一现场。字幕同步与点击跳转播放器与字幕同步由前端requestAnimationFrame驱动约 60 fps远高于timeupdate事件的 ~4 fps通过二分查找findSegmentIndex()定位当前播放时刻所在的语音段main.js同步更新字幕叠加层与结果表格高亮行。点击表格行会暂停播放器并 seek 到该段起点前 0.3 秒再继续播放main.js避免错过语音开头。SRT 导出与片段 WAV 导出SRT 导出export_srtlib.rs把内存中的SegmentResult列表按 SubRip 规范序列化序号 HH:MM:SS,mmm -- HH:MM:SS,mmm 文本时间格式由format_srt_time()生成。片段 WAV 导出save_segment_as_wav先调用decode_time_range()lib.rs——只重新解码目标时间段[start, end)对应的样本而非全文件缓冲再由write_wav()lib.rs手写 RIFF/WAVE 头把 f32 采样钳制到 [-1,1] 后量化为 16-bit PCM以 16 kHz 单声道写出。前端会基于片段内容自动生成默认文件名如segment-3-0_00s-2_50s-你好.wav。故障排查速查表问题解决办法启动时提示 Models are still loading模型在后台线程加载等待几秒模型越大越慢Failed to create recognizer检查src-tauri/assets/MODEL_NAME/是否存在且包含预期的.onnx与tokens.txt文件Unsupported format该格式可能未在Cargo.toml的 symphonia feature 中启用检查[dependencies.symphonia]一节播放器出现黑色矩形纯音频文件属正常现象——video元素只显示控制条没有画面应用启动崩溃运行npm run dev并查看 stderr 中的[init]或[build_models]日志端到端使用流程点击Select Audio/Video File通过系统原生对话框选择文件symphonia 逐包解码为单声道 f32 PCM非 16 kHz 音频经LinearResampler重采样以 512 样本32 ms窗口喂入 Silero VAD每个检测到的语音段 100 ms由离线识别器转写结果以起始时间/结束时间/文本表格呈现200 ms 增量刷新点击任意行跳转到对应片段字幕实时叠加在播放器上。小结这个 Tauri v2 sherpa-onnx 示例展示了桌面端离线语音转写的一条完整、可工程化的技术路线symphonia 解决解码零外部依赖Silero VAD 解决长音频切分sherpa-onnx 离线引擎解决推理不联网三者通过 Rust 后台线程与前端 200 ms 轮询完成异步衔接。无论你是要做一个本地字幕工具、媒体文件审校应用还是需要在隔离环境中批量转写音视频都可以直接以 non-streaming-speech-recognition-from-file 为起点借助 model_registry.rs 的 60 模型配置快速替换适配自己的语种与精度需求。仓库中另有 non-streaming-speech-recognition-from-microphone 的麦克风实时版示例可一并对照学习。【免费下载链接】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),仅供参考