# NLS Python SDK说明 本文介绍如何使用阿里云智能语音服务提供的Python SDK,包括SDK的安装方法及SDK代码示例。 > 说明 > > * 当前版本:0.0.1,支持python3 ## 安装 解压SDK压缩包后进入SDK根目录使用如下命令安装SDK依赖: > python -m pip install -r requirements.txt 依赖安装完成后使用如下命令安装SDK: > python -m pip install . > 注意: > > 上述命令需要在SDK根目录中执行 安装完成后通过以下代码可以导入SDK: > #!/bin/python > > import nls ## 多线程和多并发 根据Python官方文档: > **CPython implementation detail:** 在 CPython 中,由于存在 [全局解释器锁](https://docs.python.org/zh-cn/3/glossary.html#term-global-interpreter-lock),同一时刻只有一个线程可以执行 Python 代码(虽然某些性能导向的库可能会去除此限制)。 如果你想让你的应用更好地利用多核心计算机的计算资源,推荐你使用 [`multiprocessing`](https://docs.python.org/zh-cn/3/library/multiprocessing.html#module-multiprocessing) 或 [`concurrent.futures.ProcessPoolExecutor`](https://docs.python.org/zh-cn/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor)。 但是,如果你想要同时运行多个 I/O 密集型任务,则多线程仍然是一个合适的模型。 如果单解释器有太多线程,那么线程间切换的消耗会非常客观,有可能会导致SDK出现错误,不建议超过200线程的使用,如果有必要使用multiprocessing技术或者手动使用脚本创建多个解释器 ## 一句话识别 一句话识别对应的类为NlsSpeechRecognizer,其核心方法如下: ### 1. 初始化(\_\_init\_\_) 参数说明: | 参数 | 类型 | 参数说明 | | ----------------- | -------- | ------------------------------------------------------------ | | url | str | 网关websocket url,默认为wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1 | | akid | str | 账号access id,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | aksecret | str | 账号access secret key,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | token | str | 访问token,参考开发指南—获取Token及获取Token协议说明相关内容 | | on_start | function | 当一句话识别就绪时的回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_result_changed | function | 当一句话识别返回中间结果时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_completed | function | 当一句话识别返回最终识别结果时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_error | function | 当SDK或云端出现错误时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_close | function | 当和云端连接断开时回调,回调参数有一个——用户自定义参数,见后续callback_args参数说明 | | callback_args | list | 用户自定义参数列表,里面的内容会pack成list传递给各个回调的最后一个参数 | 返回值: 无 ### 2. start > 同步开始一句话识别,该方法会阻塞当前线程直到一句话识别就绪(on_start回调返回) 参数说明: | 参数 | 类型 | 参数说明 | | --------------------------------- | ---- | ------------------------------------------------------------ | | aformat | str | 要识别音频格式,支持pcm,opus,opu,默认pcm,**SDK不会自动将pcm编码成opus或opu,如果需要使用opus或opu,需要用户自行编码** | | sample_rate | int | 识别音频采样率,默认16000 | | ch | int | 音频通道数,默认为1,不需要提供 | | enable_intermediate_result | bool | 是否返回中间结果,默认False | | enable_punctuation_prediction | bool | 是否进行识别结果标点预测,默认False | | enable_inverse_text_normalization | bool | 是否进行ITN,默认False | | timeout | int | 阻塞超时,默认10秒 | | ping_interval | int | ping包发送间隔,默认8,不需要可以设置为0或None | | ping_timeout | int | 是否检查pong包超时,默认为None,None为不检查pong包超时 | | ex | dict | 用户提供的额外参数,该字典内容会以key:value形式合并进请求的payload段中,具体可用参数见一句话语音识别接口说明 | 返回值: bool类型,False为失败,True为成功 ### 3. stop > 停止一句话识别,并同步等待on_completed回调结束 参数说明: | 参数 | 类型 | 参数说明 | | ------- | ---- | ------------------ | | timeout | int | 阻塞超时,默认10秒 | 返回值: bool类型,False为失败,True为成功 ### 4. shutdown > 强行关闭当前请求,重复调用无副作用 参数说明: 无 返回值: 无 ### 5. send_audio > 发送二进制音频数据,发送数据的格式需要和start中的aformat对应 参数说明: | 参数 | 类型 | 参数说明 | | -------- | ----- | ------------------------------------------------------------ | | pcm_data | bytes | 要发送的二进制音频数据,格式需要和上一次start中的aformat相对应。**SDK不会自动将pcm编码成opus或opu,如果需要使用opus或opu,需要用户自行编码** | 返回值: bool类型,False为失败,True为成功 ### 代码示例: ```python import time import threading import sys import nls URL="wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1" AKID="Your AKID" AKKEY="Your AKSECRET" APPKEY="Your APPKEY" #以下代码会根据音频文件内容反复进行一句话识别 class TestSr: def __init__(self, tid, test_file): self.__th = threading.Thread(target=self.__test_run) self.__id = tid self.__test_file = test_file def loadfile(self, filename): with open(filename, "rb") as f: self.__data = f.read() def start(self): self.loadfile(self.__test_file) self.__th.start() def test_on_start(self, message, *args): print("test_on_start:{}".format(message)) def test_on_error(self, message, *args): print("on_error args=>{}".format(args)) def test_on_close(self, *args): print("on_close: args=>{}".format(args)) def test_on_result_chg(self, message, *args): print("test_on_chg:{}".format(message)) def test_on_completed(self, message, *args): print("on_completed:args=>{} message=>{}".format(args, message)) def __test_run(self): print("thread:{} start..".format(self.__id)) sr = nls.NlsSpeechRecognizer( url=URL, akid=AKID, aksecret=AKKEY, appkey=APPKEY, on_start=self.test_on_start, on_result_changed=self.test_on_result_chg, on_completed=self.test_on_completed, on_error=self.test_on_error, on_close=self.test_on_close, callback_args=[self.__id] ) while True: print("{}: session start".format(self.__id)) r = sr.start(aformat="pcm", ex={"hello":123}) self.__slices = zip(*(iter(self.__data),) * 640) for i in self.__slices: sr.send_audio(bytes(i)) time.sleep(0.01) r = sr.stop() print("{}: sr stopped:{}".format(self.__id, r)) time.sleep(1) def multiruntest(num=500): for i in range(0, num): name = "thread" + str(i) t = TestSr(name, "tests/test1.pcm") t.start() nls.enableTrace(True) multiruntest(1) ``` ## 实时语音识别 实时语音识别对应的类为NlsSpeechTranscriber,其核心方法如下: ### 1. 初始化(\_\_init\_\_) 参数说明: | 参数 | 类型 | 参数说明 | | ----------------- | -------- | ------------------------------------------------------------ | | url | str | 网关websocket url,默认为wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1 | | akid | str | 账号access id,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | aksecret | str | 账号access secret key,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | token | str | 访问token,参考开发指南—获取Token及获取Token协议说明相关内容 | | on_start | function | 当实时识别就绪时的回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_sentence_begin | function | 当实时识别一句话开始时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_sentence_end | function | 当实时识别一句话结束时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_result_changed | function | 当实时识别返回中间结果时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_completed | function | 当实时识别返回最终识别结果时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_error | function | 当SDK或云端出现错误时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_close | function | 当和云端连接断开时回调,回调参数有一个——用户自定义参数,见后续callback_args参数说明 | | callback_args | list | 用户自定义参数列表,里面的内容会pack成list传递给各个回调的最后一个参数 | 返回值: 无 ### 2. start > 同步开始实时识别,该方法会阻塞当前线程直到实时识别就绪(on_start回调返回) 参数说明: | 参数 | 类型 | 参数说明 | | --------------------------------- | ---- | ------------------------------------------------------------ | | aformat | str | 要识别音频格式,支持pcm,opus,opu,默认pcm,**SDK不会自动将pcm编码成opus或opu,如果需要使用opus或opu,需要用户自行编码** | | sample_rate | int | 识别音频采样率,默认16000 | | ch | int | 音频通道数,默认为1,不需要提供 | | enable_intermediate_result | bool | 是否返回中间结果,默认False | | enable_punctuation_prediction | bool | 是否进行识别结果标点预测,默认False | | enable_inverse_text_normalization | bool | 是否进行ITN,默认False | | timeout | int | 阻塞超时,默认10秒 | | ping_interval | int | ping包发送间隔,默认8,不需要可以设置为0或None | | ping_timeout | int | 是否检查pong包超时,默认为None,None为不检查pong包超时 | | ex | dict | 用户提供的额外参数,该字典内容会以key:value形式合并进请求的payload段中,具体可用参数见实时语音识别接口说明 | 返回值: bool类型,False为失败,True为成功 ### 3. stop > 停止实时识别,并同步等待on_completed回调结束 参数说明: | 参数 | 类型 | 参数说明 | | ------- | ---- | ------------------ | | timeout | int | 阻塞超时,默认10秒 | 返回值: bool类型,False为失败,True为成功 ### 4. shutdown > 强行关闭当前请求,重复调用无副作用 参数说明: 无 返回值: 无 ### 5. send_audio > 发送二进制音频数据,发送数据的格式需要和start中的aformat对应 参数说明: | 参数 | 类型 | 参数说明 | | -------- | ----- | ------------------------------------------------------------ | | pcm_data | bytes | 要发送的二进制音频数据,格式需要和上一次start中的aformat相对应。**SDK不会自动将pcm编码成opus或opu,如果需要使用opus或opu,需要用户自行编码** | 返回值: bool类型,False为失败,True为成功 ### 6. ctrl > 发送控制命令,先阅读实时语音识别接口说明 参数说明: | 参数 | 类型 | 参数说明 | | ---- | ---- | ------------------------------------------------------------ | | ex | dict | 自定义控制命令,该字典内容会以key:value形式合并进请求的payload段中 | 返回值: bool类型,False为失败,True为成功 ### 代码示例 ```python import time import threading import sys import nls URL="wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1" AKID="Your AKID" AKKEY="Your AKSECRET" APPKEY="Your APPKEY" #以下代码会根据音频文件内容反复进行实时识别(文件转写) class TestSt: def __init__(self, tid, test_file): self.__th = threading.Thread(target=self.__test_run) self.__id = tid self.__test_file = test_file def loadfile(self, filename): with open(filename, "rb") as f: self.__data = f.read() def start(self): self.loadfile(self.__test_file) self.__th.start() def test_on_sentence_begin(self, message, *args): print("test_on_sentence_begin:{}".format(message)) def test_on_sentence_end(self, message, *args): print("test_on_sentence_end:{}".format(message)) def test_on_start(self, message, *args): print("test_on_start:{}".format(message)) def test_on_error(self, message, *args): print("on_error args=>{}".format(args)) def test_on_close(self, *args): print("on_close: args=>{}".format(args)) def test_on_result_chg(self, message, *args): print("test_on_chg:{}".format(message)) def test_on_completed(self, message, *args): print("on_completed:args=>{} message=>{}".format(args, message)) def __test_run(self): print("thread:{} start..".format(self.__id)) sr = nls.NlsSpeechTranscriber( url=URL, akid=AKID, aksecret=AKKEY, appkey=APPKEY, on_sentence_begin=self.test_on_sentence_begin, on_sentence_end=self.test_on_sentence_end, on_start=self.test_on_start, on_result_changed=self.test_on_result_chg, on_completed=self.test_on_completed, on_error=self.test_on_error, on_close=self.test_on_close, callback_args=[self.__id] ) while True: print("{}: session start".format(self.__id)) r = sr.start(aformat="pcm", enable_intermediate_result=True, enable_punctuation_prediction=True, enable_inverse_text_normalization=True) self.__slices = zip(*(iter(self.__data),) * 640) for i in self.__slices: sr.send_audio(bytes(i)) time.sleep(0.01) sr.ctrl(ex={"test":"tttt"}) time.sleep(1) r = sr.stop() print("{}: sr stopped:{}".format(self.__id, r)) time.sleep(1) def multiruntest(num=500): for i in range(0, num): name = "thread" + str(i) t = TestSt(name, "tests/test1.pcm") t.start() nls.enableTrace(True) multiruntest(1) ``` ## 语音合成 语音合成对应的类为NlsSpeechSynthesizer,其核心方法如下: ### 1. 初始化(\_\_init\_\_) 参数说明: | 参数 | 类型 | 参数说明 | | ------------- | -------- | ------------------------------------------------------------ | | url | str | 网关websocket url,默认为wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1 | | akid | str | 账号access id,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | aksecret | str | 账号access secret key,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | token | str | 访问token,参考开发指南—获取Token及获取Token协议说明相关内容 | | on_metainfo | function | 如果start中通过ex参数传递enable_subtitle,则会返回对应字幕信息,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_data | function | 当存在合成数据后回调,回调参数有两个,一个是对应start方法aformat的二进制音频数据,一个是用户自定义参数,见后续callback_args参数说明 | | on_completed | function | 当合成完毕时候回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_error | function | 当SDK或云端出现错误时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_close | function | 当和云端连接断开时回调,回调参数有一个——用户自定义参数,见后续callback_args参数说明 | | callback_args | list | 用户自定义参数列表,里面的内容会pack成list传递给各个回调的最后一个参数 | 返回值: 无 ### 2. start > 同步开始语音合成,如果wait_complete为True(默认)则会阻塞直到所有音频合成完毕(on_completed返回之后)返回,否则会立即返回 参数说明: | 参数 | 类型 | 参数说明 | | ----------------- | ---- | ------------------------------------------------------------ | | text | str | 要合成的文字 | | aformat | str | 合成出来音频的格式,默认为"pcm" | | voice | str | 发音人,默认为”xiaoyun“ | | sample_rate | int | 识别音频采样率,默认16000 | | volume | int | 音量大小,0~100,默认为50 | | speech_rate | int | 语速,-500~500,默认为0 | | pitch_rate | int | 语调,-500~500,默认为0 | | wait_complete | bool | 是否阻塞到合成完成 | | start_timeout | int | 和云端连接建立超时,默认10秒 | | completed_timeout | int | 从连接建立到合成完成超时,默认60秒 | | ping_interval | int | ping包发送间隔,默认8,不需要可以设置为0或None | | ping_timeout | int | 是否检查pong包超时,默认为None,None为不检查pong包超时 | | ex | dict | 用户提供的额外参数,该字典内容会以key:value形式合并进请求的payload段中,具体可用参数见实时语音识别接口说明 | 返回值: bool类型,False为失败,True为成功 ### 3. shutdown > 强行关闭当前请求,重复调用无副作用 参数说明: 无 返回值: 无 ### 代码示例: ```python import time import threading import sys import nls URL="wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1" AKID="Your AKID" AKKEY="Your AKSECRET" APPKEY="Your APPKEY" TEXT='大壮正想去摘取花瓣,谁知阿丽和阿强突然内讧,阿丽拿去手枪向树干边的阿强射击,两声枪响,阿强直接倒入水中' #以下代码会根据上述TEXT文本反复进行语音合成 class TestTts: def __init__(self, tid, test_file): self.__th = threading.Thread(target=self.__test_run) self.__id = tid self.__test_file = test_file def start(self, text): self.__text = text self.__f = open(self.__test_file, "wb") self.__th.start() def test_on_metainfo(self, message, *args): print("on_metainfo message=>{}".format(message)) def test_on_error(self, message, *args): print("on_error args=>{}".format(args)) def test_on_close(self, *args): print("on_close: args=>{}".format(args)) try: self.__f.close() except Exception as e: print("close file failed since:", e) def test_on_data(self, data, *args): try: self.__f.write(data) except Exception as e: print("write data failed:", e) def test_on_completed(self, message, *args): print("on_completed:args=>{} message=>{}".format(args, message)) def __test_run(self): print("thread:{} start..".format(self.__id)) tts = nls.NlsSpeechSynthesizer( url=URL, akid=AKID, aksecret=AKKEY, appkey=APPKEY, on_metainfo=self.test_on_metainfo, on_data=self.test_on_data, on_completed=self.test_on_completed, on_error=self.test_on_error, on_close=self.test_on_close, callback_args=[self.__id] ) while True: print("{}: session start".format(self.__id)) r = tts.start(self.__text, voice="ailun") print("{}: tts done with result:{}".format(self.__id, r)) time.sleep(1) def multiruntest(num=500): for i in range(0, num): name = "thread" + str(i) t = TestTts(name, "tests/test_tts.pcm") t.start(TEXT) nls.enableTrace(True) multiruntest(1) ``` ## 高级用法——使用CommonProto实现任意接口 nls包下面的NlsCommonProto对象可以用来实现智能语音交互的任意接口,其核心方法如下: ### 1. 初始化(\_\_init\_\_) 参数说明: | 参数 | 类型 | 参数说明 | | ------------- | -------- | ------------------------------------------------------------ | | url | str | 网关websocket url,默认为wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1 | | akid | str | 账号access id,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | aksecret | str | 账号access secret key,默认为None,如果需要获取token,则需要提供,如果已有token,则不需要提供 | | token | str | 访问token,参考开发指南—获取Token及获取Token协议说明相关内容 | | on_open | function | 当和云端建连完成后回调,回调参数有一个——用户自定义参数,见后续callback_args参数说明 | | on_error | function | 当SDK或云端出现错误时回调,回调参数有两个,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | on_close | function | 当和云端连接断开时回调,回调参数有一个——用户自定义参数,见后续callback_args参数说明 | | on_data | function | 当云端返回二进制数据时回调,回调参数有两个,一个是二进制数据,一个是用户自定义参数,见后续callback_args参数说明 | | user_callback | dict | 用户自定义回调字典,key为str类型,value为function类型,当SDK收到云端应答后,会根据应答内部header字段下面name字段来索引该字典,如果对应item存在则会回调对应function。该回调包括两个参数,一个是json形式的字符串,一个是用户自定义参数,见后续callback_args参数说明 | | callback_args | list | 用户自定义参数列表,里面的内容会pack成list传递给各个回调的最后一个参数 | 返回值: 无 ### 2. start > **异步**和云端建连并发起一次请求 参数说明: | 参数 | 类型 | 参数说明 | | ------- | ---- | ---------------------------------------- | | name | str | 对应header字段中的name,用于指明请求类型 | | payload | dict | 请求中的payload,默认为{} | | context | dict | 请求中的context,默认为{} | | ping_interval | int | ping包发送间隔,默认8,不需要可以设置为0或None | | ping_timeout | int | 是否检查pong包超时,默认为None,None为不检查pong包超时 | 返回值: bool类型,False为失败,True为成功 ### 3. shutdown > 强行关闭当前请求,重复调用无副作用 参数说明: 无 返回值: 无 ### 4. send_text > 发送文本请求 参数说明: | 参数 | 类型 | 参数说明 | | ------- | ---- | ---------------------------------------- | | name | str | 对应header字段中的name,用于指明请求类型 | | payload | dict | 请求中的payload,默认为{} | | context | dict | 请求中的context,默认为{} | 返回值: bool类型,False为失败,True为成功 ### 5. send_binary > 发送二进制数据 参数说明: | 参数 | 类型 | 参数说明 | | -------- | ----- | ------------------ | | pcm_data | bytes | 要发送的二进频数据 | 返回值: bool类型,False为失败,True为成功 ### 示例代码: ```python import time import threading import sys import nls URL="wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1" AKID="Your AKID" AKKEY="Your AKSECRET" APPKEY="Your APPKEY" #以下代码会通过文件反复进行一句话识别 class TestSrCommon: def __init__(self, tid, test_file): self.__th = threading.Thread(target=self.__test_run) self.__id = tid self.__test_file = test_file def loadfile(self, filename): with open(filename, "rb") as f: self.__data = f.read() def start(self): self.loadfile(self.__test_file) self.__th.start() def test_on_open(self, *args): print("test_on_start") def test_on_start(self, message, *args): print("test_on_start:{}".format(message)) def test_on_data(self, data, *args): pass def test_on_error(self, message, *args): print("on_error args=>{}".format(args)) def test_on_close(self, *args): print("on_close: args=>{}".format(args)) def test_on_result_chg(self, message, *args): print("test_on_chg:{}".format(message)) def test_on_completed(self, message, *args): print("on_completed:args=>{} message=>{}".format(args, message)) self.__sr.shutdown() def __test_run(self): print("thread:{} start..".format(self.__id)) callbacks = { "RecognitionStarted":self.test_on_start, "RecognitionResultChanged":self.test_on_result_chg, "RecognitionCompleted":self.test_on_completed } self.__sr = nls.NlsCommonProto( url=URL, akid=AKID, aksecret=AKKEY, appkey=APPKEY, namespace="SpeechRecognizer", on_open=self.test_on_open, on_data=self.test_on_data, on_error=self.test_on_error, on_close=self.test_on_close, user_callback=callbacks, callback_args=[self.__id] ) while True: print("{}: session start".format(self.__id)) r = self.__sr.start(name="StartRecognition", payload={ "format":"pcm", "sample_rate":16000 } ) if not r: print("start failed") break time.sleep(1) self.__slices = zip(*(iter(self.__data),) * 640) for i in self.__slices: self.__sr.send_binary(bytes(i)) time.sleep(0.01) self.__sr.send_text(name="StopRecognition") time.sleep(1) def multiruntest(num=500): for i in range(0, num): name = "thread" + str(i) t = TestSrCommon(name, "tests/test1.pcm") t.start() nls.enableTrace(True) multiruntest(1) ```