
Agent Zero Whisper STT 语音转文字插件深度解析架构、配置与端到端转写流程【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero导读本文以 Agent Zero 内置的_whisper_stt插件plugins/_whisper_stt为对象完整讲解这套基于 OpenAI Whisper 的语音转文字Speech-to-Text能力的职责划分、六大配置参数、两个插件 API、模型运行时原理与前端麦克风状态机。读完本文你将掌握如何在 Agent Zero 中启用并调优 Whisper STT、send/draft两种消息投递模式的区别、静音检测到转写派发的完整数据链路以及该插件如何与sttService服务、Web UI 扩展点协同工作为后续二次开发或故障排查提供源码级依据。一、插件定位职责边界清晰的 STT 提供者从 plugins/_whisper_stt/README.md 与 plugins/_whisper_stt/AGENTS.md 可以看出该插件遵循一个插件只负责一件事的设计原则其核心职责是在插件启用时把 Whisper 注册为当前活跃的 STT 提供者拥有麦克风运行时microphone runtime、设备选择 UI、消息投递模式与插件 API将依赖安装与模型引导bootstrap约束在 Docker/启动路径上插件本身不负责安装依赖。与之配套_kokoro_tts插件负责文本转语音TTS二者共同构成 Agent Zero 的语音能力双子插件。这种拆分也体现在目录结构上语音能力从核心代码库迁出为插件后旧的核心语音文件如api/transcribe.py、helpers/whisper.py、webui/css/speech.css等已被移除并由 tests/test_speech_plugin_split.py 中的test_legacy_core_speech_artifacts_are_removed测试用例逐一断言其不存在。模块归属Ownership根据 plugins/_whisper_stt/AGENTS.md 中声明的所有权边界各文件分工如下模块归属职责api/status.py、transcribe.py转写与状态端点helpers/runtime.py、migration.py运行时与迁移行为hooks.py提供者注册与生命周期行为webui/设置页、主语音 UI、Store状态仓库与样式default_config.yaml、plugin.yaml、README.md默认值、元数据与行为说明插件元数据plugins/_whisper_stt/plugin.yaml 声明了插件的基本信息name: _whisper_stt title: Whisper STT description: Built-in Whisper speech-to-text plugin. version: 1.0.0 always_enabled: false settings_sections: - agent per_project_config: false per_agent_config: false要点always_enabled: false表示插件默认不启用需要在设置中显式打开配置作用于全局per_project_config与per_agent_config均为false不会按项目或按 Agent 隔离settings_sections: [agent]表明其配置入口挂在 Agent 设置分区下Web UI 通过 extensions/webui/voice-settings-main/whisper-card.html 在voice-settings-main扩展点渲染设置卡片。二、配置详解六大参数与取值约束插件默认配置定义在 plugins/_whisper_stt/default_config.yamlmodel_size: base language: en message_mode: send silence_threshold: 0.3 silence_duration: 1000 waiting_timeout: 2000同时plugins/_whisper_stt/helpers/runtime.py 中维护了一份同值的DEFAULT_CONFIG字典并在normalize_config()函数中实现了完整的参数校验与钳制clamping逻辑这正是配置参数说明的权威来源参数默认值含义normalize 约束源码行为model_sizebaseWhisper 模型变体仅接受集合{tiny, base, small, medium, large, turbo}中的值非法值回退默认languageen语言提示auto表示自动检测非空字符串即可auto在运行时被解析为None交给 Whisper 自动识别message_modesend最终转写结果的投递方式仅接受{send, draft}小写归一化非法值回退sendsilence_threshold0.3触发录音的最低信号门限强制转 float 并钳制到[0.0, 1.0]silence_duration1000进入等待阶段所需的静音毫秒数转 int必须 0waiting_timeout2000静音后等待多久才派发转写毫秒转 int必须 0注意normalize_config只做防御性校验任何非法或缺失的键都会被安全地替换为默认值不会抛异常——例如float(abc)会触发TypeError/ValueError捕获后静默保留默认值见 runtime.py。配置的两个入口YAML 默认值default_config.yaml作为新环境的种子值来源运行时持久化配置由migration.ensure_config_seeded()生成/校验的 JSON 配置文件实际写入路径由plugins.determine_plugin_asset_path决定见 migration.py。Web UI 的 config.html 提供图形化编辑入口其中Model Size下拉框列出全部六种模型Tiny / Base / Small / Medium / Large / TurboLanguage为文本输入框占位符en文档明确提示Useautoto let Whisper detect itVoice Message Handling二选一Send immediately/Draft in composerSilence Threshold为 0~1 的 range 滑条step 0.01Silence Duration与Waiting Timeout为数字输入框min 100、step 100 毫秒。配置保存在 Web UI 中修改后会经hooks.py的save_plugin_config走一次normalize_config保证落盘数据始终合法见 hooks.py。三、后端 API状态查询与音频转写插件向外部暴露两个 REST 端点均基于helpers.api.ApiHandler实现1.POST /api/plugins/_whisper_stt/status— 状态查询实现见 plugins/_whisper_stt/api/status.py。该端点会先调用migration.ensure_config_seeded()确保配置已初始化然后返回结构化状态{ plugin: _whisper_stt, enabled: true, config: { model_size: base, language: en, message_mode: send, silence_threshold: 0.3, silence_duration: 1000, waiting_timeout: 2000 }, model: { ready: false, loading: false, loaded_model: }, package: { version: 20250625, error: } }其中model.ready对应运行时_model is not None、model.loading对应is_updating_model即模型正在预加载package.version通过importlib.metadata.version(openai-whisper)读取若依赖缺失则error字段携带异常信息——这也印证了依赖安装走启动路径的约束插件运行时只负责读取已安装好的包。2.POST /api/plugins/_whisper_stt/transcribe— 音频转写实现见 plugins/_whisper_stt/api/transcribe.py请求体为 JSON关键字段字段必填说明audio是音频的 Base64 编码字符串前端为 WAV Blob 转换而来ctxid否上下文 ID传入后调用self.use_context(ctxid)关联上下文处理流程与返回约定插件未启用 → 返回409body 为Whisper STT plugin is disabledaudio缺失或为空 → 返回400body 为Missing audio正常情况调用runtime.transcribe(audio)返回{ success: true, text: 转写文本, language: en }转写过程抛异常 → 返回{success: false, error: 异常信息, text: }错误不会以 500 形式打断前端状态机。四、运行时原理模型加载、语言解析与转写链路模型预加载与全局单例runtime.py 的preload()/_preload()是模型管理核心使用模块级全局变量_model/_model_name缓存已加载模型避免每次转写重复加载is_updating_model作为互斥锁_preload会while is_updating_model: await asyncio.sleep(0.1)自旋等待其他加载完成防止并发加载同一模型仅在模型未加载或模型名变化时才真正执行whisper.load_model模型下载根目录固定在files.get_abs_path(/tmp/models/whisper)这也解释了模型 bootstrap 走 Docker/启动路径的约定加载过程中通过NotificationManager向界面推送Loading Whisper model...加载完成后推送Whisper model loaded.2 秒展示并同步PrintStyle控制台日志。hooks.py的save_plugin_config中还有一个贴心细节当用户把model_size从 A 改成 B 时会立即DeferredTask().start_task(runtime.preload, next_model)异步预热新模型见 hooks.py切换模型无需等到首次点击麦克风。转写调用链runtime.transcribe()→_transcribe()的完整链路runtime.py归一化配置未传则读取已保存配置_resolve_language()解析语言空字符串或auto→None不传language参数交给 Whisper 自动检测否则原样小写传递await _preload(model_name)确保模型就绪base64.b64decode还原音频字节写入tempfile.NamedTemporaryFile(suffix.wav)临时文件调用_model.transcribe(temp_path, fp16False, language...)——fp16: False确保在无 CUDA 或需要高精度的环境中也能稳定转写finally中删除临时文件避免磁盘残留。启用状态判定is_globally_enabled()通过plugins.determined_toggle_from_paths(True, reversed(plugins.get_plugin_roots(PLUGIN_NAME)))判定全局开关runtime.py保证插件目录被多次叠加时最终以最上层启停状态为准。五、旧配置迁移从核心设置到插件配置该插件从核心代码库拆分出来后需要把旧版核心配置存放在usr/settings.json平滑迁移到插件自己的配置文件这部分由 plugins/_whisper_stt/helpers/migration.py 完成ensure_config_seeded()若插件配置尚不存在则基于旧设置构建种子配置并落盘build_seed_config()读取旧键stt_model_size、stt_language、stt_silence_threshold、stt_silence_duration、stt_waiting_timeout逐项映射到新键缺失项使用默认值_coerce_float/_coerce_int提供容错转换旧值为非法类型时回退默认值。这也与测试 tests/test_speech_plugin_split.py 中的断言相呼应stt_model_size等旧键已从核心设置中移除settings.get_default_settings()的输出中不再出现任何 legacy 语音键。六、前端运行时麦克风状态机与端到端流程STT 提供者注册机制Web 前端通过 webui/js/stt-service.js 暴露全局sttService单例继承EventTarget以提供者注册表模式管理多个 STT 实现插件启用时registerProvider(_whisper_stt, {...})注入handleMicrophoneClick、requestMicrophonePermission、updateMicrophoneButtonUI、stop、getStatus五个钩子插件禁用或状态拉取失败时unregisterProvider清理并停止当前录音见 whisper-stt-store.js。麦克风按钮由此实现谁启用谁接管的解耦。插件的前端状态仓库 webui/whisper-stt-store.js 定义了完整状态机状态含义按钮颜色whisper-stt.cssinactive麦克风待机greyactivating麦克风激活中silver图标 0.8s 脉冲动画listening侦听语音redrecording正在录音greenwaiting等待最终静音tealprocessing转写中darkcyan图标脉冲动画按钮本体由 extensions/webui/chat-input-box-end/microphone-button.html 通过x-teleport注入到聊天输入区#chat-buttons-wrapper并随状态切换mic-*class 与aria-label无障碍标签同时以sttService.emitStatusChange(micStatus)广播状态。静音检测算法核心逻辑MicrophoneInput类whisper-stt-store.js使用 Web Audio API 的AnalyserNode做实时音量分析采样时域数据计算RMS 幅度sqrt(sum((sample-128)/128)² / N)门限并非直接用silence_threshold而是经过densify(value) Math.exp(-5 * (1 - value))非线性映射后比较——这使得 0~1 的滑条值在实际声学感知上更均匀RMS 超过门限且 TTS 未在播报→ 从listening进入recordingMediaRecorder.start(1000)按 1 秒分片采集录音中 RMS 持续低于门限达到silence_duration毫秒 → 进入waitingwaiting阶段再等waiting_timeout毫秒 → 进入processing触发转写派发若silence_duration到达前声音恢复silenceStartTime重置继续录音。整个状态推进由requestAnimationFrame驱动的analyzeFrame循环完成whisper-stt-store.js并且在dispose()时彻底清理 MediaRecorder、MediaStream、AudioContext避免浏览器资源泄漏。转写结果投递send 与 draft 模式process()把录音分片合成Blobtype: audio/wav转 Base64 后 POST 到/plugins/_whisper_stt/transcribe。返回文本先经过filterResult()过滤——若文本整体被{}、()或[]包裹疑似模型输出异常内容直接丢弃并记日志避免把非语音噪声当消息发送。随后sendVoiceMessage(text)whisper-stt-store.js按message_mode分流send模式updateChatInput(message)填充输入框后立即sendMessage()发送draft模式只updateChatInput(message)把文本留在编辑器中由用户审阅后再手动发送sendsImmediately为false时不触发发送。此外前端还实现了两个易用性细节通过navigator.mediaDevices.enumerateDevices()枚举音频输入设备选择结果存入localStorage键whisperSttSelectedDevice并监听devicechange事件在插拔设备时刷新列表同时订阅ttsService的statechange一旦 TTS 开始播报且麦克风处于活动状态立即stop()停止录音避免语音助手自说自话被误转写。状态页与配置页webui/main.html 提供状态面板Provider State启用/模型就绪/已加载模型/Package 版本、Resolved Config六项归一化后的实际配置、Microphone当前状态、设备下拉选择以及Request Mic Permission / Open Settings / Refresh三个操作按钮extensions/webui/voice-settings-main/whisper-card.html 在设置页展示精简卡片模型、语言、消息模式、麦克风可直接跳转配置或状态面板。七、依赖与验证如何确认插件工作正常依赖声明仓库 requirements.txt 固定了openai-whisper20250625插件运行所需的 Whisper 依赖由此声明。如前所述依赖安装与模型下载/tmp/models/whisper均发生在 Docker/启动路径插件运行时只做加载与推理。测试覆盖tests/test_speech_plugin_split.py 是理解该插件行为契约的最佳测试入口重点覆盖test_builtin_speech_plugins_are_discoverable_and_toggleable_whisper_stt可被发现、可切换always_enabledFalse且挂载agent设置分区test_plugin_owned_voice_files_exist断言plugin.yaml、api/transcribe.py、三个 WebUI 扩展点文件与whisper-stt-store.js均存在test_whisper_message_mode_defaults_to_send_and_supports_draft验证message_mode默认send、draft大小写归一化DRAFT→draft、非法值回退send并逐文件核对 UI 选项与 Store 行为test_chat_bar_keeps_existing_send_and_mic_icon_contract对七个mic-*状态类在 Store、CSS、按钮扩展点三处的同步存在性做了全量断言。快速自检清单按 plugins/_whisper_stt/AGENTS.md 的 Verification 指引改动后应冒烟测试以下链路状态端点/api/plugins/_whisper_stt/status返回enabled、config与model信息正确转写链路录音→Base64→/transcribe返回text与language模型/语言设置切换model_size触发预热languageauto时后端不传 language 参数send/draft 模式send立即发送、draft仅留在编辑器静音处理silence_threshold/silence_duration/waiting_timeout三参数联动符合预期。八、扩展与定制方向基于上述架构开发者可以低成本地扩展语音能力替换模型在设置中把model_size改为tiny最快到turbo质量最高模型变更后hooks.py会自动异步预加载多语言支持将language设为具体语言代码如zh、ja、de提升识别准确率或保持auto交给 Whisper 自动检测消息审阅流程将message_mode设为draft让用户在任何转写结果进入对话前拥有最终确认权二次开发若要接入其他 STT 引擎可仿照_whisper_stt实现一套api/helpers/ WebUI 扩展点并复用sttService.registerProvider接口webui/js/stt-service.js完成提供者注册前端无需改动即可无缝切换。结语_whisper_stt插件是 Agent Zero核心瘦身、能力插件化架构的典型样本后端把 Whisper 的模型管理、配置归一化、迁移与推理封装在helpers/中api/仅暴露status与transcribe两个薄端点前端则通过sttService提供者模式与 Web UI 扩展点实现麦克风状态机与消息投递。理解这层分工无论是调参、排障还是接入新语音引擎你都能在 plugins/_whisper_stt、webui/js/stt-service.js 与 tests/test_speech_plugin_split.py 之间快速定位问题根源。【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考