Skip to content

Commit

Permalink
feat: 为音频播放增加一个子线程队列, 去除wait参数(#208); 不二次判断Unit的意图(#200)
Browse files Browse the repository at this point in the history
  • Loading branch information
wzpan committed Mar 18, 2023
1 parent 7717d84 commit c59ce14
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 68 deletions.
2 changes: 1 addition & 1 deletion plugins/Echo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# author: wzpan
# 写诗
# 回声

import logging
from robot.sdk.AbstractPlugin import AbstractPlugin
Expand Down
2 changes: 1 addition & 1 deletion plugins/LocalPlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def handle(self, text, parsed):
self.player.stop()
self.clearImmersive() # 去掉沉浸式
else:
self.say("没听懂你的意思呢,要停止播放,请说停止播放", wait=True)
self.say("没听懂你的意思呢,要停止播放,请说停止播放")
self.player.resume()

def pause(self):
Expand Down
24 changes: 1 addition & 23 deletions robot/AI.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,30 +100,8 @@ def chat(self, texts, parsed):
"""
msg = "".join(texts)
msg = utils.stripPunctuation(msg)
intents = [
"USER_AQI",
"USER_CLOTHES",
"USER_CLOUDY",
"USER_EXERCISE",
"USER_FOG",
"USER_HIGH_TEMP",
"USER_INFLUENZA",
"USER_LOW_TEMP",
"USER_RAIN",
"USER_SNOW",
"USER_SUNNY",
"USER_TEMP",
"USER_TRIP",
"USER_ULTRAVIOLET",
"USER_WASH_CAR",
"USER_WEATHER",
"USER_WIND",
]
try:
for intent in intents:
if unit.hasIntent(parsed, intent):
return unit.getSay(parsed, intent)
return unit.getSay(parsed, "BUILT_CHAT")
return unit.getSay(parsed)
except Exception:
logger.critical("UNIT robot failed to response for %r", msg, exc_info=True)
return "抱歉, 百度UNIT服务回答失败"
Expand Down
29 changes: 12 additions & 17 deletions robot/Conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@
import io
import re
import os

from snowboy import snowboydecoder

from robot.LifeCycleHandler import LifeCycleHandler
from robot.Brain import Brain
from robot.sdk import LED, MessageBuffer
from snowboy import snowboydecoder
from robot.sdk import MessageBuffer
from robot import (
logging,
ASR,
TTS,
NLU,
AI,
Player,
ASR,
config,
constants,
utils,
logging,
NLU,
Player,
statistic,
TTS,
utils
)


Expand All @@ -29,13 +31,8 @@

class Conversation(object):
def __init__(self, profiling=False):
self.brain = None
self.asr = None
self.ai = None
self.tts = None
self.nlu = None
self.brain, self.asr, self.ai, self.tts, self.nlu, self.player = None, None, None, None, None, None
self.reInit()
self.player = None
self.brain = Brain(self)
self.brain.printPlugins()
# 历史会话消息
Expand Down Expand Up @@ -218,7 +215,6 @@ def say(
cache=False,
plugin="",
onCompleted=None,
wait=False,
append_history=True,
):
"""
Expand All @@ -227,7 +223,6 @@ def say(
:param cache: 是否缓存这句话的音频
:param plugin: 来自哪个插件的消息(将带上插件的说明)
:param onCompleted: 完成的回调
:param wait: 是否要等待说完(为True将阻塞主线程直至说完这句话)
:param append_history: 是否要追加到聊天记录
"""
append_history and self.appendHistory(1, msg, plugin=plugin)
Expand Down Expand Up @@ -290,7 +285,7 @@ def say(
self.player.preappendCompleted(
lambda: self.say("后面的内容太长了,我就不念了", append_history=False)
)
self.player.play(voice, not cache, onCompleted, wait)
self.player.play(voice, not cache, onCompleted)
utils.lruCache() # 清理缓存

def activeListen(self, silent=False):
Expand Down
6 changes: 3 additions & 3 deletions robot/LifeCycleHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ def _muse_loop_event(self):
self._conversation.doResponse(query)
self._wakeup.clear()

def _beep_hi(self, onCompleted=None, wait=False):
Player.play(constants.getData("beep_hi.wav"), onCompleted, wait)
def _beep_hi(self, onCompleted=None):
Player.play(constants.getData("beep_hi.wav"), onCompleted)

def _beep_lo(self):
Player.play(constants.getData("beep_lo.wav"))
Expand All @@ -137,7 +137,7 @@ def onWakeup(self, onCompleted=None):
唤醒并进入录音的状态
"""
logger.info("onWakeup")
self._beep_hi(onCompleted=onCompleted, wait=onCompleted)
self._beep_hi(onCompleted=onCompleted)
if config.get("/LED/enable", False):
LED.wakeup()
self._unihiker and self._unihiker.record(1, "我正在聆听...")
Expand Down
53 changes: 31 additions & 22 deletions robot/Player.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import os
import platform
import signal
from . import utils
import _thread as thread
import queue
import threading
from robot import logging
from ctypes import CFUNCTYPE, c_char_p, c_int, cdll
from contextlib import contextmanager

from . import utils

logger = logging.getLogger(__name__)


Expand All @@ -20,7 +22,6 @@ def py_error_handler(filename, line, function, err, fmt):

c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)


@contextmanager
def no_alsa_error():
try:
Expand All @@ -33,9 +34,9 @@ def no_alsa_error():
pass


def play(fname, onCompleted=None, wait=False):
def play(fname, onCompleted=None):
player = getPlayerByFileName(fname)
player.play(fname, onCompleted=onCompleted, wait=wait)
player.play(fname, onCompleted=onCompleted)


def getPlayerByFileName(fname):
Expand Down Expand Up @@ -70,13 +71,25 @@ def __init__(self, **kwargs):
self.proc = None
self.delete = False
self.onCompleteds = []

def doPlay(self):
self.play_queue = queue.Queue() # 播放队列
self.consumer_thread = threading.Thread(target=self.playLoop)
self.consumer_thread.start()

def playLoop(self):
while True:
src = self.play_queue.get()
if src:
logger.info(f"开始播放音频:{src}")
self.src = src
self.doPlay(src)
self.play_queue.task_done()

def doPlay(self, src):
system = platform.system()
if system == "Darwin":
cmd = ["afplay", str(self.src)]
cmd = ["afplay", str(src)]
else:
cmd = ["play", str(self.src)]
cmd = ["play", str(src)]
logger.debug("Executing %s", " ".join(cmd))
self.proc = subprocess.Popen(
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
Expand All @@ -85,21 +98,17 @@ def doPlay(self):
self.proc.wait()
self.playing = False
if self.delete:
utils.check_and_delete(self.src)
utils.check_and_delete(src)
logger.debug("play completed")
if self.proc and self.proc.returncode == 0:
for onCompleted in self.onCompleteds:
onCompleted and onCompleted()

def play(self, src, delete=False, onCompleted=None, wait=False):
def play(self, src, delete=False, onCompleted=None):
if src and (os.path.exists(src) or src.startswith("http")):
self.src = src
self.delete = delete
onCompleted and self.onCompleteds.append(onCompleted)
if not wait:
thread.start_new_thread(self.doPlay, ())
else:
self.doPlay()
self.play_queue.put(src)
else:
logger.critical(f"path not exists: {src}", stack_info=True)

Expand Down Expand Up @@ -206,7 +215,7 @@ def turnUp(self):
volume += 20
if volume >= 100:
volume = 100
self.plugin.say("音量已经最大啦", wait=True)
self.plugin.say("音量已经最大啦")
subprocess.run(["osascript", "-e", f"set volume output volume {volume}"])
elif system == "Linux":
res = subprocess.run(
Expand All @@ -220,12 +229,12 @@ def turnUp(self):
volume += 20
if volume >= 100:
volume = 100
self.plugin.say("音量已经最大啦", wait=True)
self.plugin.say("音量已经最大啦")
subprocess.run(["amixer", "set", "Master", f"{volume}%"])
else:
subprocess.run(["amixer", "set", "Master", "20%+"])
else:
self.plugin.say("当前系统不支持调节音量", wait=True)
self.plugin.say("当前系统不支持调节音量")
self.resume()

def turnDown(self):
Expand All @@ -241,7 +250,7 @@ def turnDown(self):
volume -= 20
if volume <= 20:
volume = 20
self.plugin.say("音量已经很小啦", wait=True)
self.plugin.say("音量已经很小啦")
subprocess.run(["osascript", "-e", f"set volume output volume {volume}"])
elif system == "Linux":
res = subprocess.run(
Expand All @@ -255,10 +264,10 @@ def turnDown(self):
volume -= 20
if volume <= 20:
volume = 20
self.plugin.say("音量已经最小啦", wait=True)
self.plugin.say("音量已经最小啦")
subprocess.run(["amixer", "set", "Master", f"{volume}%"])
else:
subprocess.run(["amixer", "set", "Master", "20%-"])
else:
self.plugin.say("当前系统不支持调节音量", wait=True)
self.plugin.say("当前系统不支持调节音量")
self.resume()
18 changes: 17 additions & 1 deletion robot/sdk/AbstractPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,27 @@ def __init__(self, con):
self.nlu = self.con.nlu

def play(self, src, delete=False, onCompleted=None, volume=1):
"""
播放音频
:param play: 要播放的音频地址
:param delete: 播放完成是否要删除,默认不删除
:param onCompleted: 播放完后的回调
:param volume: 音量
"""
self.con.play(src, delete, onCompleted, volume)

def say(self, text, cache=False, onCompleted=None, wait=False):
"""
使用TTS说一句话
:param text: 要说话的内容
:param cache: 是否要缓存该音频,默认不缓存
:param onCompleted: 播放完后的回调
:param wait: 已废弃
"""
self.con.say(
text, cache=cache, plugin=self.SLUG, onCompleted=onCompleted, wait=wait
text, cache=cache, plugin=self.SLUG, onCompleted=onCompleted
)

def activeListen(self, silent=False):
Expand Down

0 comments on commit c59ce14

Please sign in to comment.