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 ( import (
"context" "context"
"io"
"time"
"github.com/gopxl/beep/v2" "github.com/gopxl/beep/v2"
"github.com/gopxl/beep/v2/mp3" "github.com/gopxl/beep/v2/mp3"
"github.com/gopxl/beep/v2/speaker" "github.com/gopxl/beep/v2/speaker"
"github.com/gopxl/beep/v2/wav" "github.com/gopxl/beep/v2/wav"
"go.uber.org/zap" "go.uber.org/zap"
"io"
"time"
) )
var DefaultSampleRate = beep.SampleRate(44100) var DefaultSampleRate = beep.SampleRate(44100)
@@ -30,7 +31,11 @@ func PlayWav(c context.Context, r io.Reader) {
} }
defer streamer.Close() 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) s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer)
ctrl := &beep.Ctrl{Streamer: s} ctrl := &beep.Ctrl{Streamer: s}
@@ -41,18 +46,32 @@ func PlayWav(c context.Context, r io.Reader) {
}))) })))
zap.S().Debugln("等待音频播放完成...") zap.S().Debugln("等待音频播放完成...")
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
lastPos := 0
for { for {
select { select {
case <-done: case <-done:
zap.S().Infoln("音频播放正常结束") zap.S().Infoln("音频播放正常结束")
return return
case <-c.Done(): case <-c.Done():
{ zap.S().Debugf("音频播放被 context 取消: %v", c.Err())
zap.S().Infoln("音频播放被 context 取消") speaker.Lock()
speaker.Lock() ctrl.Streamer = nil
ctrl.Streamer = nil speaker.Unlock()
speaker.Unlock() return
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: case <-done:
return return
case <-c.Done(): case <-c.Done():
{ speaker.Lock()
speaker.Lock() ctrl.Streamer = nil
ctrl.Streamer = nil speaker.Unlock()
speaker.Unlock() return
return
}
} }
} }
} }