#! /usr/bin/python
import glob
import json
import re
import time
from utilities.render_worker import *
def aerender_path():
paths = glob.glob('/Applications/*After Effects*/aerender')
if len(paths) > 1:
logging.warning('Multiple After Effects installations detected')
elif not paths:
logging.error('After Effects installation not found')
else:
return paths[0]
class AERenderWorker(BaseRenderWorker):
@classmethod
def version(cls):
version = None
try:
x = subprocess.Popen([aerender_path(), '-version'], stdout=subprocess.PIPE)
x.wait()
ver_out = str(x.stdout.read().strip())
version = ver_out.split(" ")[-1].strip()
except Exception as e:
logging.error('failed getting version: {}'.format(e))
return version
renderer = 'After Effects'
render_engine = 'aerender'
supported_extensions = ['.aep']
def __init__(self, input_path, output_path, args=None):
super(AERenderWorker, self).__init__(input_path=input_path, output_path=output_path, ignore_extensions=False,
args=args)
self.comp = args.get('comp', None)
self.render_settings = args.get('render_settings', None)
self.omsettings = args.get('omsettings', None)
self.progress = 0
self.progress_history = []
self.attributes = {}
def _generate_subprocess(self):
if os.path.exists('nexrender-cli-macos'):
logging.info('nexrender found')
# {
# "template": {
# "src": String,
# "composition": String,
#
# "frameStart": Number,
# "frameEnd": Number,
# "frameIncrement": Number,
#
# "continueOnMissing": Boolean,
# "settingsTemplate": String,
# "outputModule": String,
# "outputExt": String,
# },
# "assets": [],
# "actions": {
# "prerender": [],
# "postrender": [],
# },
# "onChange": Function,
# "onRenderProgress": Function
# }
job = {'template':
{
'src': 'file://' + self.input, 'composition': self.comp.replace('"', ''),
'settingsTemplate': self.render_settings.replace('"', ''),
'outputModule': self.omsettings.replace('"', ''), 'outputExt': 'mov'}
}
x = ['./nexrender-cli-macos', "'{}'".format(json.dumps(job))]
else:
logging.info('nexrender not found')
x = [aerender_path(), '-project', self.input, '-comp', self.comp, '-RStemplate', self.render_settings,
'-OMtemplate', self.omsettings, '-output', self.output]
return x
def _parse_stdout(self, line):
# print line
if line.startswith('PROGRESS:'):
# print 'progress'
trimmed = line.replace('PROGRESS:', '').strip()
if len(trimmed):
self.progress_history.append(line)
if 'Seconds' in trimmed:
self._update_progress(line)
elif ': ' in trimmed:
tmp = trimmed.split(': ')
self.attributes[tmp[0].strip()] = tmp[1].strip()
elif line.startswith('WARNING:'):
trimmed = line.replace('WARNING:', '').strip()
self.warnings.append(trimmed)
logging.warning(trimmed)
elif line.startswith('aerender ERROR') or 'ERROR:' in line:
self.errors.append(line)
logging.error(line)
def _update_progress(self, line):
if not self.total_frames:
duration_string = self.attributes.get('Duration', None)
frame_rate = self.attributes.get('Frame Rate', '0').split(' ')[0]
self.total_frames = timecode_to_frames(duration_string.split('Duration:')[-1], float(frame_rate))
match = re.match(r'PROGRESS:.*\((?P\d+)\): (?P