smartpi 1.1.2__py3-none-any.whl → 1.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smartpi/__init__.pyc +0 -0
- smartpi/_gui.pyc +0 -0
- smartpi/ai_asr.pyc +0 -0
- smartpi/ai_llm.pyc +0 -0
- smartpi/ai_tts.pyc +0 -0
- smartpi/ai_vad.pyc +0 -0
- smartpi/audio.pyc +0 -0
- smartpi/base_driver.pyc +0 -0
- smartpi/camera.pyc +0 -0
- smartpi/color_sensor.pyc +0 -0
- smartpi/cw2015.pyc +0 -0
- smartpi/flash.pyc +0 -0
- smartpi/humidity.pyc +0 -0
- smartpi/led.pyc +0 -0
- smartpi/light_sensor.pyc +0 -0
- smartpi/local_model.pyc +0 -0
- smartpi/mcp_client.pyc +0 -0
- smartpi/mcp_fastmcp.pyc +0 -0
- smartpi/mcp_intent_recognizer.pyc +0 -0
- smartpi/models/__init__.pyc +0 -0
- smartpi/models/snakers4_silero-vad/__init__.pyc +0 -0
- smartpi/models/snakers4_silero-vad/hubconf.pyc +0 -0
- smartpi/motor.pyc +0 -0
- smartpi/move.pyc +0 -0
- smartpi/onnx_hand_workflow.pyc +0 -0
- smartpi/onnx_image_workflow.pyc +0 -0
- smartpi/onnx_pose_workflow.pyc +0 -0
- smartpi/onnx_text_workflow.pyc +0 -0
- smartpi/onnx_voice_workflow.pyc +0 -0
- smartpi/posemodel/__init__.pyc +0 -0
- smartpi/posenet_utils.pyc +0 -0
- smartpi/rknn_hand_workflow.pyc +0 -0
- smartpi/rknn_image_workflow.pyc +0 -0
- smartpi/rknn_pose_workflow.pyc +0 -0
- smartpi/rknn_text_workflow.pyc +0 -0
- smartpi/rknn_voice_workflow.pyc +0 -0
- smartpi/servo.pyc +0 -0
- smartpi/temperature.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/flash_recognizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/speech_recognizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/credential.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/log.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/common/utils.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/soe/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/soe/speaking_assessment.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/flowing_speech_synthesizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer_ws.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/vc/__init__.pyc +0 -0
- smartpi/tencentcloud-speech-sdk-python/vc/speech_convertor_ws.pyc +0 -0
- smartpi/text_gte_model/__init__.pyc +0 -0
- smartpi/text_gte_model/config/__init__.pyc +0 -0
- smartpi/text_gte_model/gte/__init__.pyc +0 -0
- smartpi/touch_sensor.pyc +0 -0
- smartpi/trace.pyc +0 -0
- smartpi/ultrasonic.pyc +0 -0
- {smartpi-1.1.2.dist-info → smartpi-1.1.4.dist-info}/METADATA +1 -1
- smartpi-1.1.4.dist-info/RECORD +77 -0
- smartpi/__init__.py +0 -8
- smartpi/_gui.py +0 -66
- smartpi/ai_asr.py +0 -1037
- smartpi/ai_llm.py +0 -934
- smartpi/ai_tts.py +0 -938
- smartpi/ai_vad.py +0 -83
- smartpi/audio.py +0 -125
- smartpi/base_driver.py +0 -618
- smartpi/camera.py +0 -84
- smartpi/color_sensor.py +0 -18
- smartpi/cw2015.py +0 -179
- smartpi/flash.py +0 -130
- smartpi/humidity.py +0 -20
- smartpi/led.py +0 -19
- smartpi/light_sensor.py +0 -72
- smartpi/local_model.py +0 -432
- smartpi/mcp_client.py +0 -100
- smartpi/mcp_fastmcp.py +0 -322
- smartpi/mcp_intent_recognizer.py +0 -408
- smartpi/models/__init__.py +0 -0
- smartpi/models/snakers4_silero-vad/__init__.py +0 -0
- smartpi/models/snakers4_silero-vad/hubconf.py +0 -56
- smartpi/motor.py +0 -177
- smartpi/move.py +0 -218
- smartpi/onnx_hand_workflow.py +0 -201
- smartpi/onnx_image_workflow.py +0 -176
- smartpi/onnx_pose_workflow.py +0 -482
- smartpi/onnx_text_workflow.py +0 -173
- smartpi/onnx_voice_workflow.py +0 -437
- smartpi/posemodel/__init__.py +0 -0
- smartpi/posenet_utils.py +0 -222
- smartpi/rknn_hand_workflow.py +0 -245
- smartpi/rknn_image_workflow.py +0 -405
- smartpi/rknn_pose_workflow.py +0 -592
- smartpi/rknn_text_workflow.py +0 -240
- smartpi/rknn_voice_workflow.py +0 -394
- smartpi/servo.py +0 -178
- smartpi/temperature.py +0 -18
- smartpi/tencentcloud-speech-sdk-python/__init__.py +0 -1
- smartpi/tencentcloud-speech-sdk-python/asr/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/asr/flash_recognizer.py +0 -178
- smartpi/tencentcloud-speech-sdk-python/asr/speech_recognizer.py +0 -311
- smartpi/tencentcloud-speech-sdk-python/common/__init__.py +0 -1
- smartpi/tencentcloud-speech-sdk-python/common/credential.py +0 -6
- smartpi/tencentcloud-speech-sdk-python/common/log.py +0 -16
- smartpi/tencentcloud-speech-sdk-python/common/utils.py +0 -7
- smartpi/tencentcloud-speech-sdk-python/soe/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/soe/speaking_assessment.py +0 -276
- smartpi/tencentcloud-speech-sdk-python/tts/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/tts/flowing_speech_synthesizer.py +0 -294
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer.py +0 -144
- smartpi/tencentcloud-speech-sdk-python/tts/speech_synthesizer_ws.py +0 -234
- smartpi/tencentcloud-speech-sdk-python/vc/__init__.py +0 -0
- smartpi/tencentcloud-speech-sdk-python/vc/speech_convertor_ws.py +0 -237
- smartpi/text_gte_model/__init__.py +0 -0
- smartpi/text_gte_model/config/__init__.py +0 -0
- smartpi/text_gte_model/gte/__init__.py +0 -0
- smartpi/touch_sensor.py +0 -16
- smartpi/trace.py +0 -120
- smartpi/ultrasonic.py +0 -20
- smartpi-1.1.2.dist-info/RECORD +0 -77
- {smartpi-1.1.2.dist-info → smartpi-1.1.4.dist-info}/WHEEL +0 -0
- {smartpi-1.1.2.dist-info → smartpi-1.1.4.dist-info}/top_level.txt +0 -0
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import sys
|
|
3
|
-
import hmac
|
|
4
|
-
import hashlib
|
|
5
|
-
import base64
|
|
6
|
-
import time
|
|
7
|
-
import json
|
|
8
|
-
import uuid
|
|
9
|
-
import requests
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def is_python3():
|
|
13
|
-
if sys.version > '3':
|
|
14
|
-
return True
|
|
15
|
-
return False
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
_PROTOCOL = "https://"
|
|
19
|
-
_HOST = "tts.cloud.tencent.com"
|
|
20
|
-
_PATH = "/stream"
|
|
21
|
-
_ACTION = "TextToStreamAudio"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class SpeechSynthesisListener:
|
|
25
|
-
'''
|
|
26
|
-
reponse:
|
|
27
|
-
所有回调均包含session_id字段
|
|
28
|
-
on_message与on_message包含data字段
|
|
29
|
-
on_fail包含Code、Message字段。
|
|
30
|
-
|
|
31
|
-
字段名 类型 说明
|
|
32
|
-
session_id String 本次请求id
|
|
33
|
-
data String 语音数据
|
|
34
|
-
Code String 错误码
|
|
35
|
-
Message String 错误信息
|
|
36
|
-
'''
|
|
37
|
-
|
|
38
|
-
def on_message(self, response):
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
def on_complete(self, response):
|
|
42
|
-
pass
|
|
43
|
-
|
|
44
|
-
def on_fail(self, response):
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class SpeechSynthesizer:
|
|
49
|
-
|
|
50
|
-
def __init__(self, appid, credential, voice_type, listener):
|
|
51
|
-
self.appid = appid
|
|
52
|
-
self.credential = credential
|
|
53
|
-
self.voice_type = voice_type
|
|
54
|
-
self.codec = "pcm"
|
|
55
|
-
self.sample_rate = 16000
|
|
56
|
-
self.volume = 0
|
|
57
|
-
self.speed = 0
|
|
58
|
-
self.listener = listener
|
|
59
|
-
|
|
60
|
-
def set_voice_type(self, voice_type):
|
|
61
|
-
self.voice_type = voice_type
|
|
62
|
-
|
|
63
|
-
def set_codec(self, codec):
|
|
64
|
-
self.codec = codec
|
|
65
|
-
|
|
66
|
-
def set_sample_rate(self, sample_rate):
|
|
67
|
-
self.sample_rate = sample_rate
|
|
68
|
-
|
|
69
|
-
def set_speed(self, speed):
|
|
70
|
-
self.speed = speed
|
|
71
|
-
|
|
72
|
-
def set_volume(self, volume):
|
|
73
|
-
self.volume = volume
|
|
74
|
-
|
|
75
|
-
def synthesis(self, text):
|
|
76
|
-
session_id = str(uuid.uuid1())
|
|
77
|
-
params = self.__gen_params(session_id, text)
|
|
78
|
-
signature = self.__gen_signature(params)
|
|
79
|
-
headers = {
|
|
80
|
-
"Content-Type": "application/json",
|
|
81
|
-
"Authorization": str(signature)
|
|
82
|
-
}
|
|
83
|
-
url = _PROTOCOL + _HOST + _PATH
|
|
84
|
-
r = requests.post(url, headers=headers,
|
|
85
|
-
data=json.dumps(params), stream=True)
|
|
86
|
-
data = None
|
|
87
|
-
response = dict()
|
|
88
|
-
response["session_id"] = session_id
|
|
89
|
-
for chunk in r.iter_content(None):
|
|
90
|
-
if data is None:
|
|
91
|
-
try:
|
|
92
|
-
rsp = json.loads(chunk)
|
|
93
|
-
response["Code"] = rsp["Response"]["Error"]["Code"]
|
|
94
|
-
response["Message"] = rsp["Response"]["Error"]["Message"]
|
|
95
|
-
self.listener.on_fail(response)
|
|
96
|
-
return
|
|
97
|
-
except:
|
|
98
|
-
data = chunk
|
|
99
|
-
response["data"] = data
|
|
100
|
-
self.listener.on_message(response)
|
|
101
|
-
continue
|
|
102
|
-
data = data + chunk
|
|
103
|
-
response["data"] = data
|
|
104
|
-
self.listener.on_message(response)
|
|
105
|
-
response["data"] = data
|
|
106
|
-
self.listener.on_complete(response)
|
|
107
|
-
|
|
108
|
-
def __gen_signature(self, params):
|
|
109
|
-
sort_dict = sorted(params.keys())
|
|
110
|
-
sign_str = "POST" + _HOST + _PATH + "?"
|
|
111
|
-
for key in sort_dict:
|
|
112
|
-
sign_str = sign_str + key + "=" + str(params[key]) + '&'
|
|
113
|
-
sign_str = sign_str[:-1]
|
|
114
|
-
hmacstr = hmac.new(self.credential.secret_key.encode('utf-8'),
|
|
115
|
-
sign_str.encode('utf-8'), hashlib.sha1).digest()
|
|
116
|
-
s = base64.b64encode(hmacstr)
|
|
117
|
-
s = s.decode('utf-8')
|
|
118
|
-
return s
|
|
119
|
-
|
|
120
|
-
def __sign(self, signstr, secret_key):
|
|
121
|
-
hmacstr = hmac.new(secret_key.encode('utf-8'),
|
|
122
|
-
signstr.encode('utf-8'), hashlib.sha1).digest()
|
|
123
|
-
s = base64.b64encode(hmacstr)
|
|
124
|
-
s = s.decode('utf-8')
|
|
125
|
-
return s
|
|
126
|
-
|
|
127
|
-
def __gen_params(self, session_id, text):
|
|
128
|
-
params = dict()
|
|
129
|
-
params['Action'] = _ACTION
|
|
130
|
-
params['AppId'] = int(self.appid)
|
|
131
|
-
params['SecretId'] = self.credential.secret_id
|
|
132
|
-
params['ModelType'] = 1
|
|
133
|
-
params['VoiceType'] = self.voice_type
|
|
134
|
-
params['Codec'] = self.codec
|
|
135
|
-
params['SampleRate'] = self.sample_rate
|
|
136
|
-
params['Speed'] = self.speed
|
|
137
|
-
params['Volume'] = self.volume
|
|
138
|
-
params['SessionId'] = session_id
|
|
139
|
-
params['Text'] = text
|
|
140
|
-
|
|
141
|
-
timestamp = int(time.time())
|
|
142
|
-
params['Timestamp'] = timestamp
|
|
143
|
-
params['Expired'] = timestamp + 24 * 60 * 60
|
|
144
|
-
return params
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import sys
|
|
3
|
-
import hmac
|
|
4
|
-
import hashlib
|
|
5
|
-
import base64
|
|
6
|
-
import time
|
|
7
|
-
import json
|
|
8
|
-
import threading
|
|
9
|
-
from websocket import ABNF, WebSocketApp
|
|
10
|
-
import uuid
|
|
11
|
-
import urllib
|
|
12
|
-
from common.log import logger
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_PROTOCOL = "wss://"
|
|
16
|
-
_HOST = "tts.cloud.tencent.com"
|
|
17
|
-
_PATH = "/stream_ws"
|
|
18
|
-
_ACTION = "TextToStreamAudioWS"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class SpeechSynthesisListener(object):
|
|
22
|
-
'''
|
|
23
|
-
'''
|
|
24
|
-
def on_synthesis_start(self, session_id):
|
|
25
|
-
logger.info("on_synthesis_start: session_id={}".format(session_id))
|
|
26
|
-
|
|
27
|
-
def on_synthesis_end(self):
|
|
28
|
-
logger.info("on_synthesis_end: -")
|
|
29
|
-
|
|
30
|
-
def on_audio_result(self, audio_bytes):
|
|
31
|
-
logger.info("on_audio_result: recv audio bytes, len={}".format(len(audio_bytes)))
|
|
32
|
-
|
|
33
|
-
def on_text_result(self, response):
|
|
34
|
-
session_id = response["session_id"]
|
|
35
|
-
request_id = response["request_id"]
|
|
36
|
-
message_id = response["message_id"]
|
|
37
|
-
result = response['result']
|
|
38
|
-
subtitles = []
|
|
39
|
-
if "subtitles" in result and len(result["subtitles"]) > 0:
|
|
40
|
-
subtitles = result["subtitles"]
|
|
41
|
-
logger.info("on_text_result: session_id={} request_id={} message_id={}\nsubtitles={}".format(
|
|
42
|
-
session_id, request_id, message_id, subtitles))
|
|
43
|
-
|
|
44
|
-
def on_synthesis_fail(self, response):
|
|
45
|
-
logger.error("on_synthesis_fail: code={} msg={}".format(
|
|
46
|
-
response['code'], response['message']
|
|
47
|
-
))
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
NOTOPEN = 0
|
|
51
|
-
STARTED = 1
|
|
52
|
-
OPENED = 2
|
|
53
|
-
FINAL = 3
|
|
54
|
-
ERROR = 4
|
|
55
|
-
CLOSED = 5
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class SpeechSynthesizer:
|
|
59
|
-
|
|
60
|
-
def __init__(self, appid, credential, listener):
|
|
61
|
-
self.appid = appid
|
|
62
|
-
self.credential = credential
|
|
63
|
-
self.status = NOTOPEN
|
|
64
|
-
self.ws = None
|
|
65
|
-
self.wst = None
|
|
66
|
-
self.listener = listener
|
|
67
|
-
|
|
68
|
-
self.text = "欢迎使用腾讯云实时语音合成"
|
|
69
|
-
self.voice_type = 0
|
|
70
|
-
self.codec = "pcm"
|
|
71
|
-
self.sample_rate = 16000
|
|
72
|
-
self.volume = 0
|
|
73
|
-
self.speed = 0
|
|
74
|
-
self.session_id = ""
|
|
75
|
-
self.enable_subtitle = True
|
|
76
|
-
self.fast_voice_type = ""
|
|
77
|
-
|
|
78
|
-
def set_voice_type(self, voice_type):
|
|
79
|
-
self.voice_type = voice_type
|
|
80
|
-
|
|
81
|
-
def set_codec(self, codec):
|
|
82
|
-
self.codec = codec
|
|
83
|
-
|
|
84
|
-
def set_sample_rate(self, sample_rate):
|
|
85
|
-
self.sample_rate = sample_rate
|
|
86
|
-
|
|
87
|
-
def set_speed(self, speed):
|
|
88
|
-
self.speed = speed
|
|
89
|
-
|
|
90
|
-
def set_volume(self, volume):
|
|
91
|
-
self.volume = volume
|
|
92
|
-
|
|
93
|
-
def set_text(self, text):
|
|
94
|
-
self.text = text
|
|
95
|
-
|
|
96
|
-
def set_enable_subtitle(self, enable_subtitle):
|
|
97
|
-
self.enable_subtitle = enable_subtitle
|
|
98
|
-
|
|
99
|
-
def set_fast_voice_type(self, fast_voice_type):
|
|
100
|
-
self.fast_voice_type = fast_voice_type
|
|
101
|
-
|
|
102
|
-
def __gen_signature(self, params):
|
|
103
|
-
sort_dict = sorted(params.keys())
|
|
104
|
-
sign_str = "GET" + _HOST + _PATH + "?"
|
|
105
|
-
for key in sort_dict:
|
|
106
|
-
sign_str = sign_str + key + "=" + str(params[key]) + '&'
|
|
107
|
-
sign_str = sign_str[:-1]
|
|
108
|
-
secret_key = self.credential.secret_key.encode('utf-8')
|
|
109
|
-
sign_str = sign_str.encode('utf-8')
|
|
110
|
-
hmacstr = hmac.new(secret_key, sign_str, hashlib.sha1).digest()
|
|
111
|
-
s = base64.b64encode(hmacstr)
|
|
112
|
-
s = s.decode('utf-8')
|
|
113
|
-
return s
|
|
114
|
-
|
|
115
|
-
def __gen_params(self, session_id):
|
|
116
|
-
self.session_id = session_id
|
|
117
|
-
|
|
118
|
-
params = dict()
|
|
119
|
-
params['Action'] = _ACTION
|
|
120
|
-
params['AppId'] = int(self.appid)
|
|
121
|
-
params['SecretId'] = self.credential.secret_id
|
|
122
|
-
params['ModelType'] = 1
|
|
123
|
-
params['VoiceType'] = self.voice_type
|
|
124
|
-
params['Codec'] = self.codec
|
|
125
|
-
params['SampleRate'] = self.sample_rate
|
|
126
|
-
params['Speed'] = self.speed
|
|
127
|
-
params['Volume'] = self.volume
|
|
128
|
-
params['SessionId'] = self.session_id
|
|
129
|
-
params['Text'] = self.text
|
|
130
|
-
params['EnableSubtitle'] = self.enable_subtitle
|
|
131
|
-
if len(self.fast_voice_type) > 0:
|
|
132
|
-
params['FastVoiceType'] = self.fast_voice_type
|
|
133
|
-
|
|
134
|
-
timestamp = int(time.time())
|
|
135
|
-
params['Timestamp'] = timestamp
|
|
136
|
-
params['Expired'] = timestamp + 24 * 60 * 60
|
|
137
|
-
return params
|
|
138
|
-
|
|
139
|
-
def __create_query_string(self, param):
|
|
140
|
-
param['Text'] = urllib.parse.quote(param['Text'])
|
|
141
|
-
|
|
142
|
-
param = sorted(param.items(), key=lambda d: d[0])
|
|
143
|
-
|
|
144
|
-
url = _PROTOCOL + _HOST + _PATH
|
|
145
|
-
|
|
146
|
-
signstr = url + "?"
|
|
147
|
-
for x in param:
|
|
148
|
-
tmp = x
|
|
149
|
-
for t in tmp:
|
|
150
|
-
signstr += str(t)
|
|
151
|
-
signstr += "="
|
|
152
|
-
signstr = signstr[:-1]
|
|
153
|
-
signstr += "&"
|
|
154
|
-
signstr = signstr[:-1]
|
|
155
|
-
return signstr
|
|
156
|
-
|
|
157
|
-
def start(self):
|
|
158
|
-
logger.info("synthesizer start: begin")
|
|
159
|
-
|
|
160
|
-
def _close_conn(reason):
|
|
161
|
-
ta = time.time()
|
|
162
|
-
self.ws.close()
|
|
163
|
-
tb = time.time()
|
|
164
|
-
logger.info("client has closed connection ({}), cost {} ms".format(reason, int((tb-ta)*1000)))
|
|
165
|
-
|
|
166
|
-
def _on_data(ws, data, opcode, flag):
|
|
167
|
-
# NOTE print all message that client received
|
|
168
|
-
# logger.info("data={} opcode={} flag={}".format(data, opcode, flag))
|
|
169
|
-
if opcode == ABNF.OPCODE_BINARY:
|
|
170
|
-
self.listener.on_audio_result(data) # <class 'bytes'>
|
|
171
|
-
pass
|
|
172
|
-
elif opcode == ABNF.OPCODE_TEXT:
|
|
173
|
-
resp = json.loads(data) # WSResponseMessage
|
|
174
|
-
if resp['code'] != 0:
|
|
175
|
-
logger.error("server synthesis fail request_id={} code={} msg={}".format(
|
|
176
|
-
resp['request_id'], resp['code'], resp['message']
|
|
177
|
-
))
|
|
178
|
-
self.listener.on_synthesis_fail(resp)
|
|
179
|
-
return
|
|
180
|
-
if "final" in resp and resp['final'] == 1:
|
|
181
|
-
logger.info("recv FINAL frame")
|
|
182
|
-
self.status = FINAL
|
|
183
|
-
_close_conn("after recv final")
|
|
184
|
-
self.listener.on_synthesis_end()
|
|
185
|
-
return
|
|
186
|
-
if "result" in resp:
|
|
187
|
-
if "subtitles" in resp["result"] and resp["result"]["subtitles"] is not None:
|
|
188
|
-
self.listener.on_text_result(resp)
|
|
189
|
-
return
|
|
190
|
-
else:
|
|
191
|
-
logger.error("invalid on_data code, opcode=".format(opcode))
|
|
192
|
-
|
|
193
|
-
def _on_error(ws, error):
|
|
194
|
-
if self.status == FINAL or self.status == CLOSED:
|
|
195
|
-
return
|
|
196
|
-
self.status = ERROR
|
|
197
|
-
logger.error("error={}, session_id={}".format(error, self.session_id))
|
|
198
|
-
_close_conn("after recv error")
|
|
199
|
-
|
|
200
|
-
def _on_close(ws, close_status_code, close_msg):
|
|
201
|
-
logger.info("conn closed, close_status_code={} close_msg={}".format(close_status_code, close_msg))
|
|
202
|
-
self.status = CLOSED
|
|
203
|
-
|
|
204
|
-
def _on_open(ws):
|
|
205
|
-
logger.info("conn opened")
|
|
206
|
-
self.status = OPENED
|
|
207
|
-
|
|
208
|
-
session_id = str(uuid.uuid1())
|
|
209
|
-
params = self.__gen_params(session_id)
|
|
210
|
-
signature = self.__gen_signature(params)
|
|
211
|
-
requrl = self.__create_query_string(params)
|
|
212
|
-
|
|
213
|
-
autho = urllib.parse.quote(signature)
|
|
214
|
-
requrl += "&Signature=%s" % autho
|
|
215
|
-
|
|
216
|
-
self.ws = WebSocketApp(requrl, None,
|
|
217
|
-
on_error=_on_error, on_close=_on_close,
|
|
218
|
-
on_data=_on_data)
|
|
219
|
-
self.ws.on_open = _on_open
|
|
220
|
-
|
|
221
|
-
self.wst = threading.Thread(target=self.ws.run_forever)
|
|
222
|
-
self.wst.daemon = True
|
|
223
|
-
self.wst.start()
|
|
224
|
-
self.status = STARTED
|
|
225
|
-
self.listener.on_synthesis_start(session_id)
|
|
226
|
-
|
|
227
|
-
logger.info("synthesizer start: end")
|
|
228
|
-
|
|
229
|
-
def wait(self):
|
|
230
|
-
logger.info("synthesizer wait: begin")
|
|
231
|
-
if self.ws:
|
|
232
|
-
if self.wst and self.wst.is_alive():
|
|
233
|
-
self.wst.join()
|
|
234
|
-
logger.info("synthesizer wait: end")
|
|
File without changes
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import sys
|
|
3
|
-
import hmac
|
|
4
|
-
import hashlib
|
|
5
|
-
import base64
|
|
6
|
-
import time
|
|
7
|
-
import json
|
|
8
|
-
import threading
|
|
9
|
-
from websocket import ABNF, WebSocketApp
|
|
10
|
-
import uuid
|
|
11
|
-
import urllib
|
|
12
|
-
from common.log import logger
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_PROTOCOL = "wss://"
|
|
16
|
-
_HOST = "tts.cloud.tencent.com"
|
|
17
|
-
_PATH = "/vc_stream"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class SpeechConvertListener(object):
|
|
21
|
-
'''
|
|
22
|
-
'''
|
|
23
|
-
def on_convert_start(self, voice_id):
|
|
24
|
-
logger.info("on_convert_start: voice_id={}".format(voice_id))
|
|
25
|
-
|
|
26
|
-
def on_convert_end(self):
|
|
27
|
-
logger.info("on_convert_end: -")
|
|
28
|
-
|
|
29
|
-
def on_audio_result(self, audio_bytes):
|
|
30
|
-
logger.info("on_audio_result: recv audio bytes, len={}".format(len(audio_bytes)))
|
|
31
|
-
|
|
32
|
-
def on_convert_fail(self, response):
|
|
33
|
-
logger.error("on_convert_fail: code={} msg={}".format(
|
|
34
|
-
response['Code'], response['Message']
|
|
35
|
-
))
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
NOTOPEN = 0
|
|
39
|
-
STARTED = 1
|
|
40
|
-
OPENED = 2
|
|
41
|
-
FINAL = 3
|
|
42
|
-
ERROR = 4
|
|
43
|
-
CLOSED = 5
|
|
44
|
-
|
|
45
|
-
class SpeechConvertor:
|
|
46
|
-
|
|
47
|
-
def __init__(self, appid, credential, listener):
|
|
48
|
-
self.appid = appid
|
|
49
|
-
self.credential = credential
|
|
50
|
-
self.status = NOTOPEN
|
|
51
|
-
self.ws = None
|
|
52
|
-
self.wst = None
|
|
53
|
-
self.listener = listener
|
|
54
|
-
|
|
55
|
-
self.voice_id = ""
|
|
56
|
-
self.voice_type = 301005
|
|
57
|
-
self.codec = "pcm"
|
|
58
|
-
self.sample_rate = 16000
|
|
59
|
-
self.volume = 0
|
|
60
|
-
self.speed = 0
|
|
61
|
-
|
|
62
|
-
def set_voice_type(self, voice_type):
|
|
63
|
-
self.voice_type = voice_type
|
|
64
|
-
|
|
65
|
-
def set_codec(self, codec):
|
|
66
|
-
self.codec = codec
|
|
67
|
-
|
|
68
|
-
def set_sample_rate(self, sample_rate):
|
|
69
|
-
self.sample_rate = sample_rate
|
|
70
|
-
|
|
71
|
-
def set_volume(self, volume):
|
|
72
|
-
self.volume = volume
|
|
73
|
-
|
|
74
|
-
def __gen_signature(self, params):
|
|
75
|
-
sort_dict = sorted(params.keys())
|
|
76
|
-
sign_str = _HOST + _PATH + '/' + str(self.appid) + "?"
|
|
77
|
-
for key in sort_dict:
|
|
78
|
-
sign_str = sign_str + key + "=" + str(params[key]) + '&'
|
|
79
|
-
sign_str = sign_str[:-1]
|
|
80
|
-
logger.info("sign_url={}".format(sign_str))
|
|
81
|
-
secret_key = self.credential.secret_key.encode('utf-8')
|
|
82
|
-
sign_str = sign_str.encode('utf-8')
|
|
83
|
-
hmacstr = hmac.new(secret_key, sign_str, hashlib.sha1).digest()
|
|
84
|
-
s = base64.b64encode(hmacstr)
|
|
85
|
-
s = s.decode('utf-8')
|
|
86
|
-
return s
|
|
87
|
-
|
|
88
|
-
def __gen_params(self, voice_id):
|
|
89
|
-
self.voice_id = voice_id
|
|
90
|
-
|
|
91
|
-
params = dict()
|
|
92
|
-
params['SecretId'] = self.credential.secret_id
|
|
93
|
-
params['VoiceType'] = self.voice_type
|
|
94
|
-
params['Codec'] = self.codec
|
|
95
|
-
params['SampleRate'] = self.sample_rate
|
|
96
|
-
params['Volume'] = self.volume
|
|
97
|
-
params['VoiceId'] = self.voice_id
|
|
98
|
-
params['End'] = 0
|
|
99
|
-
|
|
100
|
-
timestamp = int(time.time())
|
|
101
|
-
params['Timestamp'] = timestamp
|
|
102
|
-
params['Expired'] = timestamp + 24 * 60 * 60
|
|
103
|
-
return params
|
|
104
|
-
|
|
105
|
-
def __create_query_string(self, param):
|
|
106
|
-
param = sorted(param.items(), key=lambda d: d[0])
|
|
107
|
-
|
|
108
|
-
url = _PROTOCOL + _HOST + _PATH + '/' + str(self.appid)
|
|
109
|
-
|
|
110
|
-
signstr = url + "?"
|
|
111
|
-
for x in param:
|
|
112
|
-
tmp = x
|
|
113
|
-
for t in tmp:
|
|
114
|
-
signstr += str(t)
|
|
115
|
-
signstr += "="
|
|
116
|
-
signstr = signstr[:-1]
|
|
117
|
-
signstr += "&"
|
|
118
|
-
signstr = signstr[:-1]
|
|
119
|
-
return signstr
|
|
120
|
-
|
|
121
|
-
def start(self):
|
|
122
|
-
logger.info("convertor start: begin")
|
|
123
|
-
|
|
124
|
-
def _close_conn(reason):
|
|
125
|
-
ta = time.time()
|
|
126
|
-
self.ws.close()
|
|
127
|
-
tb = time.time()
|
|
128
|
-
logger.info("client has closed connection ({}), cost {} ms".format(reason, int((tb-ta)*1000)))
|
|
129
|
-
|
|
130
|
-
def _on_data(ws, data, opcode, flag):
|
|
131
|
-
# NOTE print all message that client received
|
|
132
|
-
#logger.info("data={} opcode={} flag={}".format(data, opcode, flag))
|
|
133
|
-
|
|
134
|
-
if opcode == ABNF.OPCODE_BINARY:
|
|
135
|
-
length = int.from_bytes(data[:4], byteorder='big', signed=False)
|
|
136
|
-
json_str = bytes.decode(data[4: length + 4])
|
|
137
|
-
audio_data = data[4 + length:]
|
|
138
|
-
logger.info("recv raw json: {}".format(json_str))
|
|
139
|
-
|
|
140
|
-
resp = json.loads(json_str)
|
|
141
|
-
if resp['Code'] != 0:
|
|
142
|
-
logger.error("server convert fail voice_id={} code={} msg_id={} msg={}".format(
|
|
143
|
-
resp['VoiceId'], resp['Code'], resp['MessageId'], resp['Message']
|
|
144
|
-
))
|
|
145
|
-
self.listener.on_convert_fail(resp)
|
|
146
|
-
return
|
|
147
|
-
|
|
148
|
-
# normal recv converted data
|
|
149
|
-
self.listener.on_audio_result(audio_data) # <class 'bytes'>
|
|
150
|
-
if "Final" in resp and resp['Final'] == 1:
|
|
151
|
-
logger.info("recv FINAL frame")
|
|
152
|
-
self.status = FINAL
|
|
153
|
-
_close_conn("after recv final")
|
|
154
|
-
self.listener.on_convert_end()
|
|
155
|
-
elif opcode == ABNF.OPCODE_TEXT:
|
|
156
|
-
pass
|
|
157
|
-
else:
|
|
158
|
-
logger.error("invalid on_data code, opcode=".format(opcode))
|
|
159
|
-
|
|
160
|
-
def _on_error(ws, error):
|
|
161
|
-
if self.status == FINAL or self.status == CLOSED:
|
|
162
|
-
return
|
|
163
|
-
self.status = ERROR
|
|
164
|
-
logger.error("error={}, voice_id={}".format(error, self.voice_id))
|
|
165
|
-
_close_conn("after recv error")
|
|
166
|
-
|
|
167
|
-
def _on_close(ws, close_status_code, close_msg):
|
|
168
|
-
logger.info("conn closed, close_status_code={} close_msg={}".format(close_status_code, close_msg))
|
|
169
|
-
self.status = CLOSED
|
|
170
|
-
|
|
171
|
-
def _on_open(ws):
|
|
172
|
-
logger.info("conn opened")
|
|
173
|
-
self.status = OPENED
|
|
174
|
-
|
|
175
|
-
voice_id = str(uuid.uuid1())
|
|
176
|
-
params = self.__gen_params(voice_id)
|
|
177
|
-
signature = self.__gen_signature(params)
|
|
178
|
-
requrl = self.__create_query_string(params)
|
|
179
|
-
|
|
180
|
-
autho = urllib.parse.quote(signature)
|
|
181
|
-
requrl += "&Signature=%s" % autho
|
|
182
|
-
logger.info("req_url={}".format(requrl))
|
|
183
|
-
|
|
184
|
-
self.ws = WebSocketApp(requrl, None,
|
|
185
|
-
on_error=_on_error, on_close=_on_close,
|
|
186
|
-
on_data=_on_data)
|
|
187
|
-
self.ws.on_open = _on_open
|
|
188
|
-
|
|
189
|
-
self.wst = threading.Thread(target=self.ws.run_forever)
|
|
190
|
-
self.wst.daemon = True
|
|
191
|
-
self.wst.start()
|
|
192
|
-
self.status = STARTED
|
|
193
|
-
self.listener.on_convert_start(voice_id)
|
|
194
|
-
|
|
195
|
-
logger.info("convertor start: end")
|
|
196
|
-
|
|
197
|
-
def wait(self):
|
|
198
|
-
logger.info("convertor wait: begin")
|
|
199
|
-
if self.ws:
|
|
200
|
-
if self.wst and self.wst.is_alive():
|
|
201
|
-
self.wst.join()
|
|
202
|
-
logger.info("convertor wait: end")
|
|
203
|
-
|
|
204
|
-
def send(self, audio_data, is_end=False):
|
|
205
|
-
logger.info("convertor send: begin")
|
|
206
|
-
if not self.ws:
|
|
207
|
-
logger.error("convertor send: ws is None")
|
|
208
|
-
return False
|
|
209
|
-
if self.status != OPENED:
|
|
210
|
-
logger.error("ws not opened, status={}".format(self.status))
|
|
211
|
-
return False
|
|
212
|
-
|
|
213
|
-
# message format: HEAD + JSON + AUDIO
|
|
214
|
-
# refer to https://cloud.tencent.com/document/product/1664/85973#edac94f7-2e9d-4e59-aac3-fd1bea693be0
|
|
215
|
-
json_body = json.dumps({
|
|
216
|
-
"End": 1 if is_end else 0,
|
|
217
|
-
})
|
|
218
|
-
json_body_bytes = bytes(json_body, encoding='utf-8')
|
|
219
|
-
json_body_len = len(json_body_bytes)
|
|
220
|
-
|
|
221
|
-
head = json_body_len.to_bytes(4, byteorder='big')
|
|
222
|
-
message = head + json_body_bytes + audio_data
|
|
223
|
-
logger.info("send json_body_len={} json_body={} audio_len={}".format(
|
|
224
|
-
json_body_len, json_body, len(audio_data)))
|
|
225
|
-
|
|
226
|
-
self.ws.send(message, ABNF.OPCODE_BINARY)
|
|
227
|
-
logger.info("convertor send: end")
|
|
228
|
-
return True
|
|
229
|
-
|
|
230
|
-
def wait_to_send(self):
|
|
231
|
-
while True:
|
|
232
|
-
if self.status < OPENED:
|
|
233
|
-
time.sleep(0.01)
|
|
234
|
-
else:
|
|
235
|
-
break
|
|
236
|
-
logger.info("wait_to_send: status={}".format(self.status))
|
|
237
|
-
return self.status == OPENED
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
smartpi/touch_sensor.py
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# coding=utf-8
|
|
2
|
-
import time
|
|
3
|
-
from typing import List, Optional
|
|
4
|
-
from smartpi import base_driver
|
|
5
|
-
|
|
6
|
-
#���������� port:����P�˿� �������أ�1��0; ��ȡ����-1
|
|
7
|
-
def get_value(port:bytes) -> Optional[bytes]:
|
|
8
|
-
read_sw_str=[0xA0, 0x03, 0x01, 0xBE]
|
|
9
|
-
read_sw_str[0]=0XA0+port
|
|
10
|
-
time.sleep(0.005)
|
|
11
|
-
response = base_driver.single_operate_sensor(read_sw_str,0)
|
|
12
|
-
if response == None:
|
|
13
|
-
return None
|
|
14
|
-
else:
|
|
15
|
-
return response[4]
|
|
16
|
-
|