Files
sundynix-agentix/sundynix-gateway/internal/voice/protocol.go
T
Blizzard 15f5a85612 feat(voice): WebSocket 端点 + 客户端↔网关协议(Phase 1 地基)
加 gorilla/websocket(无 genproto 冲突)。voice/protocol.go 定死单条 WS 的消息协议:
二进制帧=音频(上行麦克风/下行TTS),文本帧=JSON 控制/事件(ClientMsg:start/end/barge_in/
bye;ServerMsg:ready/transcript/task/speaking/tts_end/error);音频 PCM 16k 单声道。
handler/voice.go: GET /api/v1/voice/stream 升级 WS,鉴权走 AuthFromHeaderOrQuery(?token=,
WS 带不了 Bearer),会话外壳 + 协议读循环(音频帧/控制消息分派)已通,火山 ASR/TTS 客户端
在下一步挂 onAudio/onControl 的 TODO 点接入。build+vet+test 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 17:17:58 +08:00

55 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package voice
// 客户端 ↔ 网关的单条 WebSocket 消息协议(设计 VOICE_DESIGN.md D3):
// 一条连接同时承载上行音频、下行转写、下行 TTS 音频,用「帧类型 + JSON 消息类型」区分。
//
// - 二进制帧(BinaryMessage):纯音频 PCM
// · 上行 = 用户麦克风音频(喂 ASR)
// · 下行 = Agent 回答的 TTS 音频(客户端播放)
// - 文本帧(TextMessage, JSON):控制与事件(下方 ClientMsg / ServerMsg
// ClientMsg 是客户端发来的控制消息(文本帧)。音频走二进制帧,不在此。
type ClientMsg struct {
Type string `json:"type"`
// start:一轮语音开始(可带当前画布编排图,用它跑而非默认 DSL)
Graph string `json:"graph,omitempty"`
// 其它类型无额外字段:end(用户说完)、barge_in(打断,用户又开口)、bye(结束会话)
}
// 客户端消息类型。
const (
ClientStart = "start" // 一轮语音开始
ClientEnd = "end" // 用户说完(静音检测或手动结束)→ 触发任务
ClientBargeIn = "barge_in" // 打断:用户在 Agent 说话时又开口 → 停 TTS
ClientBye = "bye" // 结束整个语音会话
)
// ServerMsg 是网关下发的控制/事件消息(文本帧)。TTS 音频走二进制帧,不在此。
type ServerMsg struct {
Type string `json:"type"`
// transcriptASR 转写(Final=false 为实时部分结果,true 为最终)
Text string `json:"text,omitempty"`
Final bool `json:"final,omitempty"`
// task:转写完成、任务已提交,带 task_id 供客户端切运行视图
TaskID string `json:"task_id,omitempty"`
// error:出错文案
Msg string `json:"msg,omitempty"`
}
// 服务端消息类型。
const (
ServerReady = "ready" // 会话就绪,可以开始说话
ServerTranscript = "transcript" // ASR 转写结果(部分/最终)
ServerTask = "task" // 任务已提交(带 task_id
ServerSpeaking = "speaking" // Agent 开始出声(首段 TTS 音频将至)
ServerTTSEnd = "tts_end" // 本轮 TTS 播放完毕
ServerError = "error" // 出错
)
// 音频格式(与火山 ASR/TTS 约定,客户端按此采集/播放)。
const (
AudioSampleRate = 16000 // 上行 ASR16kHz
AudioBits = 16 // 16bit
AudioChannels = 1 // 单声道
)