Change playback code to not buffer
This commit is contained in:
parent
76ad34be99
commit
ab60d7a1cf
2 changed files with 79 additions and 57 deletions
135
hugvey/client.py
135
hugvey/client.py
|
@ -14,6 +14,8 @@ from hugvey.communication import LOG_BS
|
||||||
import os
|
import os
|
||||||
import collections
|
import collections
|
||||||
import math
|
import math
|
||||||
|
import urllib.request
|
||||||
|
import io
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import alsaaudio
|
import alsaaudio
|
||||||
|
@ -258,29 +260,34 @@ class CommandHandler(object):
|
||||||
# self.showMyself() # queue message for connection request
|
# self.showMyself() # queue message for connection request
|
||||||
|
|
||||||
def handle(self, cmd):
|
def handle(self, cmd):
|
||||||
print('handle', cmd)
|
try:
|
||||||
# self.sendMessage({'reply':'test'})
|
|
||||||
if not 'action' in cmd:
|
print('handle', cmd)
|
||||||
logger.critical("Invalid command: {}".format(cmd))
|
# self.sendMessage({'reply':'test'})
|
||||||
return
|
if not 'action' in cmd:
|
||||||
|
logger.critical("Invalid command: {}".format(cmd))
|
||||||
logger.info("Received {}".format(cmd))
|
return
|
||||||
|
|
||||||
if cmd['action'] == 'show_yourself':
|
logger.info("Received {}".format(cmd))
|
||||||
self.showMyself()
|
|
||||||
if cmd['action'] == 'prepare':
|
if cmd['action'] == 'show_yourself':
|
||||||
self.muteMic = True
|
self.showMyself()
|
||||||
if cmd['action'] == 'play':
|
if cmd['action'] == 'prepare':
|
||||||
self.cmdPlay(cmd)
|
self.muteMic = True
|
||||||
if cmd['action'] == 'stop':
|
if cmd['action'] == 'play':
|
||||||
self.cmdStop(cmd['id'])
|
self.cmdPlay(cmd)
|
||||||
|
if cmd['action'] == 'stop':
|
||||||
|
self.cmdStop(cmd['id'])
|
||||||
|
except Exception as e:
|
||||||
|
logger.critical("Exception during handling command: {}".format(cmd))
|
||||||
|
logger.exception(e)
|
||||||
|
|
||||||
def cmdPlay(self, cmd):
|
def cmdPlay(self, cmd):
|
||||||
self.muteMic = True
|
self.muteMic = True
|
||||||
|
|
||||||
msgId = cmd['id']
|
msgId = cmd['id']
|
||||||
pitch = cmd['pitch'] if 'pitch' in cmd else 50
|
pitch = cmd['pitch'] if 'pitch' in cmd else 50
|
||||||
file = cmd['file'] if 'file' in cmd else None
|
filepath = cmd['file'] if 'file' in cmd else None
|
||||||
text = cmd['msg'] if 'msg' in cmd else None
|
text = cmd['msg'] if 'msg' in cmd else None
|
||||||
params = cmd['params'] if 'params' in cmd else {}
|
params = cmd['params'] if 'params' in cmd else {}
|
||||||
# use duration for timing the popen duration (and redo it if needed)
|
# use duration for timing the popen duration (and redo it if needed)
|
||||||
|
@ -292,49 +299,63 @@ class CommandHandler(object):
|
||||||
self.playPopen.kill()
|
self.playPopen.kill()
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
if file is None and text is None:
|
if filepath is None and text is None:
|
||||||
logger.critical("No file nor text given: {}".format(cmd))
|
logger.critical("No file nor text given: {}".format(cmd))
|
||||||
else:
|
else:
|
||||||
if file is not None:
|
if filepath is not None:
|
||||||
logger.info("Play: {}".format(file))
|
file = self.file_address + "/" + filepath
|
||||||
file = self.file_address + "/" + file
|
logger.debug("Fetch to play: {}".format(filepath))
|
||||||
# logger.debug(['play', file])
|
start = time.time()
|
||||||
playCmd = ['play', file]
|
#: var response: http.client.HTTPResponse
|
||||||
|
response = urllib.request.urlopen(file, timeout=4)
|
||||||
|
fetchend = time.time()
|
||||||
|
logger.info("Fetched {} in {}s".format(file, fetchend-start))
|
||||||
|
if fetchend-start > 1:
|
||||||
|
logger.warning("Super slow fetching of {} in {}s".format(file, fetchend-start))
|
||||||
|
if response.getcode() != 200:
|
||||||
|
logger.critical("Error fetching: {} - {}".format(file, response))
|
||||||
|
else:
|
||||||
|
audioFile = io.BytesIO(response.read())
|
||||||
|
logger.info("Play: {}".format(filepath))
|
||||||
|
|
||||||
for param, value in params.items():
|
# logger.debug(['play', file])
|
||||||
if not value:
|
playCmd = ['play', '-']
|
||||||
continue
|
|
||||||
playCmd.append(param)
|
for param, value in params.items():
|
||||||
print(param, value)
|
if not value:
|
||||||
if value is True:
|
continue
|
||||||
continue
|
playCmd.append(param)
|
||||||
playCmd.append(str(value))
|
print(param, value)
|
||||||
environment_vars = dict(os.environ)
|
if value is True:
|
||||||
if self.play_audiodriver is not None:
|
continue
|
||||||
environment_vars['AUDIODRIVER'] = self.play_audiodriver
|
playCmd.append(str(value))
|
||||||
elif self.play_audiodev is not None:
|
environment_vars = dict(os.environ)
|
||||||
environment_vars['AUDIODEV'] = self.play_audiodev
|
if self.play_audiodriver is not None:
|
||||||
|
environment_vars['AUDIODRIVER'] = self.play_audiodriver
|
||||||
logger.debug(playCmd)
|
elif self.play_audiodev is not None:
|
||||||
|
environment_vars['AUDIODEV'] = self.play_audiodev
|
||||||
t = None
|
|
||||||
if duration is not None:
|
logger.debug(playCmd)
|
||||||
t = threading.Timer(duration+3, self.checkPopen, (msgId,duration+3))
|
|
||||||
t.start()
|
t = None
|
||||||
|
if duration is not None:
|
||||||
self.playPopen = subprocess.Popen(
|
t = threading.Timer(duration+3, self.checkPopen, (msgId,duration+3))
|
||||||
playCmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environment_vars)
|
t.start()
|
||||||
self.sendMessage({
|
|
||||||
'event': 'playbackStart',
|
self.playPopen = subprocess.Popen(
|
||||||
'msgId': msgId
|
playCmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environment_vars)
|
||||||
})
|
self.sendMessage({
|
||||||
out, err = self.playPopen.communicate()
|
'event': 'playbackStart',
|
||||||
returnCode = self.playPopen.returncode if self.playPopen else 0
|
'msgId': msgId
|
||||||
logger.debug('finished')
|
})
|
||||||
self.playPopen = None
|
out, err = self.playPopen.communicate(input=audioFile.getvalue())
|
||||||
|
playend = time.time()
|
||||||
if t is not None:
|
returnCode = self.playPopen.returncode if self.playPopen else 0
|
||||||
t.cancel()
|
logger.info('finished playing {} in {:.4f}s (duration: {}s)'.format(filepath, playend-fetchend, duration))
|
||||||
|
self.playPopen = None
|
||||||
|
|
||||||
|
if t is not None:
|
||||||
|
t.cancel()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.info("Speak: {}".format(text))
|
logger.info("Speak: {}".format(text))
|
||||||
|
|
|
@ -48,6 +48,7 @@ if __name__ == '__main__':
|
||||||
host = urlparse(hv.config['events']['cmd_address']).hostname
|
host = urlparse(hv.config['events']['cmd_address']).hostname
|
||||||
logger.info("Connect to logger on {}".format(host))
|
logger.info("Connect to logger on {}".format(host))
|
||||||
socket_handler = logging.handlers.SocketHandler(host, 19996) # default listening address
|
socket_handler = logging.handlers.SocketHandler(host, 19996) # default listening address
|
||||||
|
# socket_handler.setLevel(logging.DEBUG) # always debug
|
||||||
logger.addHandler(socket_handler);
|
logger.addHandler(socket_handler);
|
||||||
|
|
||||||
hv.start()
|
hv.start()
|
||||||
|
|
Loading…
Reference in a new issue