This repository has been archived on 2024-08-27. You can view files and clone it, but cannot push or open issues or pull requests.
negromate_origins/web/negromateweb/builder.py

200 lines
6.6 KiB
Python
Raw Normal View History

2018-10-12 23:00:20 +02:00
import json
import os
from shutil import copytree, copy
2018-10-12 23:00:20 +02:00
from pathlib import Path, PurePath
import subprocess
from jinja2 import Template, Environment, PackageLoader, select_autoescape
import asstosrt
import srt
2018-10-12 23:00:20 +02:00
import webvtt
class SongPage:
2018-10-12 23:00:20 +02:00
THUMBNAIL_GEOMETRY = '200x200'
def __init__(self, path):
self.name = path.name
self.original = None
self.author = None
self.path = path
self.video = None
self.video_type = None
2018-10-12 23:00:20 +02:00
self.vtt = None
self.srt = None
self.ass = None
self.cover = None
self.thumbnail = None
self.files = []
self.search_media()
def search_media(self):
for entry in self.path.iterdir():
if entry.name == 'metadata.json':
with entry.open('r') as metadatafile:
self.metadata = json.load(metadatafile)
if 'name' in self.metadata:
self.name = self.metadata['name']
if 'original' in self.metadata:
self.original = self.metadata['original']
if 'author' in self.metadata:
self.author = self.metadata['author']
elif entry.name.endswith('mp4'):
self.video = entry
self.video_type = 'video/mp4'
self.files.append(entry)
elif entry.name.endswith('webm'):
self.video = entry
self.video_type = 'video/webm'
self.files.append(entry)
elif entry.name.endswith('ogv'):
self.video = entry
self.video_type = 'video/ogg'
2018-10-12 23:00:20 +02:00
self.files.append(entry)
elif entry.name.endswith('vtt'):
self.vtt = entry
elif entry.name == "{}.srt".format(entry.name):
2018-10-12 23:00:20 +02:00
self.srt = entry
self.files.append(entry)
elif entry.name.endswith('ass'):
self.ass = entry
self.files.append(entry)
elif entry.name.endswith('_thumbnail.jpg'):
self.thumbnail = entry
elif entry.name.endswith('jpg'):
self.cover = entry
elif entry.name == 'index.html':
continue
else:
self.files.append(entry)
if self.srt is None and self.ass is not None:
self.srt = self.path / "{}.srt".format(self.path.name)
with self.ass.open('r') as assfile, self.srt.open('w') as srtfile:
srtfile.write(asstosrt.convert(assfile))
self.files.append(self.srt)
2018-10-12 23:00:20 +02:00
if self.vtt is None and self.srt is not None:
srtfile = self.path / self.srt
self.vtt = self.path / "{}.vtt".format(self.path.name)
webvtt.from_srt(str(self.srt.absolute())).save(str(self.vtt.absolute()))
if self.cover is None and self.video is not None:
self.cover = self.path / "{}.jpg".format(self.path.name)
2018-10-12 23:00:20 +02:00
command = [
'ffmpeg',
'-loglevel', 'quiet',
'-i', str(self.video.absolute()),
'-vcodec', 'mjpeg',
'-vframes', '1',
'-an',
'-f', 'rawvideo',
'-ss', '2',
str(self.cover.absolute()),
]
subprocess.check_call(command)
if self.thumbnail is None and self.cover is not None:
self.thumbnail = self.path / "{}_thumbnail.jpg".format(self.path.name)
2018-10-12 23:00:20 +02:00
subprocess.check_call([
'convert',
str(self.cover.absolute()),
'-resize', self.THUMBNAIL_GEOMETRY,
str(self.thumbnail.absolute()),
])
def get_context_data(self):
parsed_srt = None
if self.srt:
with self.srt.open('r') as srtfile:
try:
srt_str = srtfile.read().encode('utf-8').decode('utf-8-sig')
parsed_srt = list(srt.parse(srt_str))
except Exception as e:
print("{}: srt parse error: {}".format(self.path.name, e))
2018-10-12 23:00:20 +02:00
return {
'song': self,
'parsed_srt': parsed_srt,
2018-10-12 23:00:20 +02:00
}
def render(self, builder, context):
ctx = self.get_context_data()
ctx.update(context)
builder.render('song.html', self.path, ctx)
2018-10-12 23:00:20 +02:00
class Builder:
def __init__(self, root_folder, libreto, root_path=PurePath('/')):
2018-10-12 23:00:20 +02:00
self.root_folder = root_folder
self.libreto = libreto
2018-10-12 23:00:20 +02:00
self.root_path = root_path
self.static_dir = Path(__file__).parent / 'static'
self.env = Environment(
loader=PackageLoader('negromateweb', 'templates'),
autoescape=select_autoescape(['html']),
)
self.env.filters['url'] = self.url
def url(self, path):
return self.root_path / path.relative_to(self.root_folder)
def render(self, template, target, context):
html_file = target / 'index.html'
page_template = self.env.get_template(template)
with html_file.open('w') as page:
page.write(page_template.render(context))
def build(self):
songs = []
2018-10-12 23:00:20 +02:00
for entry in self.root_folder.iterdir():
if entry.name in ['static', 'playlist', 'home']:
2018-10-12 23:00:20 +02:00
continue
if entry.is_dir():
print("building {}".format(entry.name))
try:
songpage = SongPage(entry)
2018-10-12 23:00:20 +02:00
except Exception as e:
raise e
print("Error: {}".format(e))
continue
songs.append(songpage)
2018-10-12 23:00:20 +02:00
songs.sort(key=lambda a: a.name)
2018-10-12 23:00:20 +02:00
global_context = {
'songs': songs,
2018-10-12 23:00:20 +02:00
'root_path': self.root_path,
}
for song in songs:
song.render(self, global_context)
self.render('index.html', self.root_folder, global_context)
home = self.root_folder / 'home'
if not home.exists():
home.mkdir()
self.render('home.html', home, global_context)
2018-10-12 23:00:20 +02:00
playlist = self.root_folder / 'playlist'
if not playlist.exists():
playlist.mkdir()
self.render('playlist.html', playlist, global_context)
2018-10-12 23:00:20 +02:00
static = self.root_folder / 'static'
if not static.exists():
static.mkdir()
2018-10-12 23:00:20 +02:00
subprocess.check_call([
'rsync',
'-ra',
str(self.static_dir),
str(self.root_folder.absolute()),
])
libreto = self.root_folder / 'static/libreto/libreto.pdf'
copy(str(self.libreto.absolute()), str(libreto.absolute()))