fixes for empty titles & mov intro/outro
This commit is contained in:
parent
9c533338ff
commit
c6cea4e456
8 changed files with 195 additions and 1539 deletions
BIN
fsck2025/AgencyFB-Bold.ttf
Normal file
BIN
fsck2025/AgencyFB-Bold.ttf
Normal file
Binary file not shown.
BIN
fsck2025/AgencyFB-Regular.ttf
Normal file
BIN
fsck2025/AgencyFB-Regular.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
fsck2025/artwork/fsck-outro-base.mov
Normal file
BIN
fsck2025/artwork/fsck-outro-base.mov
Normal file
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
[meta]
|
[meta]
|
||||||
schedule = https://cfp.ctbk.de/fsck-2024/schedule/export/schedule.xml
|
schedule = https://cfp.ctbk.de/fsck-2025/schedule/export/schedule.xml
|
||||||
;; path to background video
|
;; path to background video
|
||||||
template = artwork/fsck-intro-base.mp4
|
template = artwork/fsck-intro-base.mov
|
||||||
;; whether background video uses transparency (needs to be .mov)
|
;; whether background video uses transparency (needs to be .mov)
|
||||||
alpha = false
|
alpha = false
|
||||||
;; whether background video is prores 4444
|
;; whether background video is prores 4444
|
||||||
|
@ -15,7 +15,7 @@ fade_duration = 1
|
||||||
;; 'title', 'speaker' and 'text' sections below.
|
;; 'title', 'speaker' and 'text' sections below.
|
||||||
[default]
|
[default]
|
||||||
;; default font
|
;; default font
|
||||||
fontfile = LiberationSans-Regular.ttf
|
fontfile = AgencyFB-Regular.ttf
|
||||||
;; default font color
|
;; default font color
|
||||||
fontcolor = #fae7e3
|
fontcolor = #fae7e3
|
||||||
|
|
||||||
|
@ -28,12 +28,15 @@ fontcolor = #fae7e3
|
||||||
;; - fontsize: font size (pixel)
|
;; - fontsize: font size (pixel)
|
||||||
;; - x: horizontal position (top left corner)
|
;; - x: horizontal position (top left corner)
|
||||||
;; - y: vertical position (top left corner)
|
;; - y: vertical position (top left corner)
|
||||||
|
;; - w: width of the text field
|
||||||
|
;; - h: height of the text field
|
||||||
[title]
|
[title]
|
||||||
in = 11.5
|
in = 11.5
|
||||||
out = 15
|
out = 15
|
||||||
fontsize = 67
|
fontsize = 67
|
||||||
x = 300
|
x = 300
|
||||||
y = 780
|
y = 780
|
||||||
|
fontfile = AgencyFB-Bold.ttf
|
||||||
|
|
||||||
[speaker]
|
[speaker]
|
||||||
in = 12
|
in = 12
|
||||||
|
|
File diff suppressed because it is too large
Load diff
289
make-ffmpeg.py
289
make-ffmpeg.py
|
@ -14,6 +14,7 @@ import platform
|
||||||
|
|
||||||
from PIL import ImageFont
|
from PIL import ImageFont
|
||||||
import schedulelib
|
import schedulelib
|
||||||
|
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context
|
ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
|
|
||||||
FRAME_WIDTH = 1920
|
FRAME_WIDTH = 1920
|
||||||
|
@ -34,31 +35,32 @@ class TextConfig:
|
||||||
return self.fontfile_path is not None
|
return self.fontfile_path is not None
|
||||||
|
|
||||||
def parse(self, cparser_sect, default_fontfile, default_fontcolor):
|
def parse(self, cparser_sect, default_fontfile, default_fontcolor):
|
||||||
self.inpoint = cparser_sect.getfloat('in')
|
self.inpoint = cparser_sect.getfloat("in")
|
||||||
self.outpoint = cparser_sect.getfloat('out')
|
self.outpoint = cparser_sect.getfloat("out")
|
||||||
self.x = cparser_sect.getint('x')
|
self.x = cparser_sect.getint("x")
|
||||||
self.y = cparser_sect.getint('y')
|
self.y = cparser_sect.getint("y")
|
||||||
self.w = cparser_sect.getint('w')
|
self.w = cparser_sect.getint("w")
|
||||||
|
|
||||||
self.fontcolor = cparser_sect.get('fontcolor', default_fontcolor)
|
self.fontcolor = cparser_sect.get("fontcolor", default_fontcolor)
|
||||||
|
|
||||||
fontfile = cparser_sect.get('fontfile', default_fontfile)
|
fontfile = cparser_sect.get("fontfile", default_fontfile)
|
||||||
self.fontfile_path = str(PurePath(args.project, fontfile).as_posix())
|
self.fontfile_path = str(PurePath(args.project, fontfile).as_posix())
|
||||||
|
|
||||||
if not os.path.exists(self.fontfile_path):
|
if not os.path.exists(self.fontfile_path):
|
||||||
error("Font file {} in Project Path is missing".format(self.fontfile_path))
|
error("Font file {} in Project Path is missing".format(self.fontfile_path))
|
||||||
|
|
||||||
self.fontsize = cparser_sect.getint('fontsize')
|
self.fontsize = cparser_sect.getint("fontsize")
|
||||||
self.bordercolor = cparser_sect.get('bordercolor', None)
|
self.bordercolor = cparser_sect.get("bordercolor", None)
|
||||||
|
|
||||||
def fit_text(self, text: str) -> str:
|
def fit_text(self, text: str) -> str:
|
||||||
if not text:
|
if not text:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
font = ImageFont.truetype(
|
font = ImageFont.truetype(
|
||||||
self.fontfile_path, size=self.fontsize, encoding="unic")
|
self.fontfile_path, size=self.fontsize, encoding="unic"
|
||||||
|
)
|
||||||
|
|
||||||
fitted= '\n'.join(fit_text(text, self.w or (FRAME_WIDTH-self.x-100), font))
|
fitted = "\n".join(fit_text(text, self.w or (FRAME_WIDTH - self.x - 100), font))
|
||||||
print(repr(fitted))
|
print(repr(fitted))
|
||||||
return fitted
|
return fitted
|
||||||
|
|
||||||
|
@ -66,21 +68,21 @@ class TextConfig:
|
||||||
if not text:
|
if not text:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
filter_str = ""
|
filter_str = ""
|
||||||
filter_str += "drawtext=enable='between({},{},{})':fix_bounds=true:text_align=C:x={}:y={}".format(
|
filter_str += "drawtext=enable='between({},{},{})':fix_bounds=true:text_align=C:x={}:y={}".format(
|
||||||
inout_type, self.inpoint, self.outpoint, self.x, self.y)
|
inout_type, self.inpoint, self.outpoint, self.x, self.y
|
||||||
|
)
|
||||||
if self.w:
|
if self.w:
|
||||||
filter_str+=f":boxw={self.w}"
|
filter_str += f":boxw={self.w}"
|
||||||
|
|
||||||
print(f"{text}, {type(text)}")
|
|
||||||
|
|
||||||
filter_str += ":fontfile='{}':fontsize={}:fontcolor={}:text={}".format(
|
filter_str += ":fontfile='{}':fontsize={}:fontcolor={}:text={}".format(
|
||||||
self.fontfile_path, self.fontsize, self.fontcolor, ffmpeg_escape_str(text))
|
self.fontfile_path, self.fontsize, self.fontcolor, ffmpeg_escape_str(text)
|
||||||
|
)
|
||||||
|
|
||||||
if self.bordercolor is not None:
|
if self.bordercolor is not None:
|
||||||
filter_str += ":borderw={}:bordercolor={}".format(
|
filter_str += ":borderw={}:bordercolor={}".format(
|
||||||
self.fontsize / 30, self.bordercolor)
|
self.fontsize / 30, self.bordercolor
|
||||||
|
)
|
||||||
|
|
||||||
if fade_time > 0:
|
if fade_time > 0:
|
||||||
filter_str += ":alpha='if(lt(t,{fade_in_start_time}),0,if(lt(t,{fade_in_end_time}),(t-{fade_in_start_time})/{fade_duration},if(lt(t,{fade_out_start_time}),1,if(lt(t,{fade_out_end_time}),({fade_duration}-(t-{fade_out_start_time}))/{fade_duration},0))))'".format(
|
filter_str += ":alpha='if(lt(t,{fade_in_start_time}),0,if(lt(t,{fade_in_end_time}),(t-{fade_in_start_time})/{fade_duration},if(lt(t,{fade_out_start_time}),1,if(lt(t,{fade_out_end_time}),({fade_duration}-(t-{fade_out_start_time}))/{fade_duration},0))))'".format(
|
||||||
|
@ -88,7 +90,8 @@ class TextConfig:
|
||||||
fade_in_end_time=self.inpoint + fade_time,
|
fade_in_end_time=self.inpoint + fade_time,
|
||||||
fade_out_start_time=self.outpoint - fade_time,
|
fade_out_start_time=self.outpoint - fade_time,
|
||||||
fade_out_end_time=self.outpoint,
|
fade_out_end_time=self.outpoint,
|
||||||
fade_duration=fade_time)
|
fade_duration=fade_time,
|
||||||
|
)
|
||||||
|
|
||||||
filter_str += ","
|
filter_str += ","
|
||||||
|
|
||||||
|
@ -120,34 +123,34 @@ def parse_config(filename) -> Config:
|
||||||
cparser = ConfigParser()
|
cparser = ConfigParser()
|
||||||
cparser.read(filename)
|
cparser.read(filename)
|
||||||
|
|
||||||
meta = cparser['meta']
|
meta = cparser["meta"]
|
||||||
conf.schedule = meta.get('schedule')
|
conf.schedule = meta.get("schedule")
|
||||||
infile = PurePath(args.project, meta.get('template'))
|
infile = PurePath(args.project, meta.get("template"))
|
||||||
conf.template_file = str(infile)
|
conf.template_file = str(infile)
|
||||||
conf.alpha = meta.getboolean('alpha', conf.alpha)
|
conf.alpha = meta.getboolean("alpha", conf.alpha)
|
||||||
conf.prores = meta.getboolean('prores', conf.prores)
|
conf.prores = meta.getboolean("prores", conf.prores)
|
||||||
conf.inout_type = meta.get('inout_type', conf.inout_type)
|
conf.inout_type = meta.get("inout_type", conf.inout_type)
|
||||||
conf.fade_duration = meta.getfloat('fade_duration', conf.fade_duration)
|
conf.fade_duration = meta.getfloat("fade_duration", conf.fade_duration)
|
||||||
|
|
||||||
defaults = cparser['default']
|
defaults = cparser["default"]
|
||||||
default_fontfile = defaults.get('fontfile', None)
|
default_fontfile = defaults.get("fontfile", None)
|
||||||
default_fontcolor = defaults.get('fontcolor', "#ffffff")
|
default_fontcolor = defaults.get("fontcolor", "#ffffff")
|
||||||
|
|
||||||
conf.title = TextConfig()
|
conf.title = TextConfig()
|
||||||
conf.title.parse(cparser['title'], default_fontfile, default_fontcolor)
|
conf.title.parse(cparser["title"], default_fontfile, default_fontcolor)
|
||||||
conf.speaker = TextConfig()
|
conf.speaker = TextConfig()
|
||||||
conf.speaker.parse(cparser['speaker'], default_fontfile, default_fontcolor)
|
conf.speaker.parse(cparser["speaker"], default_fontfile, default_fontcolor)
|
||||||
conf.text = TextConfig()
|
conf.text = TextConfig()
|
||||||
conf.text.parse(cparser['text'], default_fontfile, default_fontcolor)
|
conf.text.parse(cparser["text"], default_fontfile, default_fontcolor)
|
||||||
|
|
||||||
conf.extra_text = cparser['text'].get('text', '')
|
conf.extra_text = cparser["text"].get("text", "")
|
||||||
|
|
||||||
conf.fileext = infile.suffix
|
conf.fileext = infile.suffix
|
||||||
|
|
||||||
if not os.path.exists(conf.template_file):
|
if not os.path.exists(conf.template_file):
|
||||||
error("Template file {} in Project Path is missing".format(conf.template_file))
|
error("Template file {} in Project Path is missing".format(conf.template_file))
|
||||||
|
|
||||||
if conf.alpha and conf.fileext != '.mov':
|
if conf.alpha and conf.fileext != ".mov":
|
||||||
error("Alpha can only be rendered with .mov source files")
|
error("Alpha can only be rendered with .mov source files")
|
||||||
|
|
||||||
if not args.project:
|
if not args.project:
|
||||||
|
@ -169,7 +172,7 @@ def error(err_str):
|
||||||
|
|
||||||
|
|
||||||
def describe_event(event):
|
def describe_event(event):
|
||||||
return "#{}: {}".format(event['id'], event['title'])
|
return "#{}: {}".format(event["id"], event["title"])
|
||||||
|
|
||||||
|
|
||||||
def event_print(event, message):
|
def event_print(event, message):
|
||||||
|
@ -184,20 +187,20 @@ def fit_text(string: str, max_width: int, font: ImageFont) -> list[str]:
|
||||||
w = 0
|
w = 0
|
||||||
line = []
|
line = []
|
||||||
for word in split_line:
|
for word in split_line:
|
||||||
new_line = line + [word.rstrip(':')]
|
new_line = line + [word.rstrip(":")]
|
||||||
w = font.getlength(" ".join(new_line))
|
w = font.getlength(" ".join(new_line))
|
||||||
if w > max_width:
|
if w > max_width:
|
||||||
lines.append(' '.join(line))
|
lines.append(" ".join(line))
|
||||||
line = []
|
line = []
|
||||||
|
|
||||||
line.append(word.rstrip(':'))
|
line.append(word.rstrip(":"))
|
||||||
|
|
||||||
if word.endswith(':'):
|
if word.endswith(":"):
|
||||||
lines.append(' '.join(line))
|
lines.append(" ".join(line))
|
||||||
line = []
|
line = []
|
||||||
|
|
||||||
if line:
|
if line:
|
||||||
lines.append(' '.join(line))
|
lines.append(" ".join(line))
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
@ -206,65 +209,106 @@ def ffmpeg_escape_str(text: str) -> str:
|
||||||
# Escape according to https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping
|
# Escape according to https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping
|
||||||
# and don't put the string in quotes afterwards!
|
# and don't put the string in quotes afterwards!
|
||||||
text = text.replace(",", r"\,")
|
text = text.replace(",", r"\,")
|
||||||
text = text.replace(':', r"\\:")
|
text = text.replace(":", r"\\:")
|
||||||
text = text.replace("'", r"\\\'")
|
text = text.replace("'", r"\\\'")
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def enqueue_job(conf: Config, event):
|
def enqueue_job(conf: Config, event):
|
||||||
event_id = str(event['id'])
|
event_id = str(event["id"])
|
||||||
|
|
||||||
outfile = str(PurePath(args.project, event_id + '.ts'))
|
outfile = str(PurePath(args.project, event_id + ".ts"))
|
||||||
outfile_mov = str(PurePath(args.project, event_id + '.mov'))
|
outfile_mov = str(PurePath(args.project, event_id + ".mov"))
|
||||||
|
|
||||||
if event_id in args.skip:
|
if event_id in args.skip:
|
||||||
event_print(event, "skipping " + str(event['id']))
|
event_print(event, "skipping " + str(event["id"]))
|
||||||
return
|
return
|
||||||
if (os.path.exists(outfile) or os.path.exists(outfile_mov)) and not args.force:
|
if (os.path.exists(outfile) or os.path.exists(outfile_mov)) and not args.force:
|
||||||
event_print(event, "file exist, skipping " + str(event['id']))
|
event_print(event, "file exist, skipping " + str(event["id"]))
|
||||||
return
|
return
|
||||||
|
|
||||||
event_title = str(event['title'])
|
event_title = str(event["title"])
|
||||||
event_personnames = str(event['personnames'])
|
event_personnames = str(event["personnames"])
|
||||||
|
|
||||||
title = conf.title.fit_text(event_title)
|
title = conf.title.fit_text(event_title)
|
||||||
speakers = conf.speaker.fit_text(event_personnames)
|
speakers = conf.speaker.fit_text(event_personnames)
|
||||||
extra_text = conf.text.fit_text(conf.extra_text)
|
extra_text = conf.text.fit_text(conf.extra_text)
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
print('Title: ', title)
|
print("Title: ", title)
|
||||||
print('Speaker: ', speakers)
|
print("Speaker: ", speakers)
|
||||||
|
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == "Windows":
|
||||||
ffmpeg_path = './ffmpeg.exe'
|
ffmpeg_path = "./ffmpeg.exe"
|
||||||
else:
|
else:
|
||||||
ffmpeg_path = 'ffmpeg'
|
ffmpeg_path = "ffmpeg"
|
||||||
|
|
||||||
videofilter = conf.title.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, title) + ","
|
videofilters = [
|
||||||
videofilter += conf.speaker.get_ffmpeg_filter(conf.inout_type,
|
conf.title.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, title),
|
||||||
conf.fade_duration, speakers) + ","
|
conf.speaker.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, speakers),
|
||||||
videofilter += conf.text.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, extra_text)
|
conf.text.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, extra_text),
|
||||||
|
]
|
||||||
|
videofilter = ",".join(x for x in videofilters if len(x) > 0)
|
||||||
|
|
||||||
cmd = [ffmpeg_path, '-y', '-i', conf.template_file, '-vf', videofilter]
|
cmd = [ffmpeg_path, "-y", "-i", conf.template_file, "-vf", videofilter]
|
||||||
|
|
||||||
if conf.fileext == '.mov' and conf.alpha:
|
if conf.fileext == ".mov" and conf.alpha:
|
||||||
if conf.prores:
|
if conf.prores:
|
||||||
cmd += ['-vcodec', 'prores_ks', '-pix_fmt', 'yuva444p10le', '-profile:v',
|
cmd += [
|
||||||
'4444', '-shortest', '-movflags', 'faststart', '-f', 'mov', outfile_mov]
|
"-vcodec",
|
||||||
|
"prores_ks",
|
||||||
|
"-pix_fmt",
|
||||||
|
"yuva444p10le",
|
||||||
|
"-profile:v",
|
||||||
|
"4444",
|
||||||
|
"-shortest",
|
||||||
|
"-movflags",
|
||||||
|
"faststart",
|
||||||
|
"-f",
|
||||||
|
"mov",
|
||||||
|
outfile_mov,
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
cmd += ['-shortest', '-c:v', 'qtrle', '-movflags',
|
cmd += [
|
||||||
'faststart', '-f', 'mov', outfile_mov]
|
"-shortest",
|
||||||
|
"-c:v",
|
||||||
|
"qtrle",
|
||||||
|
"-movflags",
|
||||||
|
"faststart",
|
||||||
|
"-f",
|
||||||
|
"mov",
|
||||||
|
outfile_mov,
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
cmd += ['-map', '0:0', '-c:v', 'mpeg2video', '-q:v', '2', '-aspect', '16:9', '-map',
|
cmd += [
|
||||||
'0:1', '-c:a', 'mp2', '-b:a', '384k', '-shortest', '-f', 'mpegts', outfile]
|
"-map",
|
||||||
|
"0:0",
|
||||||
|
"-c:v",
|
||||||
|
"mpeg2video",
|
||||||
|
"-q:v",
|
||||||
|
"2",
|
||||||
|
"-aspect",
|
||||||
|
"16:9",
|
||||||
|
"-map",
|
||||||
|
"0:1",
|
||||||
|
"-c:a",
|
||||||
|
"mp2",
|
||||||
|
"-b:a",
|
||||||
|
"384k",
|
||||||
|
"-shortest",
|
||||||
|
"-f",
|
||||||
|
"mpegts",
|
||||||
|
outfile,
|
||||||
|
]
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
print(cmd)
|
print(cmd)
|
||||||
|
|
||||||
subprocess.check_call(cmd,
|
subprocess.check_call(
|
||||||
stderr=subprocess.STDOUT,
|
cmd,
|
||||||
)
|
stderr=subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
|
||||||
return event_id
|
return event_id
|
||||||
|
|
||||||
|
@ -272,59 +316,102 @@ def enqueue_job(conf: Config, event):
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='C3VOC Intro-Outro-Generator - Variant which renders only using video filters in ffmpeg',
|
description="C3VOC Intro-Outro-Generator - Variant which renders only using video filters in ffmpeg",
|
||||||
usage="./make-ffmpeg.py yourproject/",
|
usage="./make-ffmpeg.py yourproject/",
|
||||||
formatter_class=argparse.RawTextHelpFormatter)
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('project', action="store", metavar='Project folder', type=str, help='''
|
parser.add_argument(
|
||||||
|
"project",
|
||||||
|
action="store",
|
||||||
|
metavar="Project folder",
|
||||||
|
type=str,
|
||||||
|
help="""
|
||||||
Path to your project folder
|
Path to your project folder
|
||||||
''')
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('--debug', action="store_true", default=False, help='''
|
parser.add_argument(
|
||||||
|
"--debug",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="""
|
||||||
Run script in debug mode and render with placeholder texts,
|
Run script in debug mode and render with placeholder texts,
|
||||||
not parsing or accessing a schedule.
|
not parsing or accessing a schedule.
|
||||||
This argument must not be used together with --id
|
This argument must not be used together with --id
|
||||||
Usage: ./make-ffmpeg.py yourproject/ --debug
|
Usage: ./make-ffmpeg.py yourproject/ --debug
|
||||||
''')
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('--id', dest='ids', nargs='+', action="store", type=int, help='''
|
parser.add_argument(
|
||||||
|
"--id",
|
||||||
|
dest="ids",
|
||||||
|
nargs="+",
|
||||||
|
action="store",
|
||||||
|
type=int,
|
||||||
|
help="""
|
||||||
Only render the given ID(s) from your projects schedule.
|
Only render the given ID(s) from your projects schedule.
|
||||||
This argument must not be used together with --debug
|
This argument must not be used together with --debug
|
||||||
Usage: ./make-adobe-after-effects.py yourproject/ --id 4711 0815 4223 1337
|
Usage: ./make-adobe-after-effects.py yourproject/ --id 4711 0815 4223 1337
|
||||||
''')
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('--room', dest='rooms', nargs='+', action="store", type=str, help='''
|
parser.add_argument(
|
||||||
|
"--room",
|
||||||
|
dest="rooms",
|
||||||
|
nargs="+",
|
||||||
|
action="store",
|
||||||
|
type=str,
|
||||||
|
help="""
|
||||||
Only render the given room(s) from your projects schedule.
|
Only render the given room(s) from your projects schedule.
|
||||||
This argument must not be used together with --debug
|
This argument must not be used together with --debug
|
||||||
Usage: ./make-adobe-after-effects.py yourproject/ --room "HfG_Studio" "ZKM_Vortragssaal"
|
Usage: ./make-adobe-after-effects.py yourproject/ --room "HfG_Studio" "ZKM_Vortragssaal"
|
||||||
''')
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('--skip', nargs='+', action="store", type=str, help='''
|
parser.add_argument(
|
||||||
|
"--skip",
|
||||||
|
nargs="+",
|
||||||
|
action="store",
|
||||||
|
type=str,
|
||||||
|
help="""
|
||||||
Skip ID(s) not needed to be rendered.
|
Skip ID(s) not needed to be rendered.
|
||||||
Usage: ./make-ffmpeg.py yourproject/ --skip 4711 0815 4223 1337
|
Usage: ./make-ffmpeg.py yourproject/ --skip 4711 0815 4223 1337
|
||||||
''')
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('--force', action="store_true", default=False, help='''
|
parser.add_argument(
|
||||||
|
"--force",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="""
|
||||||
Force render if file exists.
|
Force render if file exists.
|
||||||
''')
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if (args.skip is None):
|
if args.skip is None:
|
||||||
args.skip = []
|
args.skip = []
|
||||||
|
|
||||||
config = parse_config(PurePath(args.project, 'config.ini'))
|
config = parse_config(PurePath(args.project, "config.ini"))
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
persons = ['Thomas Roth', 'Dmitry Nedospasov', 'Josh Datko',]
|
persons = [
|
||||||
events = [{
|
"Thomas Roth",
|
||||||
'id': 'debug',
|
"Dmitry Nedospasov",
|
||||||
'title': 'wallet.fail and the longest talk title to test if the template is big enough',
|
"Josh Datko",
|
||||||
'subtitle': 'Hacking the most popular cryptocurrency hardware wallets',
|
]
|
||||||
'persons': persons,
|
events = [
|
||||||
'personnames': ', '.join(persons),
|
{
|
||||||
'room': 'Borg',
|
"id": "debug",
|
||||||
}]
|
"title": "wallet.fail and the longest talk title to test if the template is big enough",
|
||||||
|
"subtitle": "Hacking the most popular cryptocurrency hardware wallets",
|
||||||
|
"persons": persons,
|
||||||
|
"personnames": ", ".join(persons),
|
||||||
|
"room": "Borg",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
events = list(schedulelib.events(config.schedule))
|
events = list(schedulelib.events(config.schedule))
|
||||||
|
@ -341,18 +428,20 @@ if __name__ == "__main__":
|
||||||
print("enqueuing {} jobs".format(len(events)))
|
print("enqueuing {} jobs".format(len(events)))
|
||||||
|
|
||||||
for event in events:
|
for event in events:
|
||||||
if args.ids and event['id'] not in args.ids:
|
if args.ids and event["id"] not in args.ids:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if args.rooms and event['room'] not in args.rooms:
|
if args.rooms and event["room"] not in args.rooms:
|
||||||
print("skipping room %s (%s)" % (event['room'], event['title']))
|
print("skipping room %s (%s)" % (event["room"], event["title"]))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
event_print(event, "enqueued as " + str(event['id']))
|
event_print(event, "enqueued as " + str(event["id"]))
|
||||||
|
|
||||||
job_id = enqueue_job(config, event)
|
job_id = enqueue_job(config, event)
|
||||||
if not job_id:
|
if not job_id:
|
||||||
event_print(event, "job was not enqueued successfully, skipping postprocessing")
|
event_print(
|
||||||
|
event, "job was not enqueued successfully, skipping postprocessing"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print('all done')
|
print("all done")
|
||||||
|
|
Loading…
Add table
Reference in a new issue