129 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| import subprocess
 | |
| import renderlib
 | |
| import argparse
 | |
| import tempfile
 | |
| import shlex
 | |
| import time
 | |
| import sys
 | |
| import os
 | |
| 
 | |
| from xml.sax.saxutils import escape as xmlescape
 | |
| 
 | |
| # Parse arguments
 | |
| parser = argparse.ArgumentParser(
 | |
| 	description='C3VOC Intro-Outro-Generator - Variant to use with apple Motion Files',
 | |
| 	usage="./make.py gpn17/Intro.motn https://url/to/schedule.xml",
 | |
| 	formatter_class=argparse.RawTextHelpFormatter)
 | |
| 
 | |
| parser.add_argument('motn', action="store", metavar='Motion-File', type=str, help='''
 | |
| 	Path to your Motion-File .motn-File
 | |
| 	''')
 | |
| parser.add_argument('schedule', action="store", metavar='Schedule-URL', type=str,  nargs='?', help='''
 | |
| 	URL or Path to your schedule.xml
 | |
| 	''')
 | |
| 
 | |
| parser.add_argument('--debug', action="store_true", default=False, help='''
 | |
| 	Run script in debug mode and render with placeholder texts,
 | |
| 	not parsing or accessing a schedule. Schedule-URL can be left blank when
 | |
| 	used with --debug
 | |
| 	This argument must not be used together with --id
 | |
| 	Usage: ./make.py yourproject/ --debug
 | |
| 	''')
 | |
| 
 | |
| parser.add_argument('--id', dest='ids', nargs='+', action="store", type=int, help='''
 | |
| 	Only render the given ID(s) from your projects schedule.
 | |
| 	This argument must not be used together with --debug
 | |
| 	Usage: ./make.py yourproject/ --id 4711 0815 4223 1337
 | |
| 	''')
 | |
| 
 | |
| args = parser.parse_args()
 | |
| 
 | |
| def error(str):
 | |
| 	print("##################################################")
 | |
| 	print(str)
 | |
| 	print("##################################################")
 | |
| 	print()
 | |
| 	parser.print_help()
 | |
| 	sys.exit(1)
 | |
| 
 | |
| if not args.motn:
 | |
| 	error("The Motion-File is a rquired argument")
 | |
| 
 | |
| if not args.debug and not args.schedule:
 | |
| 	error("Either specify --debug or supply a schedule")
 | |
| 
 | |
| if args.debug:
 | |
| 	persons = ['Arnulf Christl', 'Astrid Emde', 'Dominik Helle', 'Till Adams']
 | |
| 	events = [{
 | |
| 		'id': 3773,
 | |
| 		'title': 'Was ist Open Source, wie funktioniert das?',
 | |
| 		'subtitle': 'Die Organisation der Open Geo- und GIS-Welt. Worauf man achten sollte.',
 | |
| 		'persons': persons,
 | |
| 		'personnames': ', '.join(persons),
 | |
| 		'room': 'Großer Saal',
 | |
| 	}]
 | |
| 
 | |
| else:
 | |
| 	events = renderlib.events(args.schedule)
 | |
| 
 | |
| def run_check(command, **kwargs):
 | |
| 	args = {}
 | |
| 	for key, value in kwargs.items():
 | |
| 		args[key] = shlex.quote(value)
 | |
| 
 | |
| 	command = command.format(**args)
 | |
| 	print(" -> "+command)
 | |
| 	subprocess.check_call(shlex.split(command))
 | |
| 
 | |
| def render(event):
 | |
| 	with tempfile.TemporaryDirectory() as tempdir:
 | |
| 		work_doc = os.path.join(tempdir, "work.motn")
 | |
| 		intermediate_clip = os.path.join(tempdir, "intermediate.mov")
 | |
| 		final_clip = os.path.join(os.path.dirname(args.motn), str(event['id'])+'.ts')
 | |
| 
 | |
| 		with open(args.motn, 'r') as fp:
 | |
| 			xmlstr = fp.read()
 | |
| 
 | |
| 		for key, value in event.items():
 | |
| 			xmlstr = xmlstr.replace("$"+str(key), xmlescape(str(value)))
 | |
| 
 | |
| 		with open(work_doc, 'w') as fp:
 | |
| 			fp.write(xmlstr)
 | |
| 
 | |
| 		print("  generated work-document in " + work_doc + ", now starting compressor")
 | |
| 		run_check(
 | |
| 			'/Applications/Compressor.app/Contents/MacOS/Compressor -jobpath "{jobpath}" -settingpath {home}/Library/Application\ Support/Compressor/Settings/Apple\ ProRes\ 4444.cmprstng -locationpath "{locationpath}"',
 | |
| 				jobpath=work_doc,
 | |
| 				home=os.getenv('HOME'),
 | |
| 				locationpath=intermediate_clip)
 | |
| 
 | |
| 		while True:
 | |
| 			ps = subprocess.check_output(shlex.split('ps aux')).decode('utf-8')
 | |
| 
 | |
| 			pscnt = ps.count('compressord')
 | |
| 			if pscnt == 0:
 | |
| 				break
 | |
| 
 | |
| 			print("  still "+str(pscnt)+" Compressor.app-processes running")
 | |
| 			time.sleep(5)
 | |
| 
 | |
| 
 | |
| 		print("  generated intermediate-clip in " + intermediate_clip + ", now starting transcoder")
 | |
| 		run_check(
 | |
| 			'ffmpeg -y -i "{input}" -ar 48000 -ac 1 -f s16le -i /dev/zero -map 0:0 -c:v mpeg2video -q:v 0 -aspect 16:9 -map 1:0 -map 1:0 -map 1:0 -map 1:0 -shortest -f mpegts "{output}"',
 | |
| 				input=intermediate_clip,
 | |
| 				output=final_clip)
 | |
| 
 | |
| 		print("  transcoded final-clip to " + final_clip)
 | |
| 
 | |
| 
 | |
| 
 | |
| for event in events:
 | |
| 	if args.ids and event['id'] not in args.ids:
 | |
| 		continue
 | |
| 
 | |
| 	print("rendering", event)
 | |
| 	render(event)
 | |
| 
 | 
