package audio import ( "context" "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) func init() { err := speaker.Init(DefaultSampleRate, DefaultSampleRate.N(time.Second/10)) if err != nil { panic("扬声器初始化异常: " + err.Error()) } zap.S().Infoln("扬声器初始化完成") } func PlayWav(c context.Context, r io.Reader) { zap.S().Debugln("开始 WAV 解码") streamer, format, err := wav.Decode(r) if err != nil { zap.S().Errorln("WAV解码失败: ", err) return } defer streamer.Close() zap.S().Debugln("WAV解码成功,采样率:", format.SampleRate) s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer) ctrl := &beep.Ctrl{Streamer: s} done := make(chan struct{}) speaker.Play(beep.Seq(ctrl, beep.Callback(func() { zap.S().Debugln("音频播放完成") close(done) }))) zap.S().Debugln("等待音频播放完成...") for { select { case <-done: zap.S().Infoln("音频播放正常结束") return case <-c.Done(): { zap.S().Infoln("音频播放被 context 取消") speaker.Lock() ctrl.Streamer = nil speaker.Unlock() return } } } } func PlayMP3(c context.Context, r io.ReadCloser) { streamer, format, err := mp3.Decode(r) if err != nil { zap.S().Errorln("MP3解码失败: ", err) return } defer streamer.Close() s := beep.Resample(4, format.SampleRate, DefaultSampleRate, streamer) ctrl := &beep.Ctrl{Streamer: s} done := make(chan struct{}) speaker.Play(beep.Seq(ctrl, beep.Callback(func() { close(done) }))) for { select { case <-done: return case <-c.Done(): { speaker.Lock() ctrl.Streamer = nil speaker.Unlock() return } } } }