Mercurial > code > home > repos > homeauto
view service/announce/announce.py @ 732:fdddbdaf07b5
more service renaming; start a lot more serv.n3 job files
Ignore-this: 635aaefc7bd2fa5558eefb8b3fc9ec75
author | drewp@bigasterisk.com |
---|---|
date | Thu, 06 Feb 2020 16:36:35 -0800 |
parents | 74688c4763fe |
children |
line wrap: on
line source
""" run TTS and send speech or other sounds to playSound and to chromecasts """ import subprocess, time, re from docopt import docopt from lru import LRU from twisted.internet import utils, reactor from twisted.internet.defer import inlineCallbacks from urllib.parse import urlencode import cyclone.web import treq from standardservice.logsetup import log, verboseLogging recentFiles = LRU(50) class Index(cyclone.web.RequestHandler): def get(self): self.render('index.html') class PostAnnouncement(cyclone.web.RequestHandler): @inlineCallbacks def post(self): text = self.get_argument('text') evType = self.get_argument('evType', default=None) if evType is not None: text = f'<prosody rate="-10%" pitch="+30%">{evType}!</prosody>' + text url = yield tts(text) yield treq.post(r'http://dash:9049/playSound', params={b'uri': url}) #chromecastPlay('10.2.0.60', url) # ari #chromecastPlay('10.2.0.61', url) # bed #chromecastPlay('10.2.0.62', url) # asher return url @inlineCallbacks def chromecastPlay(ip, url, volume=None): cmdPrefix = ['/opt/cast', '--timeout', '3s', '--host', ip] if volume is not None: m = re.search(r'Volume: [\.0-9]+', subprocess.check_output(cmdPrefix + ['status'])) oldVolume = float(m.group(1)) subprocess.check_output(cmdPrefix + ['volume', str(volume)]) output = yield utils.getProcessValue( cmdPrefix[0], args=cmdPrefix[1:] + [ 'media', 'play', url.decode('utf8')]) print('cast out', output) if volume is not None: subprocess.check_call(cmdPrefix + ['volume', str(oldVolume)]) class Data(cyclone.web.RequestHandler): def get(self, which): print('getting ', which) self.set_header('Content-Type', 'audio/wav') self.write(recentFiles[which]) @inlineCallbacks def tts(input_xml, affect='surprise', ptype='disagree'): mary_host = "172.17.0.1" mary_port = "59125" maryxml = f'''<?xml version="1.0" encoding="UTF-8" ?> <maryxml version="0.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns=" http://mary.dfki.de/2002/MaryXML" xml:lang="en-US"> <p> {input_xml} </p> </maryxml>''' query_hash = {"INPUT_TEXT": maryxml, "INPUT_TYPE": "RAWMARYXML", "LOCALE": "en_US", "VOICE": "cmu-slt-hsmm", "OUTPUT_TYPE": "AUDIO", "AUDIO": "WAVE", } query = urlencode(query_hash).replace('+', '%20') resp = yield treq.post( "http://%s:%s/process?" % (mary_host, mary_port) + query) wav = yield treq.content(resp) which = '%.1f' % time.time() recentFiles[which] = wav url = f'http://10.2.0.1:9010/data/{which}' print('save', len(wav), 'bytes at', url) return url.encode('ascii') if __name__ == '__main__': arg = docopt(''' Usage: announce.py [options] -v Verbose ''') verboseLogging(arg['-v']) reactor.listenTCP(9010, cyclone.web.Application(handlers=[ (r'/', Index), (r'/announcement', PostAnnouncement), (r'/data/(.*)', Data), ], template_path='.')) reactor.run()