Annotation export to self-contained zip

This commit is contained in:
Ruben van de Ven 2023-02-23 18:52:21 +01:00
parent 8be08ce9d6
commit 6fbe49473d
3 changed files with 80 additions and 0 deletions

View file

@ -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,

View file

@ -1669,6 +1669,10 @@ class AnnotationPlayer extends HTMLElement {
position: absolute;
background: rgba(255, 255, 255, 0.7);
}
details{
color: white;
}
summary{
list-style: none;

View file

@ -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 = '&darr;';
infoEl.appendChild(downloadEl);
liEl.appendChild(playerEl);
liEl.appendChild(selectEl);
liEl.appendChild(infoEl);