Basic speaking interaction now working with google + espeak

This commit is contained in:
Ruben van de Ven 2019-01-18 15:40:43 +01:00
parent 13b61225d7
commit 30b2f9e8af
5 changed files with 53 additions and 29 deletions

1
.gitignore vendored
View file

@ -2,4 +2,5 @@ venv
*.pyc *.pyc
.project .project
.pydevproject .pydevproject
venv3

View file

@ -56,7 +56,21 @@ class CentralCommand(object):
""" """
prepare command to be picked up by the sender prepare command to be picked up by the sender
""" """
if threading.current_thread().getName() != 'MainThread':
# Threading nightmares! Adding to queue from other thread/loop (not sure which is the isse)
# won't trigger asyncios queue.get() so we have to do this thread safe, in the right loop
self.loop.call_soon_threadsafe( self._queueCommand, hv_id, msg )
else:
self._queueCommand(hv_id, msg)
def _queueCommand(self, hv_id, msg):
self.commandQueue.put_nowait((hv_id, msg)) self.commandQueue.put_nowait((hv_id, msg))
# if msg['action'] == 'play':
# self.commandQueue.put_nowait((hv_id, {
# 'action': 'play',
# 'msg': "This is an interrption",
# 'id': 'test',
# }))
def commandAllHugveys(self, msg): def commandAllHugveys(self, msg):
for hv_id in self.hugvey_ids: for hv_id in self.hugvey_ids:
@ -70,7 +84,6 @@ class CentralCommand(object):
s = self.ctx.socket(zmq.PUB) s = self.ctx.socket(zmq.PUB)
s.bind(self.config['events']['cmd_address']) s.bind(self.config['events']['cmd_address'])
self.commandAllHugveys({'action': 'show_yourself'}) self.commandAllHugveys({'action': 'show_yourself'})
# sleep to allow pending connections to connect # sleep to allow pending connections to connect
@ -80,8 +93,10 @@ class CentralCommand(object):
while self.isRunning.is_set(): while self.isRunning.is_set():
hv_id, cmd = await self.commandQueue.get() hv_id, cmd = await self.commandQueue.get()
logger.info('Got command to send: {} {}'.format(hv_id, cmd))
zmqSend(s, hv_id, cmd) zmqSend(s, hv_id, cmd)
logger.warn('Stopping command sender')
s.close() s.close()
async def instantiateHugvey(self, hugvey_id, msg): async def instantiateHugvey(self, hugvey_id, msg):

View file

@ -1,14 +1,18 @@
import pyaudio import asyncio
import socket
import audioop import audioop
import logging import logging
import time import pyaudio
import zmq
import asyncio
from zmq.asyncio import Context
import yaml
import re import re
import socket
import threading
import time
import yaml
import zmq
from zmq.asyncio import Context
from .communication import zmqReceive, zmqSend, getTopic from .communication import zmqReceive, zmqSend, getTopic
import subprocess
logger = logging.getLogger("client") logger = logging.getLogger("client")
@ -83,22 +87,11 @@ class VoiceServer(object):
try: try:
address = "tcp://*:{}".format(self.voice_port) address = "tcp://*:{}".format(self.voice_port)
self.voice_socket = self.ctx.socket(zmq.PUB) self.voice_socket = self.ctx.socket(zmq.PUB)
# self.voice_socket.setsockopt(zmq.CONFLATE, 1)
self.voice_socket.bind(address) self.voice_socket.bind(address)
# self.voice_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# self.voice_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# address = ('', self.voice_port)
# self.voice_socket.bind(address)
# self.voice_socket.listen(5)
# read_list = [self.voice_socket]
logger.info( "Waiting for voice connections on {}".format(address) ) logger.info( "Waiting for voice connections on {}".format(address) )
while not self.stopped: while not self.stopped:
await asyncio.sleep(1) await asyncio.sleep(1)
# (clientsocket, address) = self.voice_socket.accept()
# logger.info( "Got voice connection from {}".format(address))
# self.clients.append(clientsocket)
logger.info( "Stop recording & streaming") logger.info( "Stop recording & streaming")
self.voice_socket.close() self.voice_socket.close()
@ -117,7 +110,6 @@ class VoiceServer(object):
async def asyncStart(self, loop): async def asyncStart(self, loop):
future = loop.run_in_executor(None, self.start) future = loop.run_in_executor(None, self.start)
r = await future r = await future
# await self.start()
class CommandHandler(object): class CommandHandler(object):
def __init__(self, hugvey_id, cmd_address = "tcp://127.0.0.1:5555", publish_address = "tcp://0.0.0.0:5555"): def __init__(self, hugvey_id, cmd_address = "tcp://127.0.0.1:5555", publish_address = "tcp://0.0.0.0:5555"):
@ -126,9 +118,11 @@ class CommandHandler(object):
self.hugvey_id = hugvey_id self.hugvey_id = hugvey_id
self.cmd_address = cmd_address self.cmd_address = cmd_address
self.publish_address = publish_address self.publish_address = publish_address
self.playPopen = None
# 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)
# self.sendMessage({'reply':'test'}) # self.sendMessage({'reply':'test'})
if not 'action' in cmd: if not 'action' in cmd:
logger.critical("Invalid command: {}".format(cmd)) logger.critical("Invalid command: {}".format(cmd))
@ -141,16 +135,30 @@ class CommandHandler(object):
self.cmdPlay(cmd['id'], cmd['msg']) self.cmdPlay(cmd['id'], cmd['msg'])
def cmdPlay(self, msgId, msgText): def cmdPlay(self, msgId, msgText, pitch=50):
# espeak(msgText)
# TODO kill if playing & play wave file
# preferably a cat (local)/curl (remote) pipe into player
logger.info("Play: {}".format(msgText)) logger.info("Play: {}".format(msgText))
time.sleep(2) self.playPopen = subprocess.Popen(['espeak', '-p','{0}'.format(pitch), msgText], stdout=subprocess.PIPE)
returnCode = self.playPopen.wait()
self.playPopen = None
if returnCode:
logger.warn("Had returncode on play: {}".format(returnCode))
else:
logger.debug("Finished playback. Return code: {}".format(returnCode))
self.sendMessage({ self.sendMessage({
'event': 'playbackFinish', 'event': 'playbackFinish',
'msgId': msgId 'msgId': msgId
}) })
def cmdStop(self, msgId):
if self.playPopen:
logger.info("Interrupting playback")
try:
self.playPopen.terminate()
except Exception as e:
logger.critical("Could not stop playback: {}".format(e))
def showMyself(self): def showMyself(self):
"""Publish about this hugvey to central command """Publish about this hugvey to central command
@ -180,7 +188,9 @@ class CommandHandler(object):
logger.info("Subscribed to commands for {} on {}".format(topic, self.cmd_address)) logger.info("Subscribed to commands for {} on {}".format(topic, self.cmd_address))
while True: while True:
hugvey_id, cmd = await zmqReceive(s) hugvey_id, cmd = await zmqReceive(s)
self.handle(cmd) # print("GOGOG", hugvey_id, cmd)
t = threading.Thread(target=self.handle, args=(cmd,))
t.start()
# topic, msg = await s.recv_multipart() # topic, msg = await s.recv_multipart()
# print('received', msg, time.time()) # print('received', msg, time.time())
s.close() s.close()

View file

@ -2,5 +2,4 @@ pyzmq
pyaudio pyaudio
coloredlogs coloredlogs
pyyaml pyyaml
audioop google-cloud-speech
google-cloud-speech

View file

@ -2,4 +2,3 @@ pyzmq
pyaudio pyaudio
coloredlogs coloredlogs
pyyaml pyyaml
audioop