语音输入 VoiceInput 实现链路

lishihuan大约 2 分钟

语音输入 VoiceInput 实现链路

源码:VoiceInput.vue;输入条封装:ChatInput.vuevoiceMode)。

事件协议ASR流式协议.md(阿里/腾讯共用)

总览../README.md · 阿里 ../aliyun/ASR语音识别集成.md · 腾讯 ../tencent/ASR语音识别集成.md


约定

  • H5 只认原生下发的 eventasr_interimasr_session_completeasr_error 等(常量与 AsrStreamProtocol.java 一致)。
  • TERMINAL_ASR_EVENTSasr_session_completeasr_error
  • 不传、不解析 JSON 字段 isEnd

核心分支(_onStreamResult

eventH5
asr_interim_applyInterim;已接受的 interim 会重置静音 3s 计时
asr_sentence_end_sealSentence(进 committed)+ 启动 3s
asr_vad_end启动 3s
asr_session_complete_finishVoiceRecognition(立即收尾)
asr_error_finishVoiceRecognition

静音自动停录silenceTimeout > 0 时,句末/VAD/有效 interim 后 3s 无新活动_stopRecording()asr_session_complete 不再多等 3s。


展示与防回退

display = merge( merge(anchor, committed), interim )
  • interim:整段覆盖,非 diff。
  • _shouldAcceptInterimPartial:拒绝同长或更短的「回退」包(如「你好」→「你,」)。

streamToInput === true(默认)时 emit('update:text', display)hold-send 为 false,按住过程不写输入框、不 emit 预览。


发送竞态

ChatInput.onSend 最先调用 voiceInput.abortStreamSync()

  • 递增世代,丢弃后续迟到回调;
  • 若在录则停原生(type 31)。

避免「已点发送清空框 → 迟到 asr_interim 又写回」。


hold-send(豆包式)

ChatInput 驱动 VoiceInput 的 hold API,智能填单:voice-mode="hold-send"

步骤行为
点麦克风输入区切为「按住 说话」条(hideTrigger + 独立 voiceInputHold 实例)
touchstartbeginHold() → 拉 token、开流式 ASR
按住中不展示识别字、不 update:text
touchend(未上滑取消)endHold() → 等终稿 → done → ChatInput emit('send')
上滑 ≥ 72pxcancelHold()_holdDiscardResult=true,终稿在 _finishVoiceRecognition 入口丢弃

cancelHold 内部也会 abortStreamSync()


与 ChatInput 分工

模式VoiceInputChatInput
text侧边麦点击录音,silence-timeout=3000,流式写框多行输入 + 发送
hold-sendstream-to-input=false,hold API按住条 UI、上滑取消、松手 send

调试

  • H5:[ASR] event displayMode textcordovaPlugin onNative 已统一 parse 对象)。
  • 原生:adb logcat -s ALI_ASR,对照 vendorEvent