Change playback code to not buffer

This commit is contained in:
Ruben van de Ven 2019-11-13 11:19:21 +01:00
parent 76ad34be99
commit ab60d7a1cf
2 changed files with 79 additions and 57 deletions

View File

@ -14,6 +14,8 @@ from hugvey.communication import LOG_BS
import os
import collections
import math
import urllib.request
import io
try:
import alsaaudio
@ -258,29 +260,34 @@ class CommandHandler(object):
# self.showMyself() # queue message for connection request
def handle(self, cmd):
print('handle', cmd)
# self.sendMessage({'reply':'test'})
if not 'action' in cmd:
logger.critical("Invalid command: {}".format(cmd))
return
try:
logger.info("Received {}".format(cmd))
print('handle', cmd)
# self.sendMessage({'reply':'test'})
if not 'action' in cmd:
logger.critical("Invalid command: {}".format(cmd))
return
if cmd['action'] == 'show_yourself':
self.showMyself()
if cmd['action'] == 'prepare':
self.muteMic = True
if cmd['action'] == 'play':
self.cmdPlay(cmd)
if cmd['action'] == 'stop':
self.cmdStop(cmd['id'])
logger.info("Received {}".format(cmd))
if cmd['action'] == 'show_yourself':
self.showMyself()
if cmd['action'] == 'prepare':
self.muteMic = True
if cmd['action'] == 'play':
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):
self.muteMic = True
msgId = cmd['id']
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
params = cmd['params'] if 'params' in cmd else {}
# use duration for timing the popen duration (and redo it if needed)
@ -292,49 +299,63 @@ class CommandHandler(object):
self.playPopen.kill()
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))
else:
if file is not None:
logger.info("Play: {}".format(file))
file = self.file_address + "/" + file
# logger.debug(['play', file])
playCmd = ['play', file]
if filepath is not None:
file = self.file_address + "/" + filepath
logger.debug("Fetch to play: {}".format(filepath))
start = time.time()
#: 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():
if not value:
continue
playCmd.append(param)
print(param, value)
if value is True:
continue
playCmd.append(str(value))
environment_vars = dict(os.environ)
if self.play_audiodriver is not None:
environment_vars['AUDIODRIVER'] = self.play_audiodriver
elif self.play_audiodev is not None:
environment_vars['AUDIODEV'] = self.play_audiodev
# logger.debug(['play', file])
playCmd = ['play', '-']
logger.debug(playCmd)
for param, value in params.items():
if not value:
continue
playCmd.append(param)
print(param, value)
if value is True:
continue
playCmd.append(str(value))
environment_vars = dict(os.environ)
if self.play_audiodriver is not None:
environment_vars['AUDIODRIVER'] = self.play_audiodriver
elif self.play_audiodev is not None:
environment_vars['AUDIODEV'] = self.play_audiodev
t = None
if duration is not None:
t = threading.Timer(duration+3, self.checkPopen, (msgId,duration+3))
t.start()
logger.debug(playCmd)
self.playPopen = subprocess.Popen(
playCmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environment_vars)
self.sendMessage({
'event': 'playbackStart',
'msgId': msgId
})
out, err = self.playPopen.communicate()
returnCode = self.playPopen.returncode if self.playPopen else 0
logger.debug('finished')
self.playPopen = None
t = None
if duration is not None:
t = threading.Timer(duration+3, self.checkPopen, (msgId,duration+3))
t.start()
if t is not None:
t.cancel()
self.playPopen = subprocess.Popen(
playCmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environment_vars)
self.sendMessage({
'event': 'playbackStart',
'msgId': msgId
})
out, err = self.playPopen.communicate(input=audioFile.getvalue())
playend = time.time()
returnCode = self.playPopen.returncode if self.playPopen else 0
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:
logger.info("Speak: {}".format(text))

View File

@ -48,6 +48,7 @@ if __name__ == '__main__':
host = urlparse(hv.config['events']['cmd_address']).hostname
logger.info("Connect to logger on {}".format(host))
socket_handler = logging.handlers.SocketHandler(host, 19996) # default listening address
# socket_handler.setLevel(logging.DEBUG) # always debug
logger.addHandler(socket_handler);
hv.start()