语音输入

English | 中文

实验性语音识别包含三个角色:服务定义路由具名 Provider,SenseVoice Provider拥有本地推理,Remote 消费者服务浏览器。可选 Bundle将它们与麦克风 UI 组合。

Provider 选择

SpeechProviderId 为注册标识添加类型品牌。SpeechProviderInfo 携带显示名称、支持的 languages 语言提示及 host-local 或 cloud 处理位置。SpeechRequest 包含 WAV 字节和可选的 Provider、语言选择;resolve() 生成捕获一个 Provider 实例的 SpeechSpec。缺失的 Provider 或不支持的语言会报错;替换或撤销会使已解析的任务失效。音频不会回退到其他 Provider。

SpeechProvider.transcribe() 接收完整的 SpeechInput 与 AbortSignal。Transcript 返回纯文本 text、audioSeconds 和 inferenceSeconds。Provider 响应取消,并在注销完成前结束其任务。本地 Provider 串行执行调用、限制队列,并独立于 Session 管理工作进程生命周期。

浏览器与 Host 所有权

浏览器拥有麦克风轨道与未发送的草稿。TranscriptionRequest 通过带认证的 Remote 发送规范 base64 PCM16 WAV。SpeechCatalog 公布可用 Provider、默认选择及录音字节和时长限制。API 在识别前校验这些进程输入。

输入门面在录音前捕获带版本的选区。InputActions.insertText() 仅在选区版本仍有效且提交状态允许编辑时,插入一次可撤销的纯文本编辑。插入被拒绝时,转写文字保留以供显式插入。切换 Session 或释放插件使迟到结果失效。识别本身不写入 Session 事件;普通用户提交拥有最终的模型可见文字。

准备与设置

SpeechProviderInfo.downloadSources 公布准备阶段的源。SpeechPreparationOptions.downloadSource 为单次任务选择一个源;省略时保留提供方策略。SenseVoice 校验公布的选项,固定使用手动指定的源而不回退,并拒绝在准备期间改源。UI 为当前卡片中的重试保留选择,但不会将其保存为识别偏好。

Host Provider 在页面和 Session 变化期间拥有同一个准备任务。Client 在输入框、安装引导弹窗、Bundle 详情之间共享一份 follow() 订阅。可选 SpeechSetupEstimate 元数据提供各 Provider 的资源预期,与实测进度分开。SpeechPreparationStepKind 标识有序资源操作;SpeechPreparationStep 记录各步骤状态与开始时间。完整 SpeechPreparationState 在取消或失败后保留这些步骤。折叠 UI 显示当前操作,展开后列出所有步骤,仅进行中步骤显示字节进度或等待时间。关闭观察者不会取消准备。已校验文件在重试及空闲进程回收后继续复用。

准备失败时可包含 SpeechDownloadFailure,提供文件、下载源、原因分类以及可选错误码或 HTTP 状态。Client 将恢复建议本地化;原始下载错误留在 Host。

麦克风占用模型选择器与发送按钮之间的 conversation.input.activity。点击开始录音并展开工具栏;停止后转写并插入草稿。活动栏保留编辑器与提交按钮,拥有局部反馈,并在卸载时释放展开状态。取消、Escape 或隐藏页面会丢弃录音。波形历史展示实测麦克风音量。Bundle 详情包含识别偏好、准备状态和进度。显式启用时通过 plugins.bundle.activation 引导缺少模型的用户前往安装;列表只显示 Bundle 描述和开关。

设计依据

语音输入决策解释临时音频、显式 Provider 选择和延迟准备本地运行时。

Cordis API

Generated from source by scripts/gen-cordis-catalog.ts (verified fresh by pnpm run verify-cordis-catalog in doc-sync; regenerate with pnpm run gen-cordis-catalog) — the language sides differ only in locale-specific paired document paths. Signature blocks use a ts cordis-catalog fence and keep the original source JSDoc; dispatch modes are defined in the primer, and the framework-inherited ctx API lives in cordis-api/inherited.md.

ctx.speechController — SpeechController

Speech calls never activate or submit to an Agent.

```ts cordis-catalog /* * Read provider choices without preparing a recognizer. * @returns available providers, resolved default, and recording limits. / @Remote catalog(): SpeechCatalog

/* * Follow provider readiness independently of Session and preparation lifetimes. * @param signal - Client observation lifetime. * @returns initial and subsequent complete readiness snapshots. / @Remote({ mode: 'stream' }) async *follow(signal: AbortSignal): AsyncIterable

/* * Persist the user's recognition preferences. * @param patch - changed preference fields. * @returns after preferences are saved. / @Remote configure(patch: SpeechSelectionPatch): Promise

/* * Start or join one Host-owned preparation task. * @param providerId - selected recognizer. * @param options - task-local source selection validated by the provider. / @Remote prepare(providerId: SpeechProviderId, options?: SpeechPreparationOptions): void

/* * Explicitly cancel resource preparation. * @param providerId - selected recognizer. * @returns after the preparation task settles. / @Remote cancelPreparation(providerId: SpeechProviderId): Promise

/* * Validate and transcribe one recording through the explicit provider selection. * @param request - canonical WAV encoded as base64, provider id and language hint. * @param signal - Client cancellation or Remote contribution disposal. * @returns final transcript without adding a Session event. / @Remote async transcribe(request: TranscriptionRequest, signal: AbortSignal): Promise


Source: [`packages/experimental/api-speech-to-text/src/index.ts`](../../packages/experimental/api-speech-to-text/src/index.ts)

<a id="ctxspeechtotext--speechtotext"></a>

### `ctx.speechToText` — `SpeechToText`

Registry shared by all transcription consumers in one Host composition.

```ts cordis-catalog
/**
 * Register one recognizer; duplicate ids fail without replacing the original.
 * @param provider - recognizer owned by the contributing fiber.
 * @returns idempotent disposer which rejects admission, cancels, and joins accepted work.
 */
register(provider: SpeechProvider): () => Promise<void>

/**
 * Read the current recognizer roster.
 * @returns available provider facts in registration order.
 */
listProviders(): readonly SpeechProviderInfo[]

/**
 * Observe complete readiness snapshots; a slow reader coalesces intermediate progress.
 * @param caller - observer lifetime, independent of any preparation task.
 * @returns an initial snapshot followed by the latest provider states.
 */
async *follow(caller: AbortSignal): AsyncIterable<SpeechSnapshot>

/**
 * Read provider readiness and current user preferences together.
 * @returns one detached complete observation.
 */
snapshot(): SpeechSnapshot

/**
 * Persist changed selection fields into this plugin's profile entry; the resulting language must be accepted by the selected provider.
 * @param patch - explicit provider or language changes.
 * @returns after the profile write and the live update it applies.
 */
async configure(patch: SpeechSelectionPatch): Promise<void>

/**
 * Start or join provider-owned preparation.
 * @param id - exact registered provider identity.
 * @param options - task-local source selection validated by the provider.
 */
prepare(id: SpeechProviderId, options?: SpeechPreparationOptions): void

/**
 * Explicitly cancel provider preparation without tying it to a browser connection.
 * @param id - exact registered provider identity.
 * @returns after the preparation task settles.
 */
async cancelPreparation(id: SpeechProviderId): Promise<void>

/**
 * Apply composition defaults and capture the selected provider. Missing providers and unsupported languages fail explicitly.
 * @param request - complete recording and optional selection.
 * @returns provider-pinned input for transcribe().
 */
resolve(request: SpeechRequest): SpeechSpec

/**
 * Execute exactly the resolved provider; no fallback sends audio elsewhere.
 * @param spec - resolved input; a withdrawn or replaced registration is rejected.
 * @param signal - caller cancellation.
 * @returns final transcript after provider settlement.
 */
async transcribe(spec: SpeechSpec, signal: AbortSignal): Promise<Transcript>

Source: packages/experimental/speech-to-text/src/index.ts