forked from MyDuerOS/DuerOS-Python-Client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspeech_recognizer.py
More file actions
188 lines (159 loc) · 5.07 KB
/
speech_recognizer.py
File metadata and controls
188 lines (159 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# -*- coding: utf-8 -*-
"""
语音识别功能模块(语音输入)
参考:http://open.duer.baidu.com/doc/dueros-conversational-service/device-interface/voice-input_markdown
"""
import logging
import uuid
try:
import Queue as queue
except ImportError:
import queue
import sdk.sdk_config as sdk_config
logging.basicConfig(level=sdk_config.LOGGER_LEVEL)
logger = logging.getLogger('SpeechRecognizer')
class SpeechRecognizer(object):
'''
语音识别类(语音输入)
'''
STATES = {'IDLE', 'RECOGNIZING', 'BUSY', 'EXPECTING SPEECH'}
PROFILES = {'CLOSE_TALK', 'NEAR_FIELD', 'FAR_FIELD'}
PRESS_AND_HOLD = {'type': 'PRESS_AND_HOLD', 'payload': {}}
TAP = {'type': 'TAP', 'payload': {}}
def __init__(self, dueros):
'''
类初始化
:param dueros:DuerOS核心实现模块实例
'''
self.namespace = 'ai.dueros.device_interface.voice_input'
self.dueros = dueros
self.profile = 'NEAR_FIELD'
self.dialog_request_id = ''
self.listening = False
self.audio_queue = queue.Queue()
def put(self, audio):
"""
语音pcm输入
:param audio: S16_LE format, sample rate 16000 bps audio data
:return: None
"""
if self.listening:
self.audio_queue.put(audio)
def recognize(self, dialog=None, timeout=10000):
"""
语音识别
:param dialog:会话ID
:param timeout:超时时间(单位毫秒)
:return:
"""
if self.listening:
return
self.audio_queue.queue.clear()
self.listening = True
self.dueros.state_listener.on_listening()
def on_finished():
self.dueros.state_listener.on_finished()
if self.dueros.audio_player.state == 'PAUSED':
self.dueros.audio_player.resume()
# Stop playing if Xiaoduxiaodu is speaking or AudioPlayer is playing
if self.dueros.speech_synthesizer.state == 'PLAYING':
self.dueros.speech_synthesizer.stop()
elif self.dueros.audio_player.state == 'PLAYING':
self.dueros.audio_player.pause()
self.dialog_request_id = dialog if dialog else uuid.uuid4().hex
event = {
"header": {
"namespace": self.namespace,
"name": "ListenStarted",
"messageId": uuid.uuid4().hex,
"dialogRequestId": self.dialog_request_id
},
"payload": {
"profile": self.profile,
"format": "AUDIO_L16_RATE_16000_CHANNELS_1",
}
}
def gen():
time_elapsed = 0
while self.listening or time_elapsed >= timeout:
try:
chunk = self.audio_queue.get(timeout=1.0)
except queue.Empty:
break
yield chunk
time_elapsed += 10 # 10 ms chunk
self.listening = False
self.dueros.state_listener.on_thinking()
self.dueros.send_event(event, listener=on_finished, attachment=gen())
# {
# "directive": {
# "header": {
# "namespace": "SpeechRecognizer",
# "name": "StopCapture",
# "messageId": "{{STRING}}",
# "dialogRequestId": "{{STRING}}"
# },
# "payload": {
# }
# }
# }
def stop_listen(self, directive):
'''
停止录音监听(云端directive name方法)
:param directive: 云端下发的directive
:return:
'''
self.listening = False
logger.info('StopCapture')
# {
# "directive": {
# "header": {
# "namespace": "SpeechRecognizer",
# "name": "ExpectSpeech",
# "messageId": "{{STRING}}",
# "dialogRequestId": "{{STRING}}"
# },
# "payload": {
# "timeoutInMilliseconds": {{LONG}},
# "initiator": "{{STRING}}"
# }
# }
# }
def listen(self, directive):
'''
启动录音监听(云端directive name方法)
:param directive: 云端下发的directive
:return:
'''
dialog = directive['header']['dialogRequestId']
timeout = directive['payload']['timeoutInMilliseconds']
self.recognize(dialog=dialog, timeout=timeout)
def expect_speech_timeout(self):
'''
超时时间上报
:return:
'''
event = {
"header": {
"namespace": self.namespace,
"name": "ExpectSpeechTimedOut",
"messageId": uuid.uuid4().hex,
},
"payload": {}
}
self.dueros.send_event(event)
@property
def context(self):
'''
获取模块上下文(模块状态)
:return:
'''
return {
"header": {
"namespace": self.namespace,
"name": "ListenStarted"
},
"payload": {
"wakeword": "xiaoduxiaodu"
}
}