完整指南:Whisper 与 Vosk 双引擎的模型管理、定制与源码解析)
Joplin 移动端离线语音输入Voice Typing完整指南Whisper 与 Vosk 双引擎的模型管理、定制与源码解析【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplinJoplin 的 Android 应用内置了**离线语音输入Voice typing**能力无需联网即可将语音实时转录为笔记正文。本文以仓库规格文档 readme/dev/spec/voice_typing.md 为主线完整讲解默认的 Whisper.cpp 引擎与已弃用的 Vosk 引擎的启用方式、语言模型下载机制、自定义模型包与config.json的格式规范并结合 packages/app-mobile/services/voiceTyping 下的真实实现代码带你理解语音输入从「下载模型 → 申请录音权限 → 构建会话 → 流式转写 → 后处理回填笔记」的完整调用链。读完本文你将能够配置 Joplin 的语音输入、接入自建模型服务器甚至自行构建定制化语音模型。语音输入整体架构两个引擎、一次抽象Joplin 的语音输入功能由 Android 移动端提供底层分别对接两套语音识别库Whisper.cpp默认引擎功能更强大的语音转文字库支持标点、多段落在内的完整文本输出但推理速度相对较慢Vosk面向低资源设备如手机的语音识别工具包延迟更低但输出为无标点的全小写单段落文本。规格文档明确指出Whisper is a more advanced speech-to-text library, but will be slower than VoskWhisper 更强大但比 Vosk 慢。从 packages/app-mobile/services/voiceTyping/VoiceTyping.ts 的源码结构看两套引擎被抽象为统一的VoiceTypingProvider接口各引擎只需实现supported()、modelLocalFilepath(locale)、getDownloadUrl(locale)、build(options)等成员即可接入同一套「下载 → 校验 → 构建会话」流程这为引擎切换与后续扩展保留了清晰的扩展点。需要注意的是源码注释表明当前版本移动端仅支持 Whisper 一个 providervoiceTyping.preferredProvider设置已标记为 Deprecated and currently unusedVosk 相关代码已从仓库中移除仅保留在规格文档与设置元数据中作为历史兼容说明详见下文。Whisper默认语音输入引擎语言模型与默认选择Whisper.cpp 提供大量预训练模型分为仅英文模型与多语言模型两类多语言模型覆盖多种语言适合非英语用户仅英文模型则在英文转写上更专注。Joplin 默认使用体积最小的多语言模型以兼顾移动端的存储与推理开销。从 whisper.ts 的getDownloadUrl实现可以看到当前版本的实际默认下载地址模板https://github.com/joplin/voice-typing-models/releases/download/v0.2.0/{task}.zip其中{task}会被替换为whisper-small-q8_0{lang}会被替换为语言代码即仓库当前默认拉取的是whisper-small-q8_0量化模型。这意味着模型体积与识别质量之间存在取舍——q8_0为 8-bit 量化格式在保证较高识别精度的同时显著压缩了模型体积适合手机端加载。模型文件采用ggml格式model.bin这是 whisper.cpp 的底层推理格式。whisper.cpp 的 Hugging Face 页面上提供了可直接作为model.bin使用的预构建模型如需自定义模型可按照 whisper.cpp README 中的模型构建说明将训练/转换后的模型导出为 ggml 格式whisper.cpp 仓库的models/目录下提供了相关转换脚本与步骤。通过 Glossary 减少拼写错误语音识别对专有名词、人名、生僻词往往容易拼错。Joplin 提供了Voice typing: Glossary语音输入词汇表设置位于设置的 Note笔记分区。将不常见词汇加入词汇表后语音输入会更倾向于按正确写法输出。规格文档给出的示例提供Scott Joplin, ragtime.作为词汇表可帮助正确拼写 Scott Joplin 与 ragtime。该功能的底层原理是prompting提示词引导——Whisper 支持在推理时注入一段文本提示模型会参考提示中的词汇拼写。在 Joplin 实现中whisper.ts从设置voiceTyping.glossary读取词汇表通过本地化函数_()生成 Glossary: 前缀若转写语言非英语且无对应翻译则省略此前缀将「模型自带的基础 prompt来自config.json的prompts字段按转写语言选取」与「词汇表 prompt」拼接后传给 Whisper 会话。也就是说config.json中可为各语言定义提示文本而词汇表作为额外的拼写修正提示追加其后。设置项的官方描述为A comma-separated list of words. May be used for uncommon words, to help voice typing spell them correctly.逗号分隔的单词列表用于不常见词汇帮助语音输入正确拼写定义于 builtInMetadata.ts。模型下载机制与自定义下载地址默认情况下Joplin 从官方 voice-typing-models 仓库下载 Whisper 模型。如需从自定义位置下载可修改配置界面 Note 标签页中的Voice typing language files (URL)语音输入语言文件 URL设置对应内部设置键voiceTypingBaseUrl见 builtInMetadata.ts。从源码 VoiceTyping.ts 可以还原完整的下载流程依据 provider 的getDownloadUrl(locale)得到模型 URL若 URL 以.zip结尾则先下载到${modelPath}.zip下载后解压到缓存目录voice-typing-extract/{modelName}/{locale}校验其中恰好只有一个文件或目录再移动到正式的模型目录将「模型 URL 的 MD5 哈希」写入uuid文件作为下载标记isDownloadedFromOutdatedUrl()通过对比当前 URL 的 MD5 与该标记判断下载地址是否变更、是否需要重新拉取模型VoiceTyping.ts。首次使用语音输入时Joplin 会自动完成模型下载后续若修改了下载 URL应用会检测到 MD5 不匹配并重新下载对应语言的模型。自定义 Whisper 模型包ZIP 结构与 config.json 规范Joplin 支持从.zip文件加载自定义 Whisper 模型要求 ZIP 包内部具有如下结构️ modelName.zip/ │ config.json │ model.bin │ README.md其中model.binggml 格式的模型文件即上文所述可从 whisper.cpp 预构建模型中获取、或按官方流程自行构建的模型README.md模型说明非必需但建议保留config.json提示词prompting与输出后处理配置格式如下{ prompts: { en: Prompt for English-language text goes here., fr: Prompt for French-language text goes here., ...: ... more prompts for other languages ... }, output: { stringReplacements: [ [ text to replace 1, replace with ], [ text to replace 2, replace with 2 ] ], regexReplacements: [ [ some.*regular (expression)?, replace with ], [ another regular expression, replace with 2 ] ] } }各字段说明字段作用取值示例prompts按语言代码如en、fr为各语言指定 Whisper 推理提示词用于引导拼写、风格等{ en: This is a note about Joplin voice typing. }output.stringReplacements逐条字符串替换每条为[原文, 替换为]的二元数组在转写结果中精确替换文本[ [joplin, Joplin] ]output.regexReplacements逐条正则替换每条为[正则表达式, 替换为]的二元数组用于模式化修正[ [\\bapp\\b, application] ]在 whisper.ts 的WhisperConfig类中可以看到严格的解析校验逻辑prompts必须是「字符串到字符串」的对象stringReplacements/regexReplacements必须是「二元字符串数组的数组」正则替换会被编译为带g标志的RegExp。此外还支持一个文档未展开、但源码明确处理的扩展字段{ shortAudioContext: true }shortAudioContext用于标识按 whisper-acftfuto-org 的 whisper fine-tuning 项目微调、支持短音频上下文的模型设置为true时Whisper 会话将以shortAudioContext模式打开whisper.ts。转写结果的后处理在postProcessSpeechwhisper.ts中完成先按\n\n切分为段落对每段依次执行字符串替换与正则替换再重新以空行连接onDataFinalize会在首段之前不加分隔、后续段落前追加\n\n从而以多段落、带标点的格式写入笔记——这正是 Whisper 相比 Vosk 的重要体验优势。Vosk已弃用的备选引擎启用方式与弃用说明Vosk 语音输入此前可通过设置 Note 标签页中的Preferred voice typing provider首选语音输入提供方改为 Vosk 来启用。但规格文档明确警告由于兼容性问题Vosk 语音输入已弃用将在 Joplin v3.5 中移除。这一状态在源码中得到印证voiceTyping.preferredProvider设置在 builtInMetadata.ts 中已标记为Deprecated and currently unused. For now, the mobile app only supports the Whisper voice typing provider.已弃用且当前未使用目前移动端仅支持 Whisper其选项列表中vosk: Vosk旁也注明 No longer supported。因此新项目请直接使用 WhisperVosk 相关内容仅作为历史兼容说明保留。与 Whisper 的对比规格文档给出了 Vosk 与 Whisper 的简明对比这是选择引擎时最直观的参考无标点Vosk 输出为全小写文本且不含任何标点符号单段落Vosk 的整段输出是一个连续的段落速度快Vosk 的推理延迟低于 Whisper。即追求转录质量、需要标点与段落结构 → 选 Whisper极端追求响应速度且可接受纯文本 → Vosk但需承担弃用风险。Vosk 的语言模型与 Whisper 类似Vosk 使用预训练语言模型完成自动语音识别。每个语言通常提供多档模型轻量模型适合移动设备单个约 50 MB大型模型面向服务器端识别单个 2 GB 以上。规格文档同时指出Vosk 的每个语言也有多种模型可选官方 Vosk 网站alphacephei.com/vosk/models提供了完整模型列表。Vosk 模型下载自动下载与自建服务器默认情况下Joplin 会在首次使用语音输入时自动从 Vosk 官网下载轻量模型该语言文件只需下载一次。如需改为从自己的服务器下载可修改配置界面中的Voice typing language files (URL)设置同样对应voiceTypingBaseUrl详见 配置界面文档。该设置支持两种取值方式方式一提供基础 URLhttps://example.com/modelsJoplin 会自动把文件名追加到该 URL 后面。例如要下载法语模型实际请求为https://example.com/models/fr.zip方式二提供 URL 模板含{lang}变量在 URL 中嵌入{lang}占位符应用会将其展开为语言代码。例如设置为https://example.com/models/vosk-model-{lang}.zip则法语模型将从https://example.com/models/vosk-model-fr.zip下载。模板方式更灵活还可以配合查询参数使用例如https://example.com/models/vosk-models.php?lang{lang}downloadtrue说明该下载地址模板机制同样适用于 Whisper 引擎——从 whisper.ts 可见voiceTypingBaseUrl为空时使用默认模板否则以用户填写的模板为准并对{task}任务名当前为whisper-small-q8_0与{lang}语言代码做展开替换。设置为空值即恢复官方默认下载源。语音输入在源码中的完整工作流结合 VoiceTyping.ts 的build()方法可还原一次语音输入的完整生命周期检查 Provider若没有可用 provider如 iOS/web 平台抛出No supported provider found!检查并下载模型若uuid标记文件不存在则触发download()自动拉取当前语言模型首次使用会经历较长的下载过程SpeechToTextBanner.tsx 负责在界面上呈现输入状态与预览文本申请录音权限在 Android 上检查并请求android.permission.RECORD_AUDIO权限构建会话调用 provider 的build()打开 Whisper 会话传入locale、模型路径与回调对象流式转写会话start()后循环调用session.convertNext(4)逐块读取识别结果通过onPreview预览可能变化与onFinalize定稿追加进文档两个回调把文本写入笔记stop()时调用convertNext(null)冲刷剩余内容并关闭会话whisper.ts。底层音频采集与推理由原生模块完成仓库中的 packages/whisper-voice-typing 包封装了 whisper.cpp供 React Native 通过 nitro-modules 调用包含openSession/convertNext/close等原生接口与对应测试参见 whisper.test.ts。语音输入相关设置项速查以下设置均定义在 builtInMetadata.ts 中归属 Note笔记设置分区且仅当平台为 Android 且构建开关buildFlag.voiceTypingEnabled为true时显示设置键界面名称类型/默认值说明voiceTypingBaseUrlVoice typing language files (URL)String /空语音模型下载地址留空使用官方默认源支持{lang}与{task}模板voiceTyping.glossaryVoice typing: GlossaryString /逗号分隔的词汇表用于修正生僻词拼写通过 prompt 注入 WhispervoiceTyping.preferredProviderPreferred voice typing providerString /whisper-tiny已弃用且当前未使用仅保留 Vosk/Whisper 历史选项buildFlag.voiceTypingEnabled隐藏Bool /true构建期开关由于语音输入在低性能设备上体验不佳可将其默认值改为false以在构建时禁用该功能builtInMetadata.ts结语Joplin 的语音输入是「开箱即用 深度可定制」结合的典型默认 Whisper 引擎自动下载多语言模型即可使用词汇表解决专有名词拼写自定义 URL 支持自建模型分发而 ZIP 模型包配合config.json的 prompts 与替换规则则让高级用户与开发者可以完全掌控转写提示与输出格式。理解 readme/dev/spec/voice_typing.md 规格、VoiceTyping.ts 的下载与会话管理以及 whisper.ts 的配置解析细节即可在移动端构建稳定、精准的离线语音笔记体验。【免费下载链接】joplinJoplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.项目地址: https://gitcode.com/GitHub_Trending/jo/joplin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考