Mercurial > code > home > repos > homeauto
annotate service/speechMusic/speechMusic.py @ 359:b3959142d7d8
move speech_music into docker and into pygame
Ignore-this: 15260aecbf7fddb75e641b7a853b0281
author | drewp@bigasterisk.com |
---|---|
date | Sun, 09 Sep 2018 04:00:09 -0700 |
parents | 1e94d074f642 |
children | 9fd92202c886 |
rev | line source |
---|---|
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
1 #!bin/python |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
2 """ |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
3 play sounds according to POST requests. |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
4 """ |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
5 from __future__ import division |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
6 import sys, tempfile |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
7 from pyjade.ext.mako import preprocessor as mako_preprocessor |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
8 from mako.lookup import TemplateLookup |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
9 from twisted.internet import reactor |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
10 sys.path.append("/opt") |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
11 from generator import tts |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
12 import xml.etree.ElementTree as ET |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
13 from klein import Klein |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
14 from twisted.web.static import File |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
15 from logsetup import log |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
16 import pygame.mixer |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
17 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
18 templates = TemplateLookup(directories=['.'], |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
19 preprocessor=mako_preprocessor, |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
20 filesystem_checks=True) |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
21 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
22 def makeSpeech(speech, fast=False): |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
23 speechWav = tempfile.NamedTemporaryFile(suffix='.wav') |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
24 |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
25 root = ET.Element("SABLE") |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
26 r = ET.SubElement(root, "RATE", |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
27 attrib=dict(SPEED="+50%" if fast else "+0%")) |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
28 for sentence in speech.split('.'): |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
29 div = ET.SubElement(r, "DIV") |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
30 div.set("TYPE", "sentence") |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
31 div.text = sentence |
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
32 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
33 speechSecs = tts(root, speechWav.name) |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
34 return pygame.mixer.Sound(speechWav.name), speechSecs |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
35 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
36 class SoundEffects(object): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
37 def __init__(self): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
38 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
39 # also '/my/music/entrance/%s.wav' then speak "Neew %s. %s" % (sensorWords[data['sensor']], data['name']), |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
40 |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
41 log.info("loading") |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
42 self.buffers = { |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
43 'leave': pygame.mixer.Sound('sound/leave.wav'), |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
44 'highlight' : pygame.mixer.Sound('sound/KDE-Im-Highlight-Msg-44100.wav'), |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
45 'question' : pygame.mixer.Sound('sound/angel_question.wav'), |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
46 'jazztrumpet': pygame.mixer.Sound('sound/acid-jazz-trumpet-11.wav'), |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
47 'troyandabed': pygame.mixer.Sound('sound/troy_and_abed_in_the_morning.wav'), |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
48 'beep1': pygame.mixer.Sound('sound/beep1.wav'), |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
49 'beep2': pygame.mixer.Sound('sound/beep2.wav'), |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
50 } |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
51 log.info("loaded sounds") |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
52 self.playingSources = [] |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
53 self.queued = [] |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
54 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
55 def playEffect(self, name): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
56 return self.playBuffer(self.buffers[name]) |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
57 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
58 def playSpeech(self, txt, preEffect=None, postEffect=None, preEffectOverlap=0): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
59 buf, secs = makeSpeech(txt) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
60 t = 0 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
61 if preEffect: |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
62 t += self.playEffect(preEffect) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
63 t -= preEffectOverlap |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
64 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
65 reactor.callLater(t, self.playBuffer, buf) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
66 t += secs |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
67 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
68 if postEffect: |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
69 self.playBufferLater(t, self.buffers[postEffect]) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
70 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
71 def playBufferLater(self, t, buf): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
72 self.queued.append(reactor.callLater(t, self.playBuffer, buf)) |
8
5ed239235b69
speechMusic: don't fail on missing 'name' attr
drewp@bigasterisk.com
parents:
4
diff
changeset
|
73 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
74 def playBuffer(self, buf): |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
75 buf.play() |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
76 |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
77 secs = buf.get_length() |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
78 self.playingSources.append(buf) |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
79 reactor.callLater(secs + .1, self.done, buf) |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
80 return secs |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
81 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
82 def done(self, src): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
83 try: |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
84 self.playingSources.remove(src) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
85 except ValueError: |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
86 pass |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
87 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
88 def stopAll(self): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
89 while self.playingSources: |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
90 self.playingSources.pop().stop() |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
91 for q in self.queued: |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
92 q.cancel() |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
93 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
94 class Server(object): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
95 app = Klein() |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
96 def __init__(self, sfx): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
97 self.sfx = sfx |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
98 |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
99 @app.route('/static/', branch=True) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
100 def static(self, request): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
101 return File("./static") |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
102 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
103 @app.route('/', methods=['GET']) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
104 def index(self, request): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
105 t = templates.get_template("index.jade") |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
106 return t.render(effectNames=[ |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
107 dict(name=k, postUri='effects/%s' % k) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
108 for k in self.sfx.buffers.keys()]) |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
109 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
110 @app.route('/speak', methods=['POST']) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
111 def speak(self, request): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
112 self.sfx.playSpeech(request.args['msg'][0]) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
113 return "ok" |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
114 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
115 @app.route('/effects/<string:name>', methods=['POST']) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
116 def effect(self, request, name): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
117 self.sfx.playEffect(name) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
118 return "ok" |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
119 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
120 @app.route('/stopAll', methods=['POST']) |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
121 def stopAll(self, request): |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
122 self.sfx.stopAll() |
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
123 return "ok" |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
124 |
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
125 pygame.mixer.init() |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
126 sfx = SoundEffects() |
4
be855a111619
move a bunch of services into this tree, give them all web status pages
drewp@bigasterisk.com
parents:
diff
changeset
|
127 |
75
1132ab1ade80
big rewrite of speechMusic to use klein and openal
drewp@bigasterisk.com
parents:
36
diff
changeset
|
128 server = Server(sfx) |
359
b3959142d7d8
move speech_music into docker and into pygame
drewp@bigasterisk.com
parents:
215
diff
changeset
|
129 server.app.run(endpoint_description=r"tcp6:port=9049:interface=\:\:") |