You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

771 lines
31 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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 | 要识别音频格式支持pcmopusopu默认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包超时默认为NoneNone为不检查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 | 要识别音频格式支持pcmopusopu默认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包超时默认为NoneNone为不检查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包超时默认为NoneNone为不检查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包超时默认为NoneNone为不检查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)
```