diff --git a/README.md b/README.md index 9afbcce..38fb1c0 100644 --- a/README.md +++ b/README.md @@ -1,229 +1,2 @@ # DuerOS-Python-Client使用说明 -## 运行依赖 -* gstreamer1.0 -* gstreamer1.0-plugins-good -* gstreamer1.0-plugins-ugly -* python-gi -* python-gst -* gir1.2-gstreamer-1.0 -## 测试环境 -* Ubuntu 16.04 -* Python 2.7.12 -## 使用说明 -### 项目获取 -通过git下载代码到本地 - - # git clone https://github.com/MyDuerOS/DuerOS-Python-Client.git - -### 认证授权 -在DuerOS-Python-Client目录下执行 - - # ./auth.sh - -### 通过[Enter]键触发唤醒状态 -在DuerOS-Python-Client目录下执行 - - # ./enter_trigger_start.sh - -然后,每次单击[Enter]键后进行语音输入 -### 通过[小度小度]触发唤醒状态 -在DuerOS-Python-Client目录下执行 - - # ./wakeup_trigger_start.sh -然后,每次通过[小度小度]进行唤醒,然后,进行语音输入 - - -## 代码结构 -DuerOS-Python-Client代码结构如下图所示, - -![图片](./readme_resources/代码结构.png) - - -其中, - -*DuerOS-Python-Client:项目根目录* - -* DuerOS-Python-Client/auth.sh:认证授权脚本 -* DuerOS-Python-Client/enter_trigger_start.sh:[Enter]按键触发唤醒脚本 -* DuerOS-Python-Client/wakeup_tirgger_start.sh:[小度小度]触发唤醒脚本 - -*DuerOS-Python-Client/app:应用目录* - -* DuerOS-Python-Client/app/auth.py:认证授权实现模块 -* DuerOS-Python-Client/app/enter_trigger_main.py:[Enter]按键触发唤醒实现模块 -* DuerOS-Python-Client/app/wakeup_tirgger_main.py:[小度小度]触发唤醒实现模块 -* DuerOS-Python-Client/app/framework:平台相关目录 -* DuerOS-Python-Client/app/framework/mic.py:录音模块(基于pyaudio) -* DuerOS-Python-Client/app/framework/player.py:播放模块(基于GStreamer) -* DuerOS-Python-Client/app/snowboy:snowboy唤醒引擎 - -*DuerOS-Python-Client/sdk:dueros sdk目录* - -* DuerOS-Python-Client/sdk/auth.py:授权相关实现 -* DuerOS-Python-Client/sdk/dueros_core.py:dueros交互实现 -* DuerOS-Python-Client/sdk/interface:端能力接口实现 - -## SDK接口说明 -### 授权模块(sdk/auth) -#### 授权接口 -用户通过授权接口完成基于OAuth2.0的认证授权流程 - - def auth_request(client_id=CLIENT_ID, client_secret=CLIENT_SECRET): - ''' - 发起认证 - :param client_id:开发者注册信息 - :param client_secret: 开发者注册信息 - :return: - ''' - -### DuerOS核心模块(sdk/dueros_core) -#### 启动DuerOS核心模块 -DuerOS核心处理模块启动 - - def start(self): - ''' - DuerOS模块启动 - :return: - ''' -#### 停止DuerOS核心模块 -DuerOS核心处理模块停止 - - def stop(self): - ''' - DuerOS模块停止 - :return: - ''' -#### 触发语音识别状态 -DuerOS核心处理模块进入语音识别状态(唤醒后触发) - - def listen(self): - ''' - DuerOS进入语音识别状态 - :return: - ''' -#### directive监听注册 -通过监听注册接口,用户可以获得云端下发的directive内容 - - def set_directive_listener(self, listener): - ''' - directive监听器设置 - :param listener: directive监听器 - :return: - ''' - -## App接口说明 -### 录音模块(app/framework/mic) -#### 开始录音 -录音开始控制 - - def start(self): - ''' - 开始录音 - :return: - ''' -#### 结束录音 -录音结束控制 - - def stop(self): - ''' - 结束录音 - :return: - ''' -#### 录音接收实体绑定 -将录音组件同,duersdk进行绑定 - - def link(self, sink): - ''' - 绑定录音接收实体 - :param sink: 录音接收实体 - :return: - ''' -#### 录音实体解除绑定 -解除录音组件同duersdk间的绑定 - - def unlink(self, sink): - ''' - 录音实体解除绑定 - :param sink: 录音接收实体 - :return: - ''' -### 播放模块(app/framework/player) -#### 开始播放 -开始播放控制 - - def play(self, uri): - ''' - 播放 - :param uri:播放资源地址 - :return: - ''' -#### 停止播放 -停止播放控制 - - def stop(self): - ''' - 停止 - :return: - ''' -#### 暂停播放 -暂停播放控制 - - def pause(self): - ''' - 暂停 - :return: - ''' -#### 恢复播放 -恢复播放控制 - - def resume(self): - ''' - 回复播放 - :return: - ''' -#### 播放状态监听注册 -注册播放状态的监听器 - - def add_callback(self, name, callback): - ''' - 播放状态回调 - :param name: {eos, ...} - :param callback: 回调函数 - :return: - ''' -##### 播放时长 -当前播放音频的播放时长(模块属性) - - @property - def duration(self): - ''' - 播放时长 - :return: - ''' -##### 播放位置 -当前播放音频的播放位置(模块属性) - - @property - def position(self): - ''' - 播放位置 - :return: - ''' -#### 播放状态 -当前播放音频的播放状态(模块属性) - - @property - def state(self): - ''' - 播放状态 - :return: - ''' -### 工具模块(app/utils/prompt_tone) -#### 提示音播放 -短暂提示音("du")播放 - - def play(self): - ''' - 提示音播放 - :return: - ''' \ No newline at end of file +开发中分支,不建议使用,Ubuntu平台请直接使用master分支代码~ diff --git a/app/enter_trigger_main.py b/app/enter_trigger_main.py index 4e30812..157e940 100644 --- a/app/enter_trigger_main.py +++ b/app/enter_trigger_main.py @@ -3,11 +3,11 @@ 通过输入[Enter]触发唤醒状态 ''' import logging -from sdk.dueros_core import DuerOS -from app.framework.mic import Audio -from app.framework.player import Player +from app.framework.mic.default_mic.mic import Audio +from app.framework.player.player import Player from app.utils.prompt_tone import PromptTone +from sdk.dueros_core import DuerOS logging.basicConfig(level=logging.INFO) diff --git a/app/framework/mic/__init__.py b/app/framework/mic/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/framework/mic/default_mic/__init__.py b/app/framework/mic/default_mic/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/framework/mic.py b/app/framework/mic/default_mic/mic.py similarity index 100% rename from app/framework/mic.py rename to app/framework/mic/default_mic/mic.py diff --git a/app/framework/player/__init__.py b/app/framework/player/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/framework/player/aec_player/__init__.py b/app/framework/player/aec_player/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/framework/player/aec_player/common_params.py b/app/framework/player/aec_player/common_params.py new file mode 100644 index 0000000..1f4916c --- /dev/null +++ b/app/framework/player/aec_player/common_params.py @@ -0,0 +1,63 @@ +# coding:utf-8 +########################################################### +# ProcessMessage Type +# 默认值 +PROCESS_MESSAGE_TPYE_DEFAULT = 0 + +# 打断 +PROCESS_MESSAGE_TPYE_INTERRUPT = 1000 +# 恢复 +PROCESS_MESSAGE_TPYE_RESUME = 1001 +PROCESS_MESSAGE_TPYE_MUTE_CTL = 1002 +# Speech 字段播放 +PROCESS_MESSAGE_TPYE_SPEECH = 1003 +# SpeechSynthesizer +# directives下面的SpeechSynthesizer +PROCESS_MESSAGE_TPYE_SPEECH_SYNTHESIZER = 1004 +# SpeechSynthesizer停止 +PROCESS_MESSAGE_TPYE_SPEECH_SYNTHESIZER_STOP = 1005 +# AudioPlayer +PROCESS_MESSAGE_TPYE_AUDIO_PRE_DECODE = 1006 +# 播放有声资源 +PROCESS_MESSAGE_TPYE_AUDIO_PLAY = 1007 +PROCESS_MESSAGE_TPYE_AUDIO_STOP = 1008 +# Alerts +# 设置提醒 +PROCESS_MESSAGE_TPYE_SET_ALERT = 1009 +# 删除提醒 +PROCESS_MESSAGE_TPYE_DELETE_ALERT = 1010 +# Timer +# 提醒计时器指令 +PROCESS_MESSAGE_TPYE_REMIND_UPDATE = 1011 +# 提醒计时器指令 +PROCESS_MESSAGE_TPYE_REMIND_STOP = 1012 +# 修改音色 +PROCESS_MESSAGE_TPYE_CHANGE_TONE = 1013 + +################################################ +# http://wiki.baidu.com/pages/viewpage.action?pageId=268099035 +SPEECH_TYPE = "type" +SPEECH_CONTENT = "content" +ID = "id" +LOGID = "logid"; +START_PLAY_TIME = "start_play_time" +MESSAGE_ID = "message_id" +TOKEN = "token" +OFFSET_MS = "offset_ms" +FORMAT = "stream_format" +ALARM_ID = "alarm_id" +TONE = "tone" +ALERTS = "alerts" +AP_NAME = "ap_name" +PLAYER_COUNT = "player_count" +NETWORK_CONFIG_FAILED = "network_config_failed" +CUID = "cuid" + +PLAY_BEHAVIOR = "play_behavior" +URL = "url" +PROCESS_REPORT_INTERVAL_MS = "progress_report_interval_ms" + +###############################3 +TYPE_STRING = 1 +TYPE_INT = 2 +TYPE_BUFFER = 3 diff --git a/app/framework/player/aec_player/ipc_clinet.py b/app/framework/player/aec_player/ipc_clinet.py new file mode 100644 index 0000000..eee1eee --- /dev/null +++ b/app/framework/player/aec_player/ipc_clinet.py @@ -0,0 +1,151 @@ +# coding:utf-8 +import struct +import Queue as queue +import threading +from app.framework.player.aec_player.local_socket_clinet import LocalSocketClint +from app.framework.player.aec_player.process_message import ProcessMessage +import app.framework.player.aec_player.common_params as common_params + + +class IpcClient(object): + def __init__(self): + self.local_socket_client = LocalSocketClint() + self.local_socket_client.bind() + self.send_queue = queue.Queue() + self.recv_queue = queue.Queue() + + self.send_thread_flag = True + send_thread = threading.Thread(target=self.__send_run) + send_thread.daemon = True + send_thread.start() + + self.recv_thread_flag = True + recv_thread = threading.Thread(target=self.__recv_run) + recv_thread.daemon = True + recv_thread.start() + + self.listener_list = [] + + def add_listener(self, listener): + if not callable(listener): + raise 'listener is not callable!' + + self.listener_list.append(listener) + + def send(self, msg): + self.send_queue.put(msg) + + def __serialize(self, msg): + type_int_bytes = struct.pack('i', common_params.TYPE_INT) + msg.send_data += type_int_bytes + + msg_type_bytes = struct.pack('i', msg.type) + msg.send_data += msg_type_bytes + + for key in msg.map_str: + # key + key_len_bytes = struct.pack('i', len(key)) + msg.send_data += key_len_bytes + key_type_bytes = struct.pack('i', common_params.TYPE_STRING) + msg.send_data += key_type_bytes + msg.send_data += bytes(key) + + # value + val = msg.map_str[key] + val_len_bytes = struct.pack('i', len(val)) + msg.send_data += val_len_bytes + val_type_bytes = struct.pack('i', common_params.TYPE_STRING) + msg.send_data += val_type_bytes + msg.send_data += bytes(val) + + print 'key= ', key + print 'val= ', val + + for key in msg.map_int: + # key + key_len_bytes = struct.pack('i', len(key)) + msg.send_data += key_len_bytes + key_type_bytes = struct.pack('i', common_params.TYPE_STRING) + msg.send_data += key_type_bytes + msg.send_data += bytes(key) + + # value + val = msg.map_int[key] + val_len_bytes = struct.pack('i', 4) + msg.send_data += val_len_bytes + val_type_bytes = struct.pack('i', common_params.TYPE_INT) + msg.send_data += val_type_bytes + val_bytes = struct.pack('i', val) + msg.send_data += val_bytes + + data_len_bytes = struct.pack('i', len(msg.send_data)) + print 'package len= ', len(msg.send_data) + msg.send_len += data_len_bytes + + send_package_bytes = msg.send_len + msg.send_data + return send_package_bytes + + def __send_msg(self, msg): + print '\n\n\nipc send msg:\n\n\n' + send_data = self.__serialize(msg) + self.local_socket_client.send(send_data) + + def __send_run(self): + while self.send_thread_flag: + msg = self.send_queue.get() + self.__send_msg(msg) + + def __recv_run(self): + while self.recv_thread_flag: + print '\n\n\nipc recv msg:\n\n\n' + msg = ProcessMessage() + #read length part in messge + package_size = self.local_socket_client.recv(4) + package_size = struct.unpack('i', package_size)[0] + print 'whole received package size= ', package_size + + #read length of bytes form socked + package_body = self.local_socket_client.recv(package_size) + + #read the type of packet + pos = 0 + int_type = package_body[pos:pos + 4] + pos += 4 + package_type = package_body[pos:pos + 4] + msg.type = struct.unpack('i', package_type)[0] + print 'recv msg.type= %d' %(msg.type) + pos += 4 + while pos < package_size: + # key + key_len = struct.unpack('i', package_body[pos:pos + 4])[0] + pos += 4 + key_type = package_body[pos:pos + 4] + pos += 4 + key = str(package_body[pos:pos + key_len]) + print 'recv key= ', key + pos += key_len + + # val + val_len = struct.unpack('i', package_body[pos:pos + 4])[0] + pos += 4 + val_type = package_body[pos:pos + 4] + val_type = struct.unpack('i', val_type)[0] + pos += 4 + val = package_body[pos:pos + val_len] + pos += val_len + + if val_type == common_params.TYPE_INT: + int_val = struct.unpack('i', val)[0] + msg.set_int_params(key, int_val) + print 'recv int_val= ', int_val + elif val_type == common_params.TYPE_STRING: + msg.set_str_params(key, str(val)) + print 'recv string val= ', str(val) + + for listener_callback in self.listener_list: + listener_callback(msg) + + def __del__(self): + self.local_socket_client.ubind() + self.send_thread_flag = False + self.recv_thread_flag = False diff --git a/app/framework/player/aec_player/local_socket_clinet.py b/app/framework/player/aec_player/local_socket_clinet.py new file mode 100644 index 0000000..62ad4cf --- /dev/null +++ b/app/framework/player/aec_player/local_socket_clinet.py @@ -0,0 +1,29 @@ +# coding:utf-8 + +import socket +import sys + + +class LocalSocketClint(object): + def __init__(self): + self.AUDIO_PLAYER_ADDR = '/duer/audioplayer_socket_file' + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + + def bind(self): + print 'start to bind server........' + + try: + self.sock.connect(self.AUDIO_PLAYER_ADDR) + print 'bind success!' + except socket.error, msg: + print 'bind failed!, msg=', msg + sys.exit(1) + + def ubind(self): + self.sock.close() + + def send(self, data): + self.sock.sendall(data) + + def recv(self, data_len): + return self.sock.recv(data_len) diff --git a/app/framework/player/aec_player/player.py b/app/framework/player/aec_player/player.py new file mode 100644 index 0000000..a269490 --- /dev/null +++ b/app/framework/player/aec_player/player.py @@ -0,0 +1,76 @@ +# coding:utf-8 +from app.framework.player.aec_player.ipc_clinet import IpcClient +from app.framework.player.aec_player.process_message import ProcessMessage +import app.framework.player.aec_player.common_params as common_params +class Player(object): + def __init__(self): + self.ipc_client=IpcClient() + self.ipc_client.add_listener(self.__ipc_listener) + self.call_table = {} + def play(self, url): + # msg = ProcessMessage() + # msg.type = common_params.PROCESS_MESSAGE_TPYE_AUDIO_PLAY + # msg.set_str_params(common_params.ID, '1160253209') + # msg.set_str_params(common_params.LOGID, '651d0597cc0e4e52a6f017a932509bc7') + # msg.set_str_params(common_params.MESSAGE_ID, 'YXVkaW9fbXVzaWMrMTUxMDEzMTQxOV82MjlmcDEycGM=') + # msg.set_str_params(common_params.PLAY_BEHAVIOR, 'REPLACE_ALL') + # msg.set_str_params(common_params.TOKEN, 'YXVkaW9fbXVzaWMrMTE2MDI1MzIwOQ==') + # msg.set_str_params(common_params.URL, url) + # msg.set_str_params(common_params.FORMAT, 'AUDIO_MPEG') + # msg.set_int_params(common_params.OFFSET_MS, 0) + # msg.set_int_params(common_params.PROCESS_REPORT_INTERVAL_MS, 15000) + + msg = ProcessMessage() + msg.type = common_params.PROCESS_MESSAGE_TPYE_AUDIO_PLAY + msg.set_str_params(common_params.ID, '0') + msg.set_str_params(common_params.LOGID, '0') + msg.set_str_params(common_params.MESSAGE_ID, '0') + msg.set_str_params(common_params.PLAY_BEHAVIOR, 'REPLACE_ALL') + msg.set_str_params(common_params.TOKEN, '0') + msg.set_str_params(common_params.URL, url) + msg.set_str_params(common_params.FORMAT, 'AUDIO_MPEG') + msg.set_int_params(common_params.OFFSET_MS, 0) + msg.set_int_params(common_params.PROCESS_REPORT_INTERVAL_MS, 15000) + + self.ipc_client.send(msg) + + def stop(self): + msg = ProcessMessage() + msg.type = common_params.PROCESS_MESSAGE_TPYE_AUDIO_STOP + self.ipc_client.send(msg) + + def pause(self): + msg = ProcessMessage() + msg.type = common_params.PROCESS_MESSAGE_TPYE_AUDIO_STOP + self.ipc_client.send(msg) + + def resume(self): + msg = ProcessMessage() + msg.type = common_params.PROCESS_MESSAGE_TPYE_RESUME + self.ipc_client.send(msg) + + def add_callback(self, name, callback): + print "add a callback for :", name + self.call_table[name] = callback + + def __ipc_listener(self, msg): + print "received msg type = ", msg.type + callbackfunc = self.call_table[msg.type] + if (callbackfunc and callable(callbackfunc)): + callbackfunc() + + @property + def duration(self): + pass + + @property + def position(self): + pass + + @property + def state(self): + pass + + + + diff --git a/app/framework/player/aec_player/process_message.py b/app/framework/player/aec_player/process_message.py new file mode 100644 index 0000000..c3be83d --- /dev/null +++ b/app/framework/player/aec_player/process_message.py @@ -0,0 +1,16 @@ +import app.framework.player.aec_player.common_params as common_params + + +class ProcessMessage(object): + def __init__(self): + self.type = common_params.PROCESS_MESSAGE_TPYE_DEFAULT + self.map_int = {} + self.map_str = {} + self.send_len = '' + self.send_data = '' + + def set_int_params(self, key, val): + self.map_int[key] = val + + def set_str_params(self, key, val): + self.map_str[key] = val diff --git a/app/framework/player/aec_player/test.py b/app/framework/player/aec_player/test.py new file mode 100644 index 0000000..a5b203e --- /dev/null +++ b/app/framework/player/aec_player/test.py @@ -0,0 +1,17 @@ +# coding:utf-8 +import time +from app.framework.player.aec_player.player import Player + +URL = 'http://yinyueshiting.baidu.com/data2/music/31e2c3833449a76c94327b47ebf0637d/551729523/551729523.mp3?xcode=1aa6ee0550da1b5a43e6e1d8249fc792' +player = Player() + + +def test_play(): + player.play(URL) + + +if __name__ == "__main__": + test_play() + + while True: + time.sleep(1) diff --git a/app/framework/player/default_player/__init__.py b/app/framework/player/default_player/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/framework/player.py b/app/framework/player/default_player/player.py similarity index 100% rename from app/framework/player.py rename to app/framework/player/default_player/player.py diff --git a/app/framework/player/player.py b/app/framework/player/player.py new file mode 100644 index 0000000..6bd1ac0 --- /dev/null +++ b/app/framework/player/player.py @@ -0,0 +1,35 @@ +from app.framework.player.aec_player.player import Player as DevicePlayer + + +# from app.framework.player.default_player.player import Player as DevicePlayer + +class Player(object): + def __init__(self): + self.player = DevicePlayer() + + def play(self, uri): + self.player.play(uri) + + def stop(self): + self.player.stop() + + def pause(self): + self.player.pause() + + def resume(self): + self.player.resume() + + def add_callback(self, name, callback): + self.player.add_callback(name, callback) + + @property + def duration(self): + self.player.duration + + @property + def position(self): + self.player.position + + @property + def state(self): + self.player.state diff --git a/app/snowboy/_snowboydetect.so b/app/snowboy/_snowboydetect.so index ea7281b..e8640f9 100755 Binary files a/app/snowboy/_snowboydetect.so and b/app/snowboy/_snowboydetect.so differ diff --git a/app/snowboy/resources/snowboy.wav b/app/snowboy/resources/snowboy.wav index 8ce4100..6cf6fa0 100644 Binary files a/app/snowboy/resources/snowboy.wav and b/app/snowboy/resources/snowboy.wav differ diff --git a/app/snowboy/snowboydecoder.py b/app/snowboy/snowboydecoder.py index d748561..36f21a7 100644 --- a/app/snowboy/snowboydecoder.py +++ b/app/snowboy/snowboydecoder.py @@ -8,8 +8,6 @@ import os import logging -import sdk.sdk_config as sdk_config - logging.basicConfig() logger = logging.getLogger("snowboy") logger.setLevel(logging.INFO) @@ -22,8 +20,7 @@ class RingBuffer(object): """Ring buffer to hold audio from PortAudio""" - - def __init__(self, size=4096): + def __init__(self, size = 4096): self._buf = collections.deque(maxlen=size) def extend(self, data): @@ -72,16 +69,15 @@ class HotwordDetector(object): default sensitivity in the model will be used. :param audio_gain: multiply input volume by this factor. """ - def __init__(self, decoder_model, resource=RESOURCE_FILE, sensitivity=[], audio_gain=1): - # def audio_callback(in_data, frame_count, time_info, status): - # self.ring_buffer.extend(in_data) - # play_data = chr(0) * len(in_data) - # return play_data, pyaudio.paContinue + def audio_callback(in_data, frame_count, time_info, status): + self.ring_buffer.extend(in_data) + play_data = chr(0) * len(in_data) + return play_data, pyaudio.paContinue tm = type(decoder_model) ts = type(sensitivity) @@ -97,14 +93,14 @@ def __init__(self, decoder_model, self.num_hotwords = self.detector.NumHotwords() if len(decoder_model) > 1 and len(sensitivity) == 1: - sensitivity = sensitivity * self.num_hotwords - # if len(sensitivity) != 0: - # assert self.num_hotwords == len(sensitivity), \ - # "number of hotwords in decoder_model (%d) and sensitivity " \ - # "(%d) does not match" % (self.num_hotwords, len(sensitivity)) - # sensitivity_str = ",".join([str(t) for t in sensitivity]) + sensitivity = sensitivity*self.num_hotwords if len(sensitivity) != 0: - self.detector.SetSensitivity(sdk_config.SNOWBOAY_SENSITIVITY) + assert self.num_hotwords == len(sensitivity), \ + "number of hotwords in decoder_model (%d) and sensitivity " \ + "(%d) does not match" % (self.num_hotwords, len(sensitivity)) + sensitivity_str = ",".join([str(t) for t in sensitivity]) + if len(sensitivity) != 0: + self.detector.SetSensitivity(sensitivity_str.encode()) self.ring_buffer = RingBuffer( self.detector.NumChannels() * self.detector.SampleRate() * 5) @@ -122,6 +118,7 @@ def __init__(self, decoder_model, def feed_data(self, data): self.ring_buffer.extend(data) + def start(self, detected_callback=play_audio_file, interrupt_check=lambda: False, sleep_time=0.03): @@ -174,7 +171,7 @@ def start(self, detected_callback=play_audio_file, message += time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) logger.info(message) - callback = detected_callback[ans - 1] + callback = detected_callback[ans-1] if callback is not None: callback() @@ -185,6 +182,7 @@ def terminate(self): Terminate audio stream. Users cannot call start() again to detect. :return: None """ - self.stream_in.stop_stream() - self.stream_in.close() - self.audio.terminate() + # self.stream_in.stop_stream() + # self.stream_in.close() + # self.audio.terminate() + pass diff --git a/app/snowboy/xiaobai.pmdl b/app/snowboy/xiaobai.pmdl new file mode 100644 index 0000000..b8a952f Binary files /dev/null and b/app/snowboy/xiaobai.pmdl differ diff --git a/app/snowboy/xiaoduxiaodu_all_10022017.umdl b/app/snowboy/xiaoduxiaodu_all_10022017.umdl deleted file mode 100644 index ba6f383..0000000 Binary files a/app/snowboy/xiaoduxiaodu_all_10022017.umdl and /dev/null differ diff --git a/app/utils/prompt_tone.py b/app/utils/prompt_tone.py index 44840a3..ee37137 100644 --- a/app/utils/prompt_tone.py +++ b/app/utils/prompt_tone.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import os -from app.framework.player import Player + +from app.framework.player.player import Player class PromptTone(object): diff --git a/app/wakeup_trigger_main.py b/app/wakeup_trigger_main.py index 7c813d6..b34b912 100644 --- a/app/wakeup_trigger_main.py +++ b/app/wakeup_trigger_main.py @@ -16,8 +16,8 @@ import app.app_config as app_config from sdk.dueros_core import DuerOS -from app.framework.player import Player -from app.framework.mic import Audio +from app.framework.player.player import Player +from app.framework.mic.default_mic.mic import Audio from app.snowboy import snowboydecoder from app.utils.prompt_tone import PromptTone @@ -183,7 +183,8 @@ def main(): dueros.set_directive_listener(directive_listener) # [小度小度] SnowBoy唤醒引擎 - model = 'app/snowboy/xiaoduxiaodu_all_10022017.umdl' + # model = 'app/snowboy/xiaoduxiaodu_all_10022017.umdl' + model = 'app/snowboy/xiaobai.pmdl' # SnowBoy唤醒引擎实体 snowboy = SnowBoy(model) diff --git a/sdk/interface/alerts.py b/sdk/interface/alerts.py index 5a2df17..0d09dbd 100644 --- a/sdk/interface/alerts.py +++ b/sdk/interface/alerts.py @@ -28,8 +28,8 @@ def __init__(self, dueros, player): self.dueros = dueros self.player = player - self.player.add_callback('eos', self.stop) - self.player.add_callback('error', self.stop) + #self.player.add_callback('eos', self.stop) + #self.player.add_callback('error', self.stop) alarm = os.path.realpath(os.path.join(os.path.dirname(__file__), '../resources/alarm.wav')) self.alarm_uri = 'file://{}'.format(alarm) diff --git a/sdk/interface/audio_player.py b/sdk/interface/audio_player.py index 54aa762..9732146 100644 --- a/sdk/interface/audio_player.py +++ b/sdk/interface/audio_player.py @@ -9,6 +9,15 @@ import tempfile import uuid +ProcessMessageCallbackTypePlaybackStarted = 2005 +ProcessMessageCallbackTypePlaybackStopped = 2006 +ProcessMessageCallbackTypePlaybackNearlyFinished = 2007 +ProcessMessageCallbackTypePlaybackFinished = 2008 +ProcessMessageCallbackTypeProgressReportIntervalElapsed = 2009 +ProcessMessageCallbackTypeStartPlayTime = 2010 + +ProcessMessageCallbackStatusTypeStart = 3000 +ProcessMessageCallbackStatusTypeStop = 3001 class AudioPlayer(object): ''' @@ -16,6 +25,7 @@ class AudioPlayer(object): ''' STATES = {'IDLE', 'PLAYING', 'STOPPED', 'PAUSED', 'BUFFER_UNDERRUN', 'FINISHED'} + def __init__(self, dueros, player): ''' 类初始化 @@ -28,8 +38,15 @@ def __init__(self, dueros, player): self.state = 'IDLE' self.player = player - self.player.add_callback('eos', self.__playback_finished) - self.player.add_callback('error', self.__playback_failed) + self.player.add_callback(ProcessMessageCallbackTypePlaybackStarted, self.__playback_started()) + self.player.add_callback(ProcessMessageCallbackTypePlaybackFinished, self.__playback_finished()) + self.player.add_callback(ProcessMessageCallbackTypePlaybackNearlyFinished, self.__playback_nearly_finished()) + self.player.add_callback(ProcessMessageCallbackTypeProgressReportIntervalElapsed, self.__progress_report_interval_elapsed()) + self.player.add_callback(ProcessMessageCallbackTypeStartPlayTime, self.__playback_default()) + self.player.add_callback(ProcessMessageCallbackTypePlaybackStopped, self.__playback_stopped()) + + self.player.add_callback(ProcessMessageCallbackStatusTypeStart, self.__playback_default()) + self.player.add_callback(ProcessMessageCallbackStatusTypeStop, self.__playback_default()) # { # "directive": { @@ -117,7 +134,8 @@ def clear_queue(self, directive): self.player.stop() elif behavior == 'CLEAR_ENQUEUED': pass - + def __playback_default(self): + print "staus changed from external player process" def __playback_started(self): ''' 开始播放状态上报 diff --git a/sdk/interface/speech_synthesizer.py b/sdk/interface/speech_synthesizer.py index 03de7a1..50fd77c 100644 --- a/sdk/interface/speech_synthesizer.py +++ b/sdk/interface/speech_synthesizer.py @@ -7,7 +7,7 @@ import tempfile import threading import uuid - +from app.framework.player.default_player.player import Player class SpeechSynthesizer(object): ''' @@ -26,8 +26,8 @@ def __init__(self, dueros, player): self.token = '' self.state = 'FINISHED' self.finished = threading.Event() - - self.player = player + default_player = Player() + self.player = default_player self.player.add_callback('eos', self.__speech_finished) self.player.add_callback('error', self.__speech_finished)