diff --git a/.gitignore b/.gitignore index b5f2439..0fc923c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ schedule.de.xml snapshot-*.png env .DS_Store +*.swp diff --git a/glt23/TitilliumWeb-Regular-with-emoji.ttf b/glt23/TitilliumWeb-Regular-with-emoji.ttf new file mode 100644 index 0000000..8f1e397 Binary files /dev/null and b/glt23/TitilliumWeb-Regular-with-emoji.ttf differ diff --git a/glt23/TitilliumWeb-SemiBold-with-emoji.ttf b/glt23/TitilliumWeb-SemiBold-with-emoji.ttf new file mode 100644 index 0000000..2d3ab68 Binary files /dev/null and b/glt23/TitilliumWeb-SemiBold-with-emoji.ttf differ diff --git a/glt23/config.ini b/glt23/config.ini new file mode 100644 index 0000000..8fd5139 --- /dev/null +++ b/glt23/config.ini @@ -0,0 +1,33 @@ +[default] +schedule = https://pretalx.linuxtage.at/glt23/schedule/export/schedule.xml +template = glt23_intro_template.ts +alpha = false +prores = false + +[title] +in = 1 +out = 6.5 +font = TitilliumWeb-SemiBold-with-emoji.ttf +fontsize = 100 +fontcolor = #000000 +x = 200 +y = 200 + +[speaker] +in = 2 +out = 6.5 +font = TitilliumWeb-Regular-with-emoji.ttf +fontsize = 60 +fontcolor = #000000 +x = 200 +y = 800 + +[text] +in = 3 +out = 6.5 +font = TitilliumWeb-Regular-with-emoji.ttf +fontsize = 45 +fontcolor = #000000 +x = 200 +y = 1000 +text = '' diff --git a/gpn21/Roboto-Regular-enriched.ttf b/gpn21/Roboto-Regular-enriched.ttf new file mode 100644 index 0000000..02d8309 Binary files /dev/null and b/gpn21/Roboto-Regular-enriched.ttf differ diff --git a/gpn21/config.toml b/gpn21/config.toml new file mode 100644 index 0000000..520f638 --- /dev/null +++ b/gpn21/config.toml @@ -0,0 +1,34 @@ +[default] +schedule = "https://cfp.gulas.ch/gpn21/schedule/export/schedule.xml" +template = "gpn21_intro_template_audio.mp4" +alpha = false +prores = false + +[title] +in = 1.5 +out = 7 +font = "Roboto-Regular-enriched.ttf" +fontsize = 100 +fontcolor = "#000000" +x = 64 +y = 200 + +[speaker] +in = 2.5 +out = 7 +font = "Roboto-Regular-enriched.ttf" +fontsize = 60 +fontcolor = "#000000" +x = 64 +y = 900 + +[text] +in = 3 +out = 7 +font = "Roboto-Regular-enriched.ttf" +fontsize = 45 +fontcolor = "#000000" +x = 64 +y = 1000 +text = '' + diff --git a/jh23-ffm/Roboto-Regular-enriched.ttf b/jh23-ffm/Roboto-Regular-enriched.ttf new file mode 100644 index 0000000..02d8309 Binary files /dev/null and b/jh23-ffm/Roboto-Regular-enriched.ttf differ diff --git a/jh23-ffm/config.toml b/jh23-ffm/config.toml new file mode 100644 index 0000000..22e123a --- /dev/null +++ b/jh23-ffm/config.toml @@ -0,0 +1,34 @@ +[default] +schedule = "https://jh.franzi.business/schedule/jh23ffm.xml" +template = "jh23-ffm-template.ts" +alpha = false +prores = false + +[title] +in = 1.5 +out = 7 +font = "Roboto-Regular-enriched.ttf" +fontsize = 80 +fontcolor = "#ffffff" +x = 400 +y = 860 + +[speaker] +in = 2.5 +out = 7 +font = "Roboto-Regular-enriched.ttf" +fontsize = 60 +fontcolor = "#ffffff" +x = 400 +y = 960 + +[text] +in = 3 +out = 7 +font = "Roboto-Regular-enriched.ttf" +fontsize = 45 +fontcolor = "#ffffff" +x = 64 +y = 1000 +text = '' + diff --git a/make-ffmpeg-fade.py b/make-ffmpeg-fade.py index 6f1e98b..d9be29b 100755 --- a/make-ffmpeg-fade.py +++ b/make-ffmpeg-fade.py @@ -7,10 +7,19 @@ import subprocess import renderlib import argparse import shlex +from toml import load from PIL import ImageFont -from configparser import ConfigParser import json +from rich import print,inspect +import logging +from rich.logging import RichHandler + +FORMAT = "%(message)s" +logging.basicConfig( + level="INFO", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()] +) + # Parse arguments parser = argparse.ArgumentParser( description='C3VOC Intro-Outro-Generator - Variant which renders only using video filters in ffmpeg', @@ -51,24 +60,20 @@ parser.add_argument('--force', action="store_true", default=False, help=''' args = parser.parse_args() +if args.debug: + logging.getLogger().setLevel(logging.DEBUG) + if (args.skip is None): args.skip = [] -def headline(str): - print("##################################################") - print(str) - print("##################################################") - print() +if not (os.path.exists(os.path.join(args.project, 'config.toml'))): + logging.error("config.toml file in Project Path is missing") + sys.exit(1) - -def error(str): - headline(str) - parser.print_help() - sys.exit(1) - -cparser = ConfigParser() -cparser.read(os.path.join(os.path.dirname(args.project), 'config.ini')) +with open(os.path.join(args.project, 'config.toml'), 'r') as f: + cparser = load(f) +logging.debug(cparser) template = cparser['default']['template'] alpha = cparser['default']['alpha'] prores = cparser['default']['prores'] @@ -103,33 +108,31 @@ text_x = int(cparser['text']['x']) text_y = int(cparser['text']['y']) text_text = cparser['text']['text'] -font_t = os.path.join(os.path.dirname(args.project), title_font) -font_s = os.path.join(os.path.dirname(args.project), speaker_font) -font_tt = os.path.join(os.path.dirname(args.project), text_font) +font_t = os.path.join(args.project, title_font) +font_s = os.path.join(args.project, speaker_font) +font_tt = os.path.join(args.project, text_font) fileformat = os.path.splitext(template)[1] -infile = os.path.join(os.path.dirname(args.project), template) +infile = os.path.join(args.project, template) schedule = cparser['default']['schedule'] if not (os.path.exists(os.path.join(args.project, template))): - error("Template file {} in Project Path is missing".format(template)) + logging.error("Template file {} in Project Path is missing".format(template)) for ffile in (title_font, speaker_font, text_font): if not (os.path.exists(os.path.join(args.project, ffile))): - error("Font file {} in Project Path is missing".format(ffile)) + logging.error("Font file {} in Project Path is missing".format(ffile)) -if not (os.path.exists(os.path.join(args.project, 'config.ini'))): - error("config.ini file in Project Path is missing") if alpha == 'true' and not fileformat == '.mov': - error("Alpha can only be rendered with .mov source files") + logging.error("Alpha can only be rendered with .mov source files") if not args.project: - error("The Project Path is a required argument") + logging.error("The Project Path is a required argument") if not args.debug and not schedule: - error("Either specify --debug or supply a schedule in config.ini") + logging.error("Either specify --debug or supply a schedule in config.ini") if args.debug: persons = ['Thomas Roth', 'Dmitry Nedospasov', 'Josh Datko'] @@ -150,7 +153,7 @@ def describe_event(event): def event_print(event, message): - print("{} – {}".format(describe_event(event), message)) + logging.info("{} – {}".format(describe_event(event), message)) def fmt_command(command, **kwargs): @@ -176,10 +179,10 @@ def fit_text(string: str, frame_width): line_num = 0 line = "" for word in split_line: - w, _ = translation_font.getsize(" ".join([line, word])) - print("{}, {}".format(w, line)) + w = translation_font.getlength(" ".join([line, word])) + logging.debug("{}, {}".format(w, line)) if w > (frame_width): - print("too wide, breaking") + logging.debug("too wide, breaking") lines += line.strip() + "\n" line = "" @@ -222,17 +225,18 @@ def enqueue_job(event): t = fit_title(event_title) s = fit_speaker(event_personnames) - print(s) + logging.info(s) if args.debug: - print('Title: ', t) - print('Speaker: ', s) + logging.info(f'Title: {t}') + logging.info(f'Speaker: {s}') - outfile = os.path.join(os.path.dirname(args.project), event_id + '.ts') + outfile = os.path.join(args.project, event_id + '.ts') - videofilter = "drawtext=fontfile={fontfile}:fontsize={fontsize}:fontcolor={fontcolor}:x={x}:y={y}:text='{text}':".format( + videofilter = "drawtext=fontfile={fontfile}:fontsize={fontsize}:line_spacing={linespacing}:fontcolor={fontcolor}:x={x}:y={y}:text='{text}':".format( fontfile = font_t, fontsize = title_fontsize, + linespacing = int(0.05*title_fontsize), fontcolor = title_fontcolor, x = title_x, y = title_y, @@ -244,9 +248,10 @@ def enqueue_job(event): fade_out_end_time = title_in + fade_duration + title_duration + fade_duration, fade_duration = fade_duration ) - videofilter += "drawtext=fontfile={fontfile}:fontsize={fontsize}:fontcolor={fontcolor}:x={x}:y={y}:text='{text}':".format( + videofilter += "drawtext=fontfile={fontfile}:fontsize={fontsize}:line_spacing={linespacing}:fontcolor={fontcolor}:x={x}:y={y}:text='{text}':".format( fontfile = font_s, fontsize = speaker_fontsize, + linespacing = int(0.05*speaker_fontsize), fontcolor = speaker_fontcolor, x = speaker_x, y = speaker_y, @@ -258,9 +263,10 @@ def enqueue_job(event): fade_out_end_time = speaker_in + fade_duration + speaker_duration + fade_duration, fade_duration = fade_duration ) - videofilter += "drawtext=fontfile={fontfile}:fontsize={fontsize}:fontcolor={fontcolor}:x={x}:y={y}:text={text}:".format( + videofilter += "drawtext=fontfile={fontfile}:fontsize={fontsize}:line_spacing={linespacing}:fontcolor={fontcolor}:x={x}:y={y}:text={text}:".format( fontfile = font_tt, fontsize = text_fontsize, + linespacing = int(0.05*text_fontsize), fontcolor = text_fontcolor, x = text_x, y = text_y, @@ -284,8 +290,7 @@ def enqueue_job(event): else: cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -map 0:0 -c:v mpeg2video -pix_fmt:v yuv420p -qscale:v 2 -qmin:v 2 -qmax:v 7 -keyint_min 0 -bf 0 -g 0 -intra:0 -maxrate:0 90M -aspect 16:9 -map 0:1 -c:a mp2 -b:a 384k -shortest -f mpegts "{2}"'.format(infile, videofilter, outfile) - if args.debug: - print(cmd) + logging.debug(cmd) run(cmd) @@ -294,14 +299,14 @@ def enqueue_job(event): if args.ids: if len(args.ids) == 1: - print("enqueuing {} job".format(len(args.ids))) + logging.info("enqueuing {} job".format(len(args.ids))) else: - print("enqueuing {} jobs".format(len(args.ids))) + logging.info("enqueuing {} jobs".format(len(args.ids))) else: if len(events) == 1: - print("enqueuing {} job".format(len(events))) + logging.info("enqueuing {} job".format(len(events))) else: - print("enqueuing {} jobs".format(len(events))) + logging.info("enqueuing {} jobs".format(len(events))) for event in events: @@ -309,7 +314,7 @@ for event in events: continue if args.rooms and event['room'] not in args.rooms: - print("skipping room %s (%s)" % (event['room'], event['title'])) + logging.info("skipping room %s (%s)" % (event['room'], event['title'])) continue event_print(event, "enqueued as " + str(event['id'])) @@ -320,6 +325,6 @@ for event in events: continue -print('all done') +logging.info('all done') diff --git a/requirements.txt b/requirements.txt index 57edff5..921063b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,5 @@ cssutils==1.0.2 lxml==4.6.3 svg.path==4.0.2 Wand==0.6.5 +toml +rich