feat(audio): 添加音频播放进度监控和停滞检测

为诊断 TTS 音频播放卡死问题,在 PlayWav 函数中添加实时播放进度监控:

- 每秒打印当前播放位置、进度百分比和播放时间
- 检测播放停滞(位置不变时打印警告)
- 改进日志输出,显示总样本数和预计时长
- 移除 select case 中的多余花括号

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-08 16:38:35 +08:00
parent b0f07624b0
commit cbccb07398

View File

@@ -2,13 +2,14 @@ package audio
import (
"context"
"io"
"time"
"github.com/gopxl/beep/v2"
"github.com/gopxl/beep/v2/mp3"
"github.com/gopxl/beep/v2/speaker"
"github.com/gopxl/beep/v2/wav"
"go.uber.org/zap"
"io"
"time"
)
var DefaultSampleRate = beep.SampleRate(44100)
@@ -30,7 +31,11 @@ func PlayWav(c context.Context, r io.Reader) {
}
defer streamer.Close()
zap.S().Debugln("WAV解码成功采样率:", format.SampleRate)
// 获取音频长度信息
totalSamples := streamer.Len()
zap.S().Debugf("WAV解码成功采样率: %d, 总样本数: %d, 预计时长: %.2f秒",
format.SampleRate, totalSamples, float64(totalSamples)/float64(format.SampleRate))
s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer)
ctrl := &beep.Ctrl{Streamer: s}
@@ -41,18 +46,32 @@ func PlayWav(c context.Context, r io.Reader) {
})))
zap.S().Debugln("等待音频播放完成...")
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
lastPos := 0
for {
select {
case <-done:
zap.S().Infoln("音频播放正常结束")
return
case <-c.Done():
{
zap.S().Infoln("音频播放被 context 取消")
zap.S().Debugf("音频播放被 context 取消: %v", c.Err())
speaker.Lock()
ctrl.Streamer = nil
speaker.Unlock()
return
case <-ticker.C:
// 获取当前播放位置
pos := streamer.Position()
if pos != lastPos {
progress := float64(pos) / float64(totalSamples) * 100
currentTime := float64(pos) / float64(format.SampleRate)
zap.S().Debugf("播放进度: %d/%d (%.1f%%), %.2f秒", pos, totalSamples, progress, currentTime)
lastPos = pos
} else {
zap.S().Debugf("播放停滞在位置: %d/%d, Streamer状态: %v",
pos, totalSamples, ctrl.Streamer != nil)
}
}
}
@@ -79,12 +98,10 @@ func PlayMP3(c context.Context, r io.ReadCloser) {
case <-done:
return
case <-c.Done():
{
speaker.Lock()
ctrl.Streamer = nil
speaker.Unlock()
return
}
}
}
}