import xml.etree.ElementTree as ET import argparse import os import glob from urllib2 import unquote import time library = None class FCPXLibrary: def __init__(self, xml_path): parser = ET.parse(xml_path) self.root = parser.getroot() self.xml_version = self.root.attrib.get('version') self.location = self.library_location() # self.projects = self.root.findall('./library/event/project') self.formats = self.root.findall('./resources/format') self.clips = [Clip(x, self) for x in self.root.findall(".//asset-clip")] self.projects = [Project(x, self) for x in self.root.findall('./library/event/project')] def formats(self): return self.root.findall('./resources/format') def element_with_tag_value(self, element, tag, value): return self.root.findall(".//{e}[@{t}='{v}']".format(e=element, t=tag, v=value)) def clips_with_videorole(self, role): return [clip for clip in self.clips if getattr(clip, 'videoRole', None) == role] def format_with_id(self, id): # return self.root.findall("./resources/format[id='{}']".format(id)) return self.element_with_tag_value('format', 'id', id) def library_location(self): # urllib2.unquote(asset_ref.get('src'))[7:] path = self.root.findall('./library')[0].attrib['location'] return unquote(path)[7:] class Project: def __init__(self, project_element, library): for attrib in project_element.attrib: setattr(self, attrib, project_element.get(attrib)) print(project_element.attrib) print(project_element.parent) ref_clips = project_element.findall(".//ref-clip") print('start') for clip in library.clips: print(clip.name) if clip.name == ref_clips[0]: print(clip) break print('end') # for child in ref_clips: # print(child.tag, child.attrib) class Clip: def __init__(self, clip_element, library): # self.library = library # Get attribs from XML for attrib in clip_element.attrib: setattr(self, attrib, clip_element.get(attrib)) self.type = 'audio' if hasattr(self, 'audioRole') else 'video' # Get clip reference asset_ref = next(iter(library.element_with_tag_value('asset', 'id', self.ref))) for attrib in asset_ref.attrib: if not hasattr(self, attrib): setattr(self, attrib, asset_ref.get(attrib)) self.source = unquote(asset_ref.get('src'))[7:] if self.type == 'video': format_id = getattr(self, 'format', asset_ref.get('format', None)) video_format = next(iter(library.format_with_id(format_id))) if not hasattr(self, 'format'): print('no format!') try: frame_duration = fcp_time_to_float(video_format.get('frameDuration')) self.in_frame = int(round(fcp_time_to_float(self.start) / frame_duration)) duration = int(round(fcp_time_to_float(self.duration) / frame_duration)) self.out_frame = self.in_frame + duration except Exception as e: print('in/out fail: ' + str(e)) print(dir(self)) pass def optimized_source(self): path = None mov = os.path.splitext(os.path.basename(self.source))[0] + '.mov' found = glob.glob(os.path.join(library.location, '*', 'Transcoded Media', 'High Quality Media', mov)) if found: path = found[0] print(path) return path def proxy_source(self): path = None mov = os.path.splitext(os.path.basename(self.source))[0] + '.mov' found = glob.glob(os.path.join(library.location, '*', 'Transcoded Media', 'Proxy Media', mov)) if found: path = found[0] print(path) return path def __repr__(self): if self.type == 'video': return "" % (getattr(self, 'name', None), self.type, getattr(self, 'videoRole', None), self.out_frame - self.in_frame) else: return "" % (getattr(self, 'name', None), self.type, getattr(self, 'audioRole', None)) def fcp_time_to_float(timestr): try: rates = timestr.strip('s').split('/') return float(rates[0]) / float(rates[-1]) except (ZeroDivisionError, AttributeError) as e: return 0.0 import sys from types import ModuleType, FunctionType from gc import get_referents # Custom objects know their class. # Function objects seem to know way too much, including modules. # Exclude modules as well. BLACKLIST = type, ModuleType, FunctionType def getsize(obj): """sum size of object & members.""" if isinstance(obj, BLACKLIST): raise TypeError('getsize() does not take argument of type: '+ str(type(obj))) seen_ids = set() size = 0 objects = [obj] while objects: need_referents = [] for obj in objects: if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids: seen_ids.add(id(obj)) size += sys.getsizeof(obj) need_referents.append(obj) objects = get_referents(*need_referents) return size # if __name__ == "__main__": # # parser = argparse.ArgumentParser() # parser.add_argument('-i', '--input', help='Input FCPX Library XML', required=True) # parser.add_argument('-s', '--save-file', help='Description', required=False) # # args = parser.parse_args() # # library = FCPXLibrary(args.input) # # print getsize(library) # while True: # time.sleep(4) # # print library.library_location() # # print dir(library.clips[0]) # print library.clips[0] # print library.clips[0].proxy_source() # # print(args.input) # print(args.save_file) if __name__ == '__main__': library = FCPXLibrary('new.fcpxml') # print library.clips[0].source # print library.library_location() # # print dir(library.clips[0]) # print library.clips[0] # print library.clips[0].proxy_source() # for clip in library.clips: # print clip print(dir(library.projects[0])) print(library.formats)