Annotation export to self-contained zip
This commit is contained in:
parent
8be08ce9d6
commit
6fbe49473d
3 changed files with 80 additions and 0 deletions
|
@ -2,7 +2,9 @@ import json
|
|||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from urllib.error import HTTPError
|
||||
from zipfile import ZipFile
|
||||
import tornado.ioloop
|
||||
import tornado.web
|
||||
import tornado.websocket
|
||||
|
@ -240,6 +242,73 @@ class AudioListingHandler(tornado.web.RequestHandler):
|
|||
print(names)
|
||||
self.write(json.dumps(names))
|
||||
|
||||
class ExportHandler(tornado.web.RequestHandler):
|
||||
"""
|
||||
Export a player to a zip file
|
||||
"""
|
||||
def initialize(self, config, index: svganim.strokes.AnnotationIndex):
|
||||
self.config = config
|
||||
self.index = index
|
||||
|
||||
async def get(self, filename):
|
||||
logger.info(f"file {filename=}")
|
||||
if filename not in self.index.drawings:
|
||||
raise tornado.web.HTTPError(404)
|
||||
|
||||
t_in = self.get_argument('t_in', None)
|
||||
t_out = self.get_argument('t_out', None)
|
||||
|
||||
animation = self.index.drawings[filename].get_animation()
|
||||
|
||||
if t_in is not None and t_out is not None:
|
||||
animation = animation.getSlice(float(t_in), float(t_out))
|
||||
|
||||
with tempfile.TemporaryDirectory() as tdir:
|
||||
with ZipFile(tdir + '/annotation.zip', 'w') as archive:
|
||||
logger.info('write svg')
|
||||
svgstring = animation.get_as_svg()
|
||||
archive.writestr('drawing.svg', svgstring)
|
||||
|
||||
logger.info('write png')
|
||||
archive.writestr('drawing.png', cairosvg.svg2png(bytestring=svgstring))
|
||||
|
||||
logger.info('write mp3')
|
||||
audio = await animation.audio.export(format="mp3")
|
||||
archive.writestr('drawing.mp3', audio.read())
|
||||
|
||||
|
||||
logger.info('write json')
|
||||
data = animation.asDict()
|
||||
data['audio']['file'] = 'drawing.mp3';
|
||||
archive.writestr('annotation.json', json.dumps(data))
|
||||
|
||||
|
||||
logger.info('write js')
|
||||
with open('www/annotate.js', 'r') as fp:
|
||||
archive.writestr('annotate.js', fp.read())
|
||||
with open('www/assets/wNumb-1.2.0.min.js', 'r') as fp:
|
||||
archive.writestr('wNumb-1.2.0.min.js', fp.read())
|
||||
|
||||
logger.info('write html')
|
||||
html = """
|
||||
<html>
|
||||
<head>
|
||||
<script src="wNumb-1.2.0.min.js"></script>
|
||||
<script src="annotate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<annotation-player data-poster-url="drawing.svg" data-annotation-url="annotation.json">
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
archive.writestr('drawing.html', html)
|
||||
|
||||
with open(tdir + '/annotation.zip', 'rb') as fp:
|
||||
self.set_header("Content-Type", "application/zip")
|
||||
self.write(fp.read())
|
||||
logger.info('done')
|
||||
|
||||
|
||||
|
||||
class AnimationHandler(tornado.web.RequestHandler):
|
||||
def initialize(self, config, index: svganim.strokes.AnnotationIndex):
|
||||
|
@ -669,6 +738,7 @@ class Server:
|
|||
},
|
||||
),
|
||||
(r"/files/(.*)", AnimationHandler, {"config": self.config, "index": self.index}),
|
||||
(r"/export/(.*)", ExportHandler, {"config": self.config, "index": self.index}),
|
||||
(
|
||||
r"/audio/(.+)",
|
||||
tornado.web.StaticFileHandler,
|
||||
|
|
|
@ -1669,6 +1669,10 @@ class AnnotationPlayer extends HTMLElement {
|
|||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
details{
|
||||
color: white;
|
||||
}
|
||||
|
||||
summary{
|
||||
list-style: none;
|
||||
|
|
|
@ -163,6 +163,12 @@ class AnnotationManager {
|
|||
infoEl.classList.add('annotation-info');
|
||||
infoEl.innerText = `[${tag.get_name()}] ${annotation.comment}`;
|
||||
|
||||
const downloadEl = document.createElement('a');
|
||||
downloadEl.href = annotation.url.replace('files', 'export');
|
||||
downloadEl.innerHTML = '↓';
|
||||
|
||||
infoEl.appendChild(downloadEl);
|
||||
|
||||
liEl.appendChild(playerEl);
|
||||
liEl.appendChild(selectEl);
|
||||
liEl.appendChild(infoEl);
|
||||
|
|
Loading…
Reference in a new issue