feat: 启用豆包二遍识别模式以提升实时性和准确率

- 切换到 bigmodel_async endpoint 并启用 enable_nonstream
- 第一遍流式识别提供实时文字预览
- VAD 分句后自动触发第二遍非流式识别提升准确率
- 修改文本处理逻辑从累加改为替换(适配 full 模式)
- 统一配置字段命名:app_key → app_id, access_key → access_token
This commit is contained in:
2026-03-01 21:34:54 +08:00
parent e4b5841c93
commit 8c7b9b45fd
7 changed files with 55 additions and 53 deletions

View File

@@ -62,21 +62,21 @@ func (h *Handler) handleConn(c *websocket.Conn) {
defer close(resultCh)
// Writer goroutine: single writer to avoid concurrent writes
// Accumulates all result texts; paste is triggered by stop, not by ASR final.
// bigmodel_async with enable_nonstream: server returns full text each time (not incremental)
// We replace preview text on each update instead of accumulating.
var wg sync.WaitGroup
var accMu sync.Mutex
var accText string
var previewMu sync.Mutex
var previewText string
wg.Add(1)
go func() {
defer wg.Done()
for msg := range resultCh {
// Accumulate text from both partial and final results
// Replace preview text with latest result (full mode)
if msg.Type == MsgPartial || msg.Type == MsgFinal {
accMu.Lock()
accText += msg.Text
// Send accumulated preview to phone
preview := ServerMsg{Type: msg.Type, Text: accText}
accMu.Unlock()
previewMu.Lock()
previewText = msg.Text
preview := ServerMsg{Type: msg.Type, Text: previewText}
previewMu.Unlock()
if err := c.WriteMessage(websocket.TextMessage, preview.Bytes()); err != nil {
log.Warn("ws write error", "err", err)
return
@@ -128,10 +128,10 @@ func (h *Handler) handleConn(c *websocket.Conn) {
if active {
continue
}
// Reset accumulated text for new session
accMu.Lock()
accText = ""
accMu.Unlock()
// Reset preview text for new session
previewMu.Lock()
previewText = ""
previewMu.Unlock()
sa, cl, err := h.asrFactory(resultCh)
if err != nil {
log.Error("asr start failed", "err", err)
@@ -154,11 +154,11 @@ func (h *Handler) handleConn(c *websocket.Conn) {
}
sendAudio = nil
active = false
// Now paste the accumulated text
accMu.Lock()
finalText := accText
accText = ""
accMu.Unlock()
// Paste the final preview text
previewMu.Lock()
finalText := previewText
previewText = ""
previewMu.Unlock()
if finalText != "" && h.pasteFunc != nil {
if err := h.pasteFunc(finalText); err != nil {
log.Error("auto-paste failed", "err", err)