127 lines
2.7 KiB
Go
127 lines
2.7 KiB
Go
package tts
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"game-driver/config"
|
|
"game-driver/leaf"
|
|
"game-driver/pkg/audio"
|
|
"game-driver/pkg/errorsx"
|
|
"game-driver/pkg/logger"
|
|
"io"
|
|
"log"
|
|
"time"
|
|
|
|
nls "github.com/aliyun/alibabacloud-nls-go-sdk"
|
|
)
|
|
|
|
type AliTTS struct {
|
|
config.AliyunConfig
|
|
ctx context.Context
|
|
tokenResult nls.TokenResult
|
|
}
|
|
|
|
type result struct {
|
|
Data io.ReadWriter
|
|
Error error
|
|
}
|
|
|
|
var DefaultTTS = &AliTTS{}
|
|
|
|
// onTaskFailed 识别过程中的错误处理回调参数
|
|
func (tts *AliTTS) onTaskFailed(text string, param interface{}) {
|
|
p, _ := param.(*result)
|
|
p.Error = fmt.Errorf("语音合成异常: %v", text)
|
|
}
|
|
|
|
// onSynthesisResult 语音合成数据回调参数
|
|
func (tts *AliTTS) onSynthesisResult(data []byte, param interface{}) {
|
|
p, _ := param.(*result)
|
|
p.Data.Write(data)
|
|
}
|
|
|
|
func (tts *AliTTS) Sound(text string) {
|
|
if text == "" {
|
|
return
|
|
}
|
|
buf, err := tts.Get(text)
|
|
if err == nil && buf != nil {
|
|
audio.PlayWav(tts.ctx, buf)
|
|
} else {
|
|
logger.Errorln("AliTTS 请求异常: ", err)
|
|
}
|
|
}
|
|
|
|
func (tts *AliTTS) getToken() error {
|
|
if tts.tokenResult.ExpireTime != 0 && time.Unix(tts.tokenResult.ExpireTime, 0).After(time.Now()) {
|
|
return nil
|
|
}
|
|
tts.tokenResult = nls.TokenResult{}
|
|
resultMessage, err := nls.GetToken("cn-shanghai", "nls-meta.cn-shanghai.aliyuncs.com", tts.AccessKeyID, tts.AccessKeySecret, "2019-02-28")
|
|
if err != nil {
|
|
return err
|
|
} else if resultMessage.ErrMsg != "" {
|
|
return errorsx.ThirdPartyErr
|
|
}
|
|
tts.tokenResult = resultMessage.TokenResult
|
|
return nil
|
|
}
|
|
|
|
func (tts *AliTTS) Get(text string) (io.Reader, error) {
|
|
param := nls.DefaultSpeechSynthesisParam()
|
|
param.Volume = 100
|
|
|
|
err := tts.getToken()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
connectConfig := nls.NewConnectionConfigWithToken(nls.DEFAULT_URL, tts.AppKey, tts.tokenResult.Id)
|
|
|
|
logger := nls.NewNlsLogger(leaf.DefaultWriter, "", log.LstdFlags|log.Ltime)
|
|
logger.SetLogSil(false)
|
|
logger.SetDebug(true)
|
|
|
|
ttsData := &result{
|
|
Data: &bytes.Buffer{},
|
|
}
|
|
|
|
synthesis, err := nls.NewSpeechSynthesis(
|
|
connectConfig, logger, false,
|
|
tts.onTaskFailed, tts.onSynthesisResult, nil,
|
|
nil, nil, ttsData,
|
|
)
|
|
if err != nil {
|
|
return ttsData.Data, err
|
|
}
|
|
defer synthesis.Shutdown()
|
|
|
|
ch, err := synthesis.Start(text, param, nil)
|
|
if err != nil {
|
|
return ttsData.Data, err
|
|
}
|
|
|
|
// 等待语音合成结束
|
|
select {
|
|
case done := <-ch:
|
|
{
|
|
if !done {
|
|
return ttsData.Data, errorsx.ThirdPartyErr
|
|
}
|
|
return ttsData.Data, nil
|
|
}
|
|
case <-time.After(time.Duration(tts.Timeout) * time.Second):
|
|
return ttsData.Data, errorsx.DriverTimeoutErr
|
|
case <-tts.ctx.Done():
|
|
return ttsData.Data, errorsx.DriverCancelErr
|
|
}
|
|
}
|
|
|
|
func New(ctx context.Context, config config.AliyunConfig) *AliTTS {
|
|
return &AliTTS{
|
|
ctx: ctx,
|
|
AliyunConfig: config,
|
|
}
|
|
}
|