package handler import ( "time" "github.com/qy/hw-ws-service/internal/audio" "github.com/qy/hw-ws-service/internal/connection" ) // SendOpusStream 将 Opus 帧列表按 60ms/帧的节奏流控发送给硬件。 // // 流控策略: // 1. 预缓冲:前 PreBufferCount 帧立即发送,减少硬件首帧延迟 // 2. 时序流控:按 (帧序号 × 60ms) 计算期望发送时间,select 等待 // 3. 打断:监听 abortCh,收到关闭信号立即返回 func SendOpusStream(conn *connection.Connection, frames [][]byte, abortCh <-chan struct{}) { if len(frames) == 0 { return } startTime := time.Now() playedMs := 0 // 阶段1:预缓冲,快速发送前 N 帧 pre := audio.PreBufferCount if pre > len(frames) { pre = len(frames) } for _, f := range frames[:pre] { select { case <-abortCh: return default: } conn.SendBinary(f) //nolint:errcheck // 连接断开时下一次 ReadMessage 会返回错误 } playedMs = pre * audio.FrameDurationMs // 阶段2:时序流控 for _, f := range frames[pre:] { expectedAt := startTime.Add(time.Duration(playedMs) * time.Millisecond) delay := time.Until(expectedAt) if delay > 0 { select { case <-time.After(delay): // 到达预期发送时间,继续 case <-abortCh: return } } // delay <= 0:处理比预期慢,追赶进度,直接发送 select { case <-abortCh: return default: } conn.SendBinary(f) //nolint:errcheck playedMs += audio.FrameDurationMs } }