-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.py
141 lines (106 loc) · 3.95 KB
/
server.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
141
import os
import json
import base64
import mimetypes
import asyncio
from subprocess import Popen, PIPE
from tornado import web, gen, template, websocket
from tornado.httpclient import AsyncHTTPClient
from tornado.platform.asyncio import AsyncIOMainLoop
from parse_ff_graph import graph_to_filter_chain
MAX_FILE_SIZE = 10
PROJECT_ROOT = os.path.dirname(__file__)
UPLOADS = os.path.join(PROJECT_ROOT, 'uploads')
# O-oh. Convenience.
if not os.path.exists(UPLOADS):
os.mkdir(UPLOADS)
class MainHandler(web.RequestHandler):
def get(self):
self.render('homepage.html')
class UploadHandler(web.RequestHandler):
def get(self):
self.render('upload.html', **{'filesize': MAX_FILE_SIZE})
def put(self):
print('UploadHandler.put')
content_length = int(self.request.headers.get('Content-Length', 0))
if content_length <= MAX_FILE_SIZE *(1024 *1024):
files = self.request.files.get('file', [])
for file_config in files:
filename = file_config.get('filename')
path = os.path.join(UPLOADS, filename)
with open(path, 'wb') as file:
file.write(file_config.get('body'))
resp = {
'path': os.path.relpath(path, PROJECT_ROOT),
'filename': filename,
}
self.finish(json.dumps(resp))
else:
print('\tFile is too big!')
self.send_error(status_code=413)
def get_render_path(path):
name, ext = os.path.splitext(path)
return '{0}_render{1}'.format(name, ext)
class RenderWebSocket(websocket.WebSocketHandler):
"""
Load node tree from client
"""
def open(self):
print('RenderWebSocket.open')
@gen.coroutine
def on_message(self, msg):
print('RenderWebSocket.on_message')
print('\t < {0}'.format(msg))
if msg is not None:
render_config = json.loads(msg)
filters = graph_to_filter_chain(render_config.get('filters', {}))
path = os.path.join(UPLOADS, render_config.get('reference_file'))
reply = ''
result = None
errors = []
if os.path.exists(path):
render_path = get_render_path(path)
cmd = ['ffmpeg', '-i', path, '-vf', filters, '-y', render_path,]
reply = 'Render {0} using cmd: <pre>{1}</pre>'.format(
render_config.get('reference_file'), cmd
)
print('\t{0}'.format(reply))
process = Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
if process.returncode != 0:
errors.append(stderr)
else:
data = base64.b64encode(
open(render_path, 'rb').read()
).decode('ascii')
mtype, encoding = mimetypes.guess_type(path)
result = 'data:{0};base64,{1}'.format(mtype, data)
else:
errors.append('Could not load file from path {0}'.format(path))
print('\t > {0}'.format(reply))
resp = {
'reference_file': render_config.get('reference_file'),
'result': result,
'errors': errors,
'message': reply,
}
self.write_message(json.dumps(resp))
def on_close(self):
print('RenderWebSocket.on_close')
settings = {
'debug': True,
'autoreload': False,
'template_path': os.path.join(PROJECT_ROOT, 'templates'),
}
application = web.Application([
(r'/', MainHandler),
(r'/upload', UploadHandler),
(r'/socket', RenderWebSocket),
(r'/static/(.*)', web.StaticFileHandler, {
'path': os.path.join(PROJECT_ROOT, 'assets'),
}),
], **settings)
if __name__ == "__main__":
AsyncIOMainLoop().install()
application.listen(8888)
asyncio.get_event_loop().run_forever()