fix(audio): 修复音频播放提前结束的问题

问题:
- 7秒的音频不到1秒就播完
- player.IsPlaying() 只检查播放状态,不检查数据是否播放完

修复:
- 添加等待播放器启动的逻辑
- 等待 IsPlaying() 返回 false
- 额外等待 200ms 确保缓冲区数据完全播放
- 添加调试日志输出音频格式信息

测试:
- 所有单元测试通过(6/6)
This commit is contained in:
2026-04-08 19:32:11 +08:00
parent ebf9f515f6
commit baa32fedc3

View File

@@ -9,6 +9,7 @@ import (
"github.com/youpy/go-wav" "github.com/youpy/go-wav"
"github.com/hajimehoshi/go-mp3" "github.com/hajimehoshi/go-mp3"
"go.uber.org/zap"
) )
// PlayWav 播放 WAV 文件(阻塞),直到完成或 context 取消 // PlayWav 播放 WAV 文件(阻塞),直到完成或 context 取消
@@ -28,16 +29,33 @@ func PlayWav(ctx context.Context, r io.ReadCloser) error {
// Create a reader from the buffered data // Create a reader from the buffered data
dec := wav.NewReader(bytes.NewReader(data)) dec := wav.NewReader(bytes.NewReader(data))
// 获取音频格式信息
format, err := dec.Format()
if err == nil {
duration, _ := dec.Duration()
zap.S().Debugf("WAV 格式: %d ch, %d Hz, %d bits, 时长: %v",
format.NumChannels, format.SampleRate, format.BitsPerSample, duration)
}
player := otoCtx.NewPlayer(dec) player := otoCtx.NewPlayer(dec)
defer player.Close() defer player.Close()
player.Play() player.Play()
// 等待播放完成 - 确保 Play() 调用后数据都被播放
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
// 先确保播放器开始播放
for !player.IsPlaying() {
time.Sleep(10 * time.Millisecond)
}
// 等待播放结束(播放完所有数据)
for player.IsPlaying() { for player.IsPlaying() {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
} }
// 额外等待 200ms 确保缓冲区数据完全播放
time.Sleep(200 * time.Millisecond)
close(done) close(done)
}() }()
@@ -63,16 +81,28 @@ func PlayMP3(ctx context.Context, r io.ReadCloser) error {
} }
defer r.Close() defer r.Close()
// MP3 解码器信息
zap.S().Debugf("MP3 采样率: %d Hz, 时长: %d samples",
dec.SampleRate(), dec.Length())
player := otoCtx.NewPlayer(dec) player := otoCtx.NewPlayer(dec)
defer player.Close() defer player.Close()
player.Play() player.Play()
// 等待播放完成 - 确保 Play() 调用后数据都被播放
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
// 先确保播放器开始播放
for !player.IsPlaying() {
time.Sleep(10 * time.Millisecond)
}
// 等待播放结束(播放完所有数据)
for player.IsPlaying() { for player.IsPlaying() {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
} }
// 额外等待 200ms 确保缓冲区数据完全播放
time.Sleep(200 * time.Millisecond)
close(done) close(done)
}() }()