-
Notifications
You must be signed in to change notification settings - Fork 4
/
manage.py
140 lines (124 loc) · 4.52 KB
/
manage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""
usage: go.py <command>
commands:
runserver - run web server on 127.0.0.1 port %(port)s
build - build all generated content
clean - remove all generated content
"""
from wsgiref.simple_server import make_server
from wsgiref.util import FileWrapper
import os
import sys
import mimetypes
import wave
import subprocess
import hashlib
import json
ROOT = os.path.abspath(os.path.dirname(__file__))
path = lambda *x: os.path.join(ROOT, *x)
port = 8020
htmlpath = path('static-files', 'script.html')
oggpath = path('static-files', 'script.ogg')
jsonpath = path('static-files', 'script.json')
def say(words, filename, voice='Alex'):
null = open('/dev/null', 'w')
finalwav = path('final.wav')
out = wave.open(finalwav, 'w')
nchannels = 1
sampwidth = 2
framerate = 22050
comptype = 'NONE'
compname = 'not compressed'
out.setparams((nchannels, sampwidth, framerate, 0, comptype, compname))
durations = []
tmpwave = path('tmp.wave')
tmpwav = path('tmp.wav')
for word in words:
if isinstance(word, basestring):
subprocess.check_call(['say', '-v', voice, '-o', tmpwave, word])
subprocess.check_call(['ffmpeg', '-y', '-i', tmpwave, tmpwav],
stdout=null, stderr=subprocess.STDOUT)
inp = wave.open(tmpwav, 'r')
durations.append(float(inp.getnframes()) / framerate)
out.writeframes(inp.readframes(inp.getnframes()))
inp.close()
for tmpfilename in [tmpwave, tmpwav]:
os.unlink(tmpfilename)
elif isinstance(word, (int, float)):
out.writeframes('\0' * (sampwidth * int(word * framerate)))
durations.append(float(word))
else:
raise ValueError('unexpected: %s' % word)
out.close()
subprocess.check_call(['ffmpeg', '-y', '-i', finalwav,
'-acodec', 'libvorbis', '-aq', '1', filename],
stdout=null, stderr=subprocess.STDOUT)
os.unlink(finalwav)
null.close()
return durations
def build():
print "generating script.ogg and script.json from script.html."
script = open(htmlpath, 'r')
speak = []
for line in script:
line = line.strip()
if line and not line.startswith('<'):
speak.append(line)
speak.append(0.5)
speakhash = hashlib.sha1(json.dumps(speak)).hexdigest()
if os.path.exists(jsonpath) and os.path.exists(oggpath):
oldmetadata = json.load(open(jsonpath, 'r'))
if oldmetadata['speakhash'] == speakhash:
print "done (no changes needed)."
return
metadata = dict(speakhash=speakhash, durations=say(speak, oggpath))
json.dump(metadata, open(jsonpath, 'w'))
print "done."
def make_app():
def app(environ, start_response):
origpath = environ['PATH_INFO']
if origpath.endswith('/'):
origpath = '%sindex.html' % origpath
fileparts = origpath[1:].split('/')
fullpath = path('static-files', *fileparts)
fullpath = os.path.normpath(fullpath)
(mimetype, encoding) = mimetypes.guess_type(fullpath)
if fullpath in [jsonpath, oggpath]:
build()
if (fullpath.startswith(ROOT) and
not '.git' in fullpath and
os.path.isfile(fullpath) and
mimetype):
filesize = os.stat(fullpath).st_size
start_response('200 OK', [('Content-Type', mimetype),
('Content-Length', str(filesize)),
('Accept-Ranges', 'bytes')])
return FileWrapper(open(fullpath, 'rb'))
start_response('404 Not Found', [('Content-Type', 'text/plain')])
return ['Not Found: ', origpath]
return app
def serve(ip=''):
ipstr = ip
if not ipstr:
ipstr = 'all IP interfaces'
server = make_server(ip, port, make_app())
print "serving on %s port %d" % (ipstr, port)
server.serve_forever()
if __name__ == "__main__":
if len(sys.argv) < 2:
print __doc__ % globals()
sys.exit(1)
cmd = sys.argv[1]
if cmd == 'runserver':
serve('127.0.0.1')
elif cmd == 'build':
build()
elif cmd == 'clean':
for filename in [jsonpath, oggpath]:
if os.path.exists(filename):
print "removing %s" % filename
os.remove(filename)
print "done cleaning."
else:
print "unknown command: %s" % cmd
sys.exit(1)