Files
mapleafgo e4c34f0eec refactor(tts): TTS 极简重构与代码质量提升
## 核心改进

### TTS 模块重构
- 统一 API,仅保留 Sound(ctx, text) 方法
- 优化日志,添加 [TTS] 前缀和结构化字段
- 实现互斥等待:同时只播放一个,新请求等待旧播放完成
- 响应 context 取消:超时或断开时立即停止播放
- 移除全局 context 存储,改为参数传递
- 简化实例化:New(config) 无需传入 context

### 代码质量提升
- 修复 PlayWav/PlayMP3 的死循环 bug(context 取消时缺少 return)
- 修复 standby_ctrl/pause.go 的忙循环(添加 Sleep 避免CPU 100%)
- 添加关键路径错误传播(only_video.go 不再忽略播放错误)
- 新增 pkg/errorsx/handler.go 统一错误处理工具

## 代码优化
- TTS 代码从 234 行精简到 166 行(减少 29%)
- 移除冗余状态管理(playing 标志、等待循环)
- 利用互斥锁的阻塞特性实现优雅等待
- 保持简洁易读的代码风格

## 行为说明
 同时只能播放一个 TTS(互斥)
 新请求等待当前播放完成(不打断)
 响应 context 取消(超时停止)
 日志完善,便于排查问题

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 14:05:16 +08:00

71 lines
1.5 KiB
Go

package middleware
import (
"context"
"game-driver/internal/schema"
"game-driver/leaf"
"game-driver/pkg/tts"
"go.uber.org/zap"
"sync"
"time"
)
// TickerAction 定时器动作,用于在指定时间点执行打印和语音播报
func TickerAction() leaf.HandlerFunc {
return func(c *leaf.Context) {
pm := leaf.Value[*schema.PlayModal](c, PayloadJSONKey)
// 构建打印和语音播报的时间映射
printMap := make(map[int]schema.PrintModal, len(pm.Print))
for _, p := range pm.Print {
printMap[p.Time] = p
}
ttsMap := make(map[int]schema.TTSTimer, len(pm.TTS.Timer))
for _, t := range pm.TTS.Timer {
ttsMap[t.Time] = t
}
// 等待组
var wait sync.WaitGroup
defer wait.Wait()
// 结束信号通道
a := make(chan struct{})
// 发送结束信号
defer close(a)
wait.Add(1)
go func(ctx context.Context) {
start := time.Now()
defer wait.Done()
// 定时器
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
zap.S().Infoln("开始 Ticker 计时")
defer zap.S().Infoln("结束 Ticker 计时")
for over := false; !over; {
select {
case <-a:
over = true
case <-ctx.Done():
zap.S().Infoln("Ticker 计时被取消")
over = true
case m := <-ticker.C:
{
s := int(m.Sub(start).Seconds())
if _, ok := printMap[s]; ok {
//TODO: 屏幕打印
}
if to, ok := ttsMap[s]; ok {
tts.DefaultTTS.Sound(ctx, to.Value)
}
}
}
}
}(c)
c.Next()
}
}