@alwith/module-voice (英语)
私人释放候选人。 流出 VUI 和 Doubao 的语音识别,带有可选的React和编辑适配器. 没有全权证书.
公共入境点
| 导入 | API 和责任 |
|---|---|
@alwith/module-voice | VoiceController, (中文(简体) ), VoiceError, (中文(简体) ), VoiceInteraction、偏好、沉默检测和运输合同。 没有反应,DOM,或陶里依赖. |
@alwith/module-voice/audio | prepareCapture, (中文(简体) ), PcmEncoder,以及 watchInputDevices。浏览器麦克风和设备 API. |
@alwith/module-voice/worklet | AudioWorklet资产. 把它装入 URL 并将其传送到 prepareCapture。 。 。 . |
@alwith/module-voice/chat | DraftPort, (中文(简体) ), DraftTransaction,以及 RevisionDraft. 基于修订版的编辑器集成,不依赖聊天框架. |
@alwith/module-voice/react | VoiceControls, (中文(简体) ), VoiceSettingsForm他们的槽/主机类型, useVoiceInteraction下层 useVoice 钩. |
@alwith/module-voice/tauri | createTauriTransport 与注入的引线/通道桥连接 alwith-voice 插件 . |
@alwith/module-voice/commands | 生成用于插件命令的已打入绑定( E)profiles, (中文(简体) ), saveCredential, (中文(简体) ), deleteCredential(中文(简体) ). |
@alwith/module-voice/locales | 英语和简化了的主机本地化的中文字符串. |
React and React DOM 是可选的同伴依赖关系,在消耗时需要 /react. 该套件离开React,React DOM,以及JSX运行时间外部;消费者提供自己的拷贝. 反应输出使用生产JSX变换. 其他出入口不需要反应.
记录和编辑器交互
VoiceController 拥有一个识别行动。 打电话 start(options) 带有新的录音ID,证书配置,热字,以及提供者平滑选项. 国家、部分文本、最后文本和错误通过召回到达. finish() 冲出抓取并等待操作的最终结果;失败拒绝. cancel() 中断操作,并且 dispose() 等其清净. 只有在麦克风停止后,才发放捕获许可.
VoiceInteraction 围绕创建的会话添加编辑器交易和提交行为 InteractionHost.createSession。主机提供草稿、录用检查、设置和证书可用性、配置 UI、同步编辑功能、提交、转弯观察和用户可见错误/不说话报告。 配置 UI 失败通过报告 onError。设置被装入,用于新的交互,并在无手回合中重复使用.
这三种模式是:
dictation: 更新所选的草稿范围; 留给用户 .send:完成所配置的静态/持续限值,并通过主机提交.handsfree:提交、等待接受和相应的回合完成,然后再次记录.
提交返回 { status: "accepted" } 或者说 { status: "blocked", reason };失败拒绝。 主机在提交前必须安装转弯观测,并将完成与接受的即时连接. 仅仅接受,或繁忙的状态过渡,并不是完成。 主办方必须在批准等待、断开、转弯失败或介入时拒绝这一意见。 仅在此关联可用时启用手无寸铁 .
自动发送模式拒绝现有的非空文本草稿 。 空最终文本恢复了原选择并停止自动收听. 识别文本是一个完整的替换快照,而不是三角洲. 普通套接字关闭不会取代最终结果 .
每个用户或外部编辑草稿都必须推进其修改,包括同文写作. DraftPort.compareAndSet 必须在实际写作时检查目标身份和修改。 取消只恢复一个仍然拥有的草稿;失败保留了显示的预览. 使用 cancel(false) 用于外部编辑和 cancel(true) 为明确的用户回滚。 成功提交文件必须只澄清其提交的修订草案,不得视为取消无手周期的外部编辑。 处理目标替换或卸载时的相互作用.
反应控制和设置槽
VoiceControls 接收 host (没有 createSession 财务报告和审定财务报表 commit, (中文(简体) ), transport一个捕捉工厂, enabled和马厩 cancelRef。它创建控制器和静音探测器,并用 React DOM 执行编辑器的修改 flushSync供应 Button 组件、本地化标签和图标;软件包不强制设置应用程序设计系统。 内容 cancelRef 回调保存外部编辑。 保持一个编辑目标的身份草稿,运输,并取消对调的稳定;替换它们处理交互.
VoiceSettingsForm 收到一个 VoiceSettingsHost 与 load, (中文(简体) ), save, (中文(简体) ), profiles, (中文(简体) ), saveCredential,以及 deleteCredential供应 Group, (中文(简体) ), Row, (中文(简体) ), Input, (中文(简体) ), Textarea, (中文(简体) ), Button, (中文(简体) ), Switch,以及 Select 结束 VoiceSettingsSlots,加上 text, (中文(简体) ), onError,以及 onSaved。选择槽接收一个标签、值、选项列表和 onChange;它调整了主机的选定执行。 输入证书值是为了保存,绝不装入窗体。 设备在未保存的设置和证书输入之外独立重试刷新设备.
defaultPreferences() 建立优惠; parsePreferences(unknown) (一) 验证持续的投入; recordingSettings(preferences, cwd) 合并了全局和精确的项目路径热词,分割逗号/新线,修剪并去除. 持久性和项目特性仍然是东道方的责任。 平滑是杜宝的选择.
设备和沉默限制
捕获使用单相16千赫签名的小端PCM并拒绝无支持的样本率. 一个空的 deviceId 选择系统默认;一个明确的ID请求,即精确的设备. watchInputDevices(media, changed, failed) 列举音频输入,听取设备更改,忽略 stale 响应,并返回一个未订阅的函数. 编号不要求麦克风许可或打开单独的捕获流;设备标签和可用性取决于浏览器许可.
自动模式在PCM框架之上使用RMS能. SilenceDetector 报告一次停止的决定。 这是一个能量阈值探测器,而不是语音识别模型.
| 设置 | 默认 | 有效范围 |
|---|---|---|
threshold | 0.015 | 大于0,最多1个 |
silenceMs | 1400 | 200至10 000毫秒 |
initialSilenceMs | 10000 | 起码 silenceMs |
maxDurationMs | 60000 | 起码 initialSilenceMs,最多30万毫秒 |
所有价值都必须是有限的。 无静态配置的首选项接收所记录的默认值 。 一旦语音超过阈值,后继的沉默可以完成回合;初始的沉默和最长持续时间提供了单独的停止条件. 这些限制适用于自动模式. 土著承认期限仍然独立.
前端队列在其字节预算中包括飞行中写作. 原生音频被限制在10个200ms帧. 过量流明显失败, 而不是丢弃中间音频 。 取消不会等待排队的音频排出 .
本土活动和东道主生命周期
承认和提供商住在私人本地语音图书馆,在本包中运出 native/<os>-<cpu>/。 Tauri 主机使用公共插件 alwith-voice 从箱.io:
[dependencies]
alwith-voice = "0.6"
.plugin(alwith_voice::init(credentials, Config { development_directory }))
credentials 执行 alwith_voice::Credentials:主机的证书商店,它运行插件的步子,同时自持锁来操作,因此根据录音的起步命令证书更改. 插件拥有文档身份( 它解析了网页视图在导航和窗口破坏上的录音), 事件路径到频道, 以及命令 start, (中文(简体) ), push, (中文(简体) ), control, (中文(简体) ), profiles, (中文(简体) ), saveCredential 财务报告和审定财务报表 deleteCredential赠款 alwith-voice:default (记录和配置文件可用性) alwith-voice:credentials 转到设置窗口。 打电话 alwith_voice::shutdown(app) ; 调用 cancel_provider(app, provider) 当主机在插件命令外更改证书时。 已打入的装订从 @alwith/module-voice/commands· ; createTauriTransport 地址插件命令。 TLS在库内使用Rustls AWS-LC.
活动带有记录ID,在目前本地产出中,则带有指定服务 generation 和增加记录 sequence。部分结合会留下序列空白。 控制器过滤不匹配的世代和重复/旧事件;合同保留了元数据对现有传输的可选性. 原生活动也携带被捆绑的主人进行主机出行. 不要从选中的聊天或 WebView 提供的窗口标签中推断所有权 .
失败事件显示一个已消毒的信息和结构化 VoiceFailure 字段 : stage, (中文(简体) ), category, (中文(简体) ), code无效 requestId。 。 。 . VoiceError.detail 在当前时保存此元数据。 保留数字提供者出错代码;原始传输/提供者出错文本不会通过本地事件消息被曝光. 主机决定如何定位并显示失败. 抓取和录入错误也可能是普通的JavaScript错误,没有本土细节.
主机在不返回被存储的密钥到WebView的情况下解析证书,将所有权绑定在其认证的窗口/文件身份上,并承认实际的麦克风放出. 只有在旧文档无法再被捕获时才能解析;在文档替换时否认新的捕获. 在程序退出前拨打关闭, 在完成主机拆解前加入事件阅读器 。 仅限主机 cancelProvider 命令终止该提供者的活动会话,同时保留捕获所有权直至发布确认.
AL 与 U 证书整合
U通过其本土的认证适配器在macOS Keychain或Windows证书管理器中存储供应商证书. 其他主机提供自己的安全证书解析器;OS证书存储器不是浏览器包的一部分. 不支持的安全存储平台明显失败.
在第一次访问时, U 从它的遗产中移取相应的证书 voice-credentials.json 只有在没有安全记录的情况下。 在返回证书之前,移民必须成功地写出安全的储存。 遗留文件被保存,不会被自动删除. 被锁定的商店或失败的写入被报告;适配器不会回到使用平正文本密钥.
撤销会写出一个空的安全记录作为持久标记,防止所保留的遗留文件再导入被移除的密钥. 取代或撤销证书也会取消提供商活跃的本地会话. 证书访问和本地开始接受共享一个锁, 因此排队的开始不能绕过撤销 。 存储的密钥从未被配置文件 - 可用性 API 返回 .
建立和核查边界
从此包目录 :
bun run build
bun test src
bun run verify
bun pm pack
cargo test --manifest-path rust/Cargo.toml # UPDATE_BINDINGS=1 regenerates src/generated/commands.ts
cargo test -p alwith-voice-impl --manifest-path ../../Cargo.toml
本地图书馆每个平台建造并组装成 native/ 在释放。 在发布前在每个支持的主机平台运行 Rust 测试. 单身 THIRD_PARTY_LICENSES.txt 包含本地图书馆的全部第三方许可、版权和通知文本,并必须与该套件一起申请 LICENSE。软件包许可证不变.
自动覆盖包括PCM尾巴,抓取设置时被取消,队列界限,草稿所有权,控制器定稿,免手接取/完成, stale callback,首选,静音检测,以及设备列表生命周期. 原生测试覆盖协议框架,本地WebSocket同平端,事件元数据/卫生,供应商取消,以及关闭. U对共享控制/设置,文件生成,以及使用假的秘密后端的认证迁移/撤销进行整合测试. 共享- crate 集成测试创建并关闭一个没有库文件的服务. 本地同行和假身份证明不能与现场服务或实际的OS认证对话框建立相容性.
预包装钩子重建了 JavaScript 并检查插件是否保留了适配器,箱子/包装版本对齐,即 rust/ 没有打包,框架独立的核心条目和生产JSX产出.
经过修改后重建并测试准确安装的文物. 特别是检查生产 反应输出用途 react/jsx-runtime;仅凭发展并不能证明这一点。 另一次修订的测试计数不是该候选人的证据.
真正的VUI/Doubao识别,OS认证提示,麦克风权限/设备行为,Windows运行时行为,以及签名的应用程序接受仍然是单独的验证要求. 无法启用自动提供者倒置、背景重试、记录记录或音频记录。 在生产推出前完成现场提供者和签名平台核查.
Doubao 资源选择
VoicePreferences.doubaoResourceId 配置 X-Api-Resource-Id 头曰. 默认是 volc.seedasr.sauc.duration; 旧被保存的首选项在加载时获得此默认值 。 Doubao 设置表接受账户启用的另一资源, 例如 volc.seedasr.sauc.concurrent。这是普通的配置,不是证书。 缺少或空白值选择默认资源。 无效的标题字符被拒绝 .
主机传递值为 StartOptions.resourceId。排除会维护现有主机的默认值。 VUI 不发送此信头 。 设置在每次录音开始时被读取,包括之后的无手回合;活录保存了它的原始资源. 报告资源出错时没有自动资源切换.
键盘手势
主机可以启用 VoiceControls.optionTap 并提供本地化 shortcutHint。在活跃的聊天窗口中,在500 ms以内有两个干净的可选/可选自带开始录制;一个自带完成录制。 在连接或手无寸铁的回复时, 一个自带会取消该交互 。 最终化忽略了自带. 被修改的和弦,长柄,密钥重复,IME组成,指针交互,并失去窗口焦点重置手势. 打开菜单/对话框可以防止启动, 但不能阻断完成或取消活动互动 。 U 启用此手势, 匹配桌面语音分支 。 没有 OS- global 快捷键注册 .
无头反应交互
useVoiceInteraction 从 @alwith/module-voice/react 提供完整的语音交互而不渲染UI. VoiceControls 内部使用同一种钩. 抓取,流出更新草稿,静音检测,呈递,无手循环,可选选项/可选手势,以及清理仍然共享.
UseVoiceInteractionOptions 接受 host, (中文(简体) ), transport, (中文(简体) ), capture, (中文(简体) ), enabled选项 optionTap,可选稳定 cancelRef。东道方合同匹配 VoiceControls.host。保持编辑对象的草稿、运输并取消更改身份的稳定;改变它们可以处理旧的交互。 禁用取消活动交互并阻止新录制. 取消的参考文献保留了目前的草案文本.
结果暴露了 state (单位:千美元)phase, (中文(简体) ), waiting)和稳定行动:
start(): Promise<void>开始录制.finish(): Promise<void>完成并等待提供者的最终结果.toggle(): Promise<void>启动、 完成记录, 或取消连接/ rep 等待; 定稿忽略了切换 .cancel(restore: boolean): void取消;true恢复原有的草稿,false保留当前文本.
业务错误通过报告 host.onError。处理动作承诺拒绝如下所示;在卸载拒绝/扔出之后呼吁采取的行动.
import { useVoiceInteraction, type UseVoiceInteractionOptions } from "@alwith/module-voice/react"
import type { ReactNode } from "react"
function CustomVoicePanel(options: UseVoiceInteractionOptions): ReactNode {
const { state, toggle, cancel } = useVoiceInteraction(options)
return (
<section aria-label="Voice input">
<output aria-live="polite">{state.waiting ? "Waiting for reply" : state.phase}</output>
<button
disabled={!options.enabled || state.phase === "finishing"}
onClick={() => { void toggle().catch(options.host.onError) }}>
{state.waiting || state.phase === "starting" ? "Cancel" : state.phase === "recording" ? "Finish" : "Start"}
</button>
<button onClick={() => cancel(true)}>Discard recording</button>
</section>
)
}
每个活跃作曲家上架一个交互钩. 不要挂在旁边 VoiceControls 同一草案:该部分已经拥有实例。 主机拥有布局,造型,标签,图标,和动画. 下级 useVoice 钩子仍然可供单会话使用,而无需聊天交互管弦.
合并第三方许可证
运行 bun run licenses 更改 Rust 依赖关系后。 它收集锁定的 macOS ARM64 和 Windows x64 依赖图并写入 THIRD_PARTY_LICENSES.txt包括组件身份、版本、来源和完整的许可证/通知文本,不重复. bun run licenses:check 重现内存中的预期内容, 并在差异中失败; 预包运行此检查 .
license-evidence.json 正在为三个省略许可证文件的上方箱档案建立输入。 它保留了准确的文本和被标注的上游URL,不包含在npm包中,这些版本改变时需要审查. 使用不同依赖性版本或额外目标的主机必须包括适用于其自身已解决的构件的通知.
只有主机阶段 LICENSE 财务报告和审定财务报表 THIRD_PARTY_LICENSES.txt 为了声音。 其他模块的许可证文件是独立的.
代码实时呼叫
useCodexRealtimeVoice 从 /react 财务报告和审定财务报表 RealtimeVoice 从 /audio 添加双向WebRTC呼叫 现有 Codex ACP会话. 主机提供已发布的能力客户端的实时方法,一个会话ID,接纳状态,以及可见错误报告. codexRealtimeSignaling 绘制通过非加太公司进行SDP交换的地图; 证书和辅助代理仍然为Codex所有。 没有创建新的对话,也没有第二笔录店.
电话传过去 idle, (中文(简体) ), connecting, (中文(简体) ), connected,以及 closing连接意味着谈判媒体,而不仅仅是接受的启动请求。 30秒的设定期限报告失败. 结束一个呼叫立即释放出本地媒体,然后等待远程停止确认. 更改绑定会话, 禁用控件, 或卸载取消调用 。 拒绝启动,错误的信号,运输损失,设备去除,以及回放拒绝都是明显的失败;不存在重试或提供者倒置. 主办方不得同时开始口述,在表面放弃所有权时必须停止呼叫. 代码账户必须支持实时;单靠CLI是不够的.