Categorygithub.com/aliyun/alibabacloud-nls-go-sdk
modulepackage
1.1.1
Repository: https://github.com/aliyun/alibabacloud-nls-go-sdk.git
Documentation: pkg.go.dev

# README

NLS Go SDK说明

本文介绍如何使用阿里云智能语音服务提供的Go SDK,包括SDK的安装方法及SDK代码示例。

前提条件

使用SDK前,请先阅读接口说明,详细请参见接口说明

下载安装

说明

  • SDK支持go1.16
  • 请确认已经安装golang环境,并完成基本配置
  1. 下载SDK

通过以下命令完成SDK下载和安装:

go get github.com/aliyun/alibabacloud-nls-go-sdk

  1. 导入SDK

在代码中通过将以下字段加入import来导入SDK:

import ("github.com/aliyun/alibabacloud-nls-go-sdk")

SDK常量

常量常量含义
SDK_VERSIONSDK版本
PCMpcm音频格式
WAVwav音频格式
OPUSopus音频格式
OPUopu音频格式
DEFAULT_DISTRIBUTE获取token时使用的默认区域,"cn-shanghai"
DEFAULT_DOMAIN获取token时使用的默认URL,"nls-meta.cn-shanghai.aliyuncs.com"
DEFAULT_VERSION获取token时使用的协议版本,"2019-02-28"
DEFAULT_URL默认公有云URL,"wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1"

SDK日志

1. func DefaultNlsLog() *NlsLogger

用于创建全局唯一的默认日志对象,默认日志以NLS为前缀,输出到标准错误

参数说明:

返回值:

NlsLogger对象指针

2. func NewNlsLogger(w io.Writer, tag string, flag int) *NlsLogger

创建一个新的日志

参数说明:

参数类型参数说明
wio.Writer任意实现io.Writer接口的对象
tagstring日志前缀,会打印到日志行首部
flagint日志flag,具体参考go官方log文档

返回值:

NlsLogger对象指针

3. func (logger *NlsLogger) SetLogSil(sil bool)

设置日志是否输出到对应的io.Writer

参数说明:

参数类型参数说明
silbool是否禁止日志输出,true为禁止

返回值:

4. func (logger *NlsLogger) SetDebug(debug bool)

设置是否打印debug日志,仅影响通过Debugf或Debugln进行输出的日志

参数说明:

参数类型参数说明
debugbool是否允许debug日志输出,true为允许

返回值:

5. func (logger *NlsLogger) SetOutput(w io.Writer)

设置日志输出方式

参数说明:

参数类型参数说明
wio.Writer任意实现io.Writer接口的对象

返回值:

6. func (logger *NlsLogger) SetPrefix(prefix string)

设置日志行的标签

参数说明:

参数类型参数说明
prefixstring日志行标签,会输出在日志行行首

返回值:

7. func (logger *NlsLogger) SetFlags(flags int)

设置日志属性

参数说明:

参数类型参数说明
flagsint日志属性,见https://pkg.go.dev/log#pkg-constants

返回值:

8. 日志打印

日志打印方法:

方法名方法说明
func (l *NlsLogger) Print(v ...interface{})标准日志输出
func (l *NlsLogger) Println(v ...interface{})标注日志输出,行尾自动换行
func (l *NlsLogger) Printf(format string, v ...interface{})带format的日志输出,format方式见go官方文档
func (l *NlsLogger) Debugln(v ...interface{})debug信息日志输出,行尾自动换行
func (l *NlsLogger) Debugf(format string, v ...interface{})带format的debug信息日志输出
func (l *NlsLogger) Fatal(v ...interface{})致命错误日志输出,输出后自动进程退出
func (l *NlsLogger) Fatalln(v ...interface{})致命错误日志输出,行尾自动换行,输出后自动进程退出
func (l *NlsLogger) Fatalf(format string, v ...interface{})带format的致命错误日志输出,输出后自动进程退出
func (l *NlsLogger) Panic(v ...interface{})致命错误日志输出,输出后自动进程退出并打印崩溃信息
func (l *NlsLogger) Panicln(v ...interface{})致命错误日志输出,行尾自动换行,输出后自动进程退出并打印崩溃信息
func (l *NlsLogger) Panicf(format string, v ...interface{})带format的致命错误日志输出,输出后自动进程退出并打印崩溃信息

获取token

1. func GetToken(dist string, domain string, akid string, akkey string, version string) (*TokenResultMessage, error)

获取访问token

参数说明:

参数类型参数说明
diststring区域,如果不确定,请使用DEFAULT_DISTRIBUTE
domainstringURL,如果不确定,请使用DEFAULT_DOMAIN
akidstring阿里云accessid
akkeystring阿里云accesskey
versionstring协议版本,如果不确定,请使用DEFAULT_VERSION

返回值:

TokenResultMessage对象指针和错误信息

建立连接

1. ConnectionConfig

用于建立连接的基础参数

参数说明:

参数类型参数说明
Urlstring访问的公有云URL,如果不确定,可以使用DEFAULT_URL
Tokenstring通过GetToken获取的token或者测试token
Akidstring阿里云accessid
Akkeystring阿里云accesskey
Appkeystringappkey,可以在控制台中对应项目上看到

2. func NewConnectionConfigWithAKInfoDefault(url string, appkey string, akid string, akkey string) (*ConnectionConfig, error)

通过url,appkey,akid和akkey创建连接参数,等效于先调用GetToken然后再调用NewConnectionConfigWithToken

参数说明:

参数类型参数说明
Urlstring访问的公有云URL,如果不确定,可以使用DEFAULT_URL
Appkeystringappkey,可以在控制台中对应项目上看到
Akidstring阿里云accessid
Akkeystring阿里云accesskey

返回值:

*ConnectionConfig:连接参数对象指针,用于后续创建语音交互实例

error:异常对象,为nil则无异常

3. func NewConnectionConfigWithToken(url string, appkey string, token string) *ConnectionConfig

通过url,appkey和token创建连接参数

参数说明:

参数类型参数说明
Urlstring访问的公有云URL,如果不确定,可以使用DEFAULT_URL
Appkeystringappkey,可以在控制台中对应项目上看到
Tokenstring已经通过GetToken或其他方式获取的token

返回值:

*ConnectionConfig:连接参数对象指针

4. func NewConnectionConfigFromJson(jsonStr string) (*ConnectionConfig, error)

通过json字符串来创建连接参数

参数说明

参数类型参数说明
jsonStrstring描述连接参数的json字符串,有效字段如下:url,token,akid,akkey,appkey。其中必须包含url和appkey,如果包含token则不需要包含akid和akkey

返回值:

*ConnectionConfig:连接对象指针

一句话识别

1. SpeechRecognitionStartParam

一句话识别参数

参数说明:

参数类型参数说明
Formatstring音频格式,默认使用pcm
SampleRateint采样率,默认16000
EnableIntermediateResultbool是否打开中间结果返回
EnablePunctuationPreditionbool是否打开标点预测
EnableInverseTextNormalizationbool是否打开ITN

2. func DefaultSpeechRecognitionParam() SpeechRecognitionStartParam

返回一个默认的推荐参数,其中format为pcm,采样率为16000,中间结果,标点预测和ITN全开

参数说明:

返回值:

默认参数

3. func NewSpeechRecognition(...) (*SpeechRecognition, error)

创建一个SpeechRecognition实例

参数说明:

参数类型参数说明
config*ConnectionConfig见上文建立连接相关内容
logger*NlsLogger见SDK日志相关内容
taskfailedfunc(string, interface{})识别过程中的错误处理回调,interface{}为用户自定义参数
startedfunc(string, interface{})建连完成回调
resultchangedfunc(string, interface{})识别中间结果回调
completedfunc(string, interface{})最终识别结果回调
closedfunc(interface{})连接断开回调
paraminterface{}用户自定义参数

返回值:

*SpeechRecognition:识别对象指针

error:错误异常

4. func (sr *SpeechRecognition) Start(param SpeechRecognitionStartParam, extra map[string]interface{}) (chan bool, error)

根据param发起一次一句话识别

参数说明:

参数类型参数说明
paramSpeechRecognitionStartParam一句话识别参数
extramap[string]interface{}额外key value参数

返回值:

chan bool:同步start完成的管道

error:错误异常

5. func (sr *SpeechRecognition) Stop() (chan bool, error)

停止一句话识别

参数说明:

返回值:

chan bool:同步stop完成的管道

error:错误异常

6. func (sr *SpeechRecognition) Shutdown()

强制断开连接

参数说明:

返回值:

7. func (sr *SpeechRecognition) SendAudioData(data []byte) error

发送音频,音频格式必须和参数中一致

参数说明

参数类型参数说明
data[]byte音频数据

返回值:

error:异常错误

一句话识别代码示例:

package main

import (
        "errors"
        "flag"
        "fmt"
        "log"
        "os"
        "os/signal"
        "sync"
        "time"

        "github.com/aliyun/alibabacloud-nls-go-sdk"
)

const (
  		AKID  = "Your AKID"
        AKKEY = "Your AKKEY"
        //online key
        APPKEY = "Your APPKEY"
        TOKEN  = "Your TOKEN"
)

func onTaskFailed(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("TaskFailed:", text)
}

func onStarted(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onStarted:", text)
}

func onResultChanged(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onResultChanged:", text)
}

func onCompleted(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onCompleted:", text)
}

func onClose(param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onClosed:")
}

func waitReady(ch chan bool, logger *nls.NlsLogger) error {
        select {
        case done := <-ch:
                {
                        if !done {
                                logger.Println("Wait failed")
                                return errors.New("wait failed")
                        }
                        logger.Println("Wait done")
                }
        case <-time.After(20 * time.Second):
                {
                        logger.Println("Wait timeout")
                        return errors.New("wait timeout")
                }
        }
        return nil
}

var lk sync.Mutex
var fail = 0
var reqNum = 0

func testMultiInstance(num int) {
        pcm, err := os.Open("tests/test1.pcm")
        if err != nil {
                log.Default().Fatalln(err)
        }

        buffers := nls.LoadPcmInChunk(pcm, 320)
        param := nls.DefaultSpeechRecognitionParam()
        //config := nls.NewConnectionConfigWithToken(PRE_URL_WSS,
        //        APPKEY, TOKEN)
    	config := nls.NewConnectionConfigWithAKInfoDefault(nls.DEFAULT_URL, APPKEY, AKID, AKKEY)
        var wg sync.WaitGroup
        for i := 0; i < num; i++ {
                wg.Add(1)
                go func(id int) {
                        defer wg.Done()
                        strId := fmt.Sprintf("ID%d   ", id)
                        logger := nls.NewNlsLogger(os.Stderr, strId, 			log.LstdFlags|log.Lmicroseconds)
                        logger.SetLogSil(false)
                        logger.SetDebug(true)
      logger.Printf("Test Normal Case for SpeechRecognition:%s", strId)
                        sr, err := nls.NewSpeechRecognition(config, logger,
                                onTaskFailed, onStarted, onResultChanged,
                                onCompleted, onClose, logger)
                        if err != nil {
                                logger.Fatalln(err)
                                return
                        }

      test_ex := make(map[string]interface{})
      test_ex["test"] = "hello"

                        for {
                                lk.Lock()
                                reqNum++
                                lk.Unlock()
                                logger.Println("SR start")
                                ready, err := sr.Start(param, test_ex)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        sr.Shutdown()
                                        continue
                                }

                                err = waitReady(ready, logger)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        sr.Shutdown()
                                        continue
                                }

                                for _, data := range buffers.Data {
                                        if data != nil {
                                                sr.SendAudioData(data.Data)
                                                time.Sleep(10 * time.Millisecond)
                                        }
                                }

                                logger.Println("send audio done")
                                ready, err = sr.Stop()
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        sr.Shutdown()
                                        continue
                                }

                                err = waitReady(ready, logger)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        sr.Shutdown()
                                        continue
                                }

                                logger.Println("Sr done")
                                sr.Shutdown()
                        }
                }(i)
        }

        wg.Wait()
}

func main() {
        coroutineId := flag.Int("num", 1, "coroutine number")
        flag.Parse()
        log.Default().Printf("start %d coroutines", *coroutineId)

        c := make(chan os.Signal, 1)
        signal.Notify(c, os.Interrupt)
        go func() {
                for range c {
                        lk.Lock()
                        log.Printf(">>>>>>>>REQ NUM: %d>>>>>>>>>FAIL: %d", reqNum, fail)
                        lk.Unlock()
                        os.Exit(0)
                }
        }()
        testMultiInstance(*coroutineId)
}

实时语音识别

1. SpeechTranscriptionStartParam

实时语音识别参数

参数说明:

参数类型参数说明
Formatstring音频格式,默认使用pcm
SampleRateint采样率,默认16000
EnableIntermediateResultbool是否打开中间结果返回
EnablePunctuationPreditionbool是否打开标点预测
EnableInverseTextNormalizationbool是否打开ITN
MaxSentenceSilenceint语音断句检测阈值,静音时长超过该阈值会被认为断句,合法参数范围200~2000(ms),默认值800m
enable_wordsbool是否开启返回词信息,可选,默认false不开启

2. func DefaultSpeechTranscriptionParam() SpeechTranscriptionStartParam

创建一个默认参数

参数说明:

返回值:

SpeechTranscriptionStartParam:默认参数

3. func NewSpeechTranscription(...) (*SpeechTranscription, error)

创建一个实时识别对象

参数说明:

参数类型参数说明
config*ConnectionConfig见上文建立连接相关内容
logger*NlsLogger见SDK日志相关内容
taskfailedfunc(string, interface{})识别过程中的错误处理回调,interface{}为用户自定义参数
startedfunc(string, interface{})建连完成回调
sentencebeginfunc(string, interface{})一句话开始
sentenceendfunc(string, interface{})一句话结束
resultchangedfunc(string, interface{})识别中间结果回调
completedfunc(string, interface{})最终识别结果回调
closedfunc(interface{})连接断开回调
paraminterface{}用户自定义参数

返回值:

*SpeechRecognition:识别对象指针

error:错误异常

4. func (st *SpeechTranscription) Start(param SpeechTranscriptionStartParam, extra map[string]interface{}) (chan bool, error)

开始实时识别

参数说明:

参数类型参数说明
paramSpeechTranscriptionStartParam实时识别参数
extramap[string]interface{}额外key value参数

返回值:

chan bool:同步start完成的管道

error:错误异常

5. func (st *SpeechTranscription) Stop() (chan bool, error)

停止实时识别

参数说明:

返回值:

chan bool:同步stop完成的管道

error:错误异常

6. func (st *SpeechTranscription) Ctrl(param map[string]interface{}) error

发送控制命令,先阅读实时语音识别接口说明

参数说明:

参数类型参数说明
parammap[string]interface{}自定义控制命令,该字典内容会以key:value形式合并进请求的payload段中

返回值:

error:错误异常

7. func (st *SpeechTranscription) Shutdown()

强制停止

参数说明:

返回值:

8. func (sr *SpeechTranscription) SendAudioData(data []byte) error

发送音频,音频格式必须和参数中一致

参数说明

参数类型参数说明
data[]byte音频数据

返回值:

error:异常错误

代码示例

package main

import (
        "errors"
        "flag"
        "fmt"
        "log"
        "os"
        "os/signal"
        "sync"
        "time"

         "github.com/aliyun/alibabacloud-nls-go-sdk"
)

const (
  		AKID  = "Your AKID"
        AKKEY = "Your AKKEY"
        //online key
        APPKEY = "Your APPKEY"
        TOKEN  = "Your TOKEN"
)

func onTaskFailed(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("TaskFailed:", text)
}

func onStarted(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onStarted:", text)
}

func onSentenceBegin(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onSentenceBegin:", text)
}

func onSentenceEnd(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onSentenceEnd:", text)
}

func onResultChanged(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onResultChanged:", text)
}

func onCompleted(text string, param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onCompleted:", text)
}

func onClose(param interface{}) {
        logger, ok := param.(*nls.NlsLogger)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        logger.Println("onClosed:")
}

func waitReady(ch chan bool, logger *nls.NlsLogger) error {
        select {
        case done := <-ch:
                {
                        if !done {
                                logger.Println("Wait failed")
                                return errors.New("wait failed")
                        }
                        logger.Println("Wait done")
                }
        case <-time.After(20 * time.Second):
                {
                        logger.Println("Wait timeout")
                        return errors.New("wait timeout")
                }
        }
        return nil
}

var lk sync.Mutex
var fail = 0
var reqNum = 0

func testMultiInstance(num int) {
        pcm, err := os.Open("tests/test1.pcm")
        if err != nil {
                log.Default().Fatalln(err)
        }

        buffers := nls.LoadPcmInChunk(pcm, 320)
        param := nls.DefaultSpeechTranscriptionParam()
        //config := nls.NewConnectionConfigWithToken(PRE_URL_WSS,
        //        APPKEY, TOKEN)
    	config := nls.NewConnectionConfigWithAKInfoDefault(nls.DEFAULT_URL, APPKEY, AKID, AKKEY)
        var wg sync.WaitGroup
        for i := 0; i < num; i++ {
                wg.Add(1)
                go func(id int) {
                        defer wg.Done()
                        strId := fmt.Sprintf("ID%d   ", id)
                        logger := nls.NewNlsLogger(os.Stderr, strId, log.LstdFlags|log.Lmicroseconds)
                        logger.SetLogSil(false)
                        logger.SetDebug(true)
                        logger.Printf("Test Normal Case for SpeechRecognition:%s", strId)
                        st, err := nls.NewSpeechTranscription(config, logger,
                                onTaskFailed, onStarted,
                                onSentenceBegin, onSentenceEnd, onResultChanged,
                                onCompleted, onClose, logger)
                        if err != nil {
                                logger.Fatalln(err)
                                return
                        }

                        test_ex := make(map[string]interface{})
                        test_ex["test"] = "hello"

                        for {
                                lk.Lock()
                                reqNum++
                                lk.Unlock()
                                logger.Println("ST start")
                                ready, err := st.Start(param, test_ex)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        st.Shutdown()
                                        continue
                                }

                                err = waitReady(ready, logger)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        st.Shutdown()
                                        continue
                                }

                                for _, data := range buffers.Data {
                                        if data != nil {
                                                st.SendAudioData(data.Data)
                                                time.Sleep(10 * time.Millisecond)
                                        }
                                }

                                logger.Println("send audio done")
                                ready, err = st.Stop()
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        st.Shutdown()
                                        continue
                                }

                                err = waitReady(ready, logger)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        st.Shutdown()
                                        continue
                                }

                                logger.Println("Sr done")
                                st.Shutdown()
                        }
                }(i)
        }

        wg.Wait()
}

func main() {
        coroutineId := flag.Int("num", 1, "coroutine number")
        flag.Parse()
        log.Default().Printf("start %d coroutines", *coroutineId)

        c := make(chan os.Signal, 1)
        signal.Notify(c, os.Interrupt)
        go func() {
                for range c {
                        lk.Lock()
                        log.Printf(">>>>>>>>REQ NUM: %d>>>>>>>>>FAIL: %d", reqNum, fail)
                        lk.Unlock()
                        os.Exit(0)
                }
        }()
        testMultiInstance(*coroutineId)
}

语音合成

1. SpeechSynthesisStartParam

参数说明:

参数类型参数说明
Voicestring发音人,默认“xiaoyun”
Formatstring音频格式,默认使用wav
SampleRateint采样率,默认16000
Volumeint音量,范围为0-100,默认50
SpeechRateint语速,范围为-500-500,默认为0
PitchRateint音高,范围为-500-500,默认为0
EnableSubtitlebool字幕功能,默认为false

2. func DefaultSpeechSynthesisParam() SpeechSynthesisStartParam

创建一个默认的语音合成参数

参数说明:

返回值:

SpeechSynthesisStartParam:语音合成参数

3. func NewSpeechSynthesis(...) (*SpeechSynthesis, error)

创建一个新的语音合成对象

参数说明:

参数类型参数说明
config*ConnectionConfig见上文建立连接相关内容
logger*NlsLogger见SDK日志相关内容
taskfailedfunc(string, interface{})识别过程中的错误处理回调,interface{}为用户自定义参数
synthesisresultfunc([]byte, interface{})语音合成数据回调
metainfofunc(string, interface{})字幕数据回调,需要参数中EnableSubtitle为true
completedfunc(string, interface{})合成完毕结果回调
closedfunc(interface{})连接断开回调
paraminterface{}用户自定义参数

返回值:

4. func (tts *SpeechSynthesis) Start(text string, param SpeechSynthesisStartParam, extra map[string]interface{}) (chan bool, error)

给定文本和参数进行语音合成

参数说明:

参数类型参数说明
textstring待合成文本
paramSpeechTranscriptionStartParam语音合成参数
extramap[string]interface{}额外key value参数

返回值:

chan bool:语音合成完成通知管道

error:错误异常

5. func (tts *SpeechSynthesis) Shutdown()

强制停止语音合成

参数说明:

返回值:

代码示例:

package main

import (
        "errors"
        "flag"
        "fmt"
        "io"
        "log"
        "os"
        "os/signal"
        "sync"
        "time"

         "github.com/aliyun/alibabacloud-nls-go-sdk"
)

const (
  		AKID  = "Your AKID"
        AKKEY = "Your AKKEY"
        //online key
        APPKEY = "Your APPKEY"
        TOKEN  = "Your TOKEN"
)

type TtsUserParam struct {
        F           io.Writer
        Logger      *nls.NlsLogger
}

func onTaskFailed(text string, param interface{}) {
        p, ok := param.(*TtsUserParam)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        p.Logger.Println("TaskFailed:", text)
}

func onSynthesisResult(data []byte, param interface{}) {
        p, ok := param.(*TtsUserParam)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }
        p.F.Write(data)
}

func onCompleted(text string, param interface{}) {
        p, ok := param.(*TtsUserParam)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        p.Logger.Println("onCompleted:", text)
}


func onClose(param interface{}) {
        p, ok := param.(*TtsUserParam)
        if !ok {
                log.Default().Fatal("invalid logger")
                return
        }

        p.Logger.Println("onClosed:")
}

func waitReady(ch chan bool, logger *nls.NlsLogger) error {
        select {
        case done := <-ch:
                {
                        if !done {
                                logger.Println("Wait failed")
                                return errors.New("wait failed")
                        }
                        logger.Println("Wait done")
                }
        case <-time.After(60 * time.Second):
                {
                        logger.Println("Wait timeout")
                        return errors.New("wait timeout")
                }
        }
        return nil
}

var lk sync.Mutex
var fail = 0
var reqNum = 0

const (
        TEXT = "你好小德,今天天气怎么样。"
)

func testMultiInstance(num int) {
        param := nls.DefaultSpeechSynthesisParam()
		//config := nls.NewConnectionConfigWithToken(PRE_URL_WSS,
        //        APPKEY, TOKEN)
    	config := nls.NewConnectionConfigWithAKInfoDefault(nls.DEFAULT_URL, APPKEY, AKID, AKKEY)
        var wg sync.WaitGroup
        for i := 0; i < num; i++ {
                wg.Add(1)
                go func(id int) {
                        defer wg.Done()
                        strId := fmt.Sprintf("ID%d   ", id)
                        fname := fmt.Sprintf("ttsdump%d.wav", id)
                        ttsUserParam := new(TtsUserParam)
                        fout, err := os.OpenFile(fname, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
                        logger := nls.NewNlsLogger(os.Stderr, strId, log.LstdFlags|log.Lmicroseconds)
                        logger.SetLogSil(false)
                        logger.SetDebug(true)
                        logger.Printf("Test Normal Case for SpeechRecognition:%s", strId)
                        ttsUserParam.F = fout
                        ttsUserParam.Logger = logger
      tts, err := nls.NewSpeechSynthesis(config, logger,
                                onTaskFailed, onSynthesisResult, nil,
                                onCompleted, onClose, ttsUserParam)
                        if err != nil {
                                logger.Fatalln(err)
                                return
                        }

                        for {
                                lk.Lock()
                                reqNum++
                                lk.Unlock()
                                logger.Println("SR start")
                                ch, err := tts.Start(TEXT, param, nil)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        tts.Shutdown()
                                        continue
                                }

                                err = waitReady(ch, logger)
                                if err != nil {
                                        lk.Lock()
                                        fail++
                                        lk.Unlock()
                                        tts.Shutdown()
                                        continue
                                }
                                logger.Println("Synthesis done")
                                tts.Shutdown()
                        }
                }(i)
        }

        wg.Wait()
}

func main() {
        coroutineId := flag.Int("num", 1, "coroutine number")
        flag.Parse()
        log.Default().Printf("start %d coroutines", *coroutineId)

        c := make(chan os.Signal, 1)
        signal.Notify(c, os.Interrupt)
        go func() {
                for range c {
                        lk.Lock()
                        log.Printf(">>>>>>>>REQ NUM: %d>>>>>>>>>FAIL: %d", reqNum, fail)
                        lk.Unlock()
                        os.Exit(0)
                }
        }()
        testMultiInstance(*coroutineId)
}

# Packages

No description provided by the author

# Functions

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Constants

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
token.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
AFORMAT.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
namespace field.
No description provided by the author
name field.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
namespace field.
No description provided by the author
No description provided by the author
No description provided by the author
name field.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
namespace field.
name field.
No description provided by the author

# Variables

No description provided by the author

# Structs

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author