def test_monoaural_aiff(self): new_file = os.path.join(common.sandbox(), 'ama_aiff.aaf') with aaf2.open(new_file, 'w') as f: aiff_file = common.generate_pcm_audio_mono('test_ama_aiff', fmt='aiff') meta = common.probe(aiff_file) mobs = ama.create_media_link(f, aiff_file, meta) self.assertTrue(len(mobs), 3) with aaf2.open(new_file, 'r') as f: common.walk_aaf(f.root) self.assertTrue(len(f.content.mobs) == 3) self.assertTrue(len(list(f.content.mastermobs())) == 1) master_mob = next(f.content.mastermobs()) self.assert_mastermob_valid_edit_spec(master_mob=master_mob, expected_sound_slots=1, expected_picture_slots=0) self.assertEqual(len(master_mob.slots), 1, "MasterMob should only have one slot") self.assertEqual(master_mob.slots[0].media_kind, 'Sound', "MasterMob slot has incorrect media_kind") source_clip = master_mob.slots[0].segment.components[0] descriptor = source_clip.mob.descriptor self.assertIsNotNone(descriptor, "File SourceMob has no WAVEDescriptor") self.assertIsInstance(descriptor, aaf2.essence.AIFCDescriptor, "File SourceMob has no AIFCDescriptor") self.assertIsNotNone( descriptor['Summary'].value, "AIFCDescriptor missing required 'Summary' property")
def test_delete_propetry(self): result_file = common.get_test_file('delete.aaf') with aaf2.open(result_file, 'w') as f: m = f.create.MasterMob() m['AppCode'].value = 14 m.usage = 'Usage_LowerLevel' f.content.mobs.append(m) with aaf2.open(result_file, 'rw') as f: mob = list(f.content.mobs)[0] assert 'AppCode' in mob assert 'UsageCode' in mob del mob['AppCode'] del mob['UsageCode'] assert 'AppCode' not in mob assert 'UsageCode' not in mob with self.assertRaises(KeyError): del mob['AppCode'] with aaf2.open(result_file, 'r') as f: mob = list(f.content.mobs)[0] assert 'AppCode' not in mob assert 'UsageCode' not in mob with self.assertRaises(KeyError): del mob['AppCode']
def test_basic_audio_link(self): audio_profile_name = 'pcm_48000_s24le' sample_format = audio.pcm_profiles[audio_profile_name]['sample_format'] sample_rate = audio.pcm_profiles[audio_profile_name]['sample_rate'] audio_duration = 1 audio_sample = common.generate_pcm_audio_mono( audio_profile_name, sample_format=sample_format, sample_rate=sample_rate, duration=audio_duration, fmt='mxf_opatom') meta = common.probe(audio_sample) audio_mob_id = mobid.MobID( meta['format']['tags']['material_package_umid']) audio_source_mob_id = mobid.MobID( meta['streams'][0]['tags']['file_package_umid']) new_file = os.path.join(common.sandbox(), 'mxf_link_audio.aaf') with aaf2.open(new_file, 'w') as f: f.content.link_external_mxf(audio_sample) with aaf2.open(new_file, 'r') as f: assert len(f.content.mobs) == 2 for mob in f.content.mobs: if isinstance(mob, mobs.MasterMob): assert mob.mob_id == audio_mob_id elif isinstance(mob, mobs.SourceMob): if isinstance(mob.descriptor, essence.PCMDescriptor): assert mob.mob_id == audio_source_mob_id
def test_dnxhd(self): frames = 3 for profile_name in [ 'dnx_1080p_36_23.97', 'dnx_720p_90x_25', 'dnx_1080i_120_25', 'dnx_1080p_175x_23.97' ]: new_file = os.path.join(common.sandbox(), '%s_import_essence.aaf' % profile_name) sample = common.generate_dnxhd(profile_name, '%s-import.dnxhd' % profile_name, frames=frames) with aaf2.open(new_file, 'w') as f: profile = video.dnx_profiles.get(profile_name) mob = f.create.MasterMob(profile_name) f.content.mobs.append(mob) mob.import_dnxhd_essence(sample, profile['frame_rate']) with aaf2.open(new_file, 'r') as f: mob = next(f.content.sourcemobs()) stream = mob.essence.open('r') dump_path = os.path.join(common.sample_dir(), '%s-import-dump.dnxhd' % profile_name) with io.open(dump_path, 'wb') as out: out.write(stream.read()) assert common.compare_files(dump_path, sample) assert mob.slots[0].segment.length == frames assert mob.descriptor.length == frames
def test_create(self): new_file = os.path.join(common.sandbox(), 'create_essence.aaf') test_data = b"Essence Data!!" mob_id = aaf2.mobid.MobID() mob_id.int = 1 with aaf2.open(new_file, 'w') as f: mob = f.create.SourceMob() mob.descriptor = f.create.TapeDescriptor() f.content.mobs.append(mob) e = f.create.EssenceData() e.mob = mob f.content.essencedata.append(e) stream = e.open("w") stream.write(test_data) e.mob = mob mob.mob_id = mob_id e.mob_id = mob_id with aaf2.open(new_file, 'r') as f: e = next(f.content.essencedata.values()) assert e.mob_id == mob_id stream = e.open("r") assert stream.read() == test_data mob = e.mob assert mob
def test_add_extension_existing(self): test_file = common.get_test_file('extension_add_existing.aaf') shutil.copy(common.test_file_01(), test_file) original_pids = [] original_classdefs_count = None original_typedef_count = None with aaf2.open(test_file, 'r') as f: original_classdefs_count = len(f.metadict['ClassDefinitions']) original_typedef_count = len(f.metadict['TypeDefinitions']) for classdef in f.metadict['ClassDefinitions'].values(): # make sure non of the properties and dynamics for pdef in classdef['Properties'].values(): pid = pdef['LocalIdentification'].value if pdef['LocalIdentification'].value >= 0x8000: original_pids.append(pid) # open files 'rw' and add extensions with aaf2.open(test_file, 'rw', extensions=True) as f: pass all_pids = [] with aaf2.open(test_file, 'r') as f: new_classdefs_count = len(f.metadict['ClassDefinitions']) new_typedef_count = len(f.metadict['TypeDefinitions']) for classdef in f.metadict['ClassDefinitions'].values(): for pdef in classdef['Properties'].values(): pid = pdef['LocalIdentification'].value # make sure there are no duplicate pids self.assertTrue(pid not in all_pids) all_pids.append(pid) self.assertTrue(new_classdefs_count > original_classdefs_count) self.assertTrue(new_typedef_count > original_typedef_count)
def test_register(self): result_file = common.get_test_file('register_class.aaf') test_classdef_uuid = UUID(int=1) test_prop_uuid = UUID(int=42) test_prop_pid = 0xBEEF parent_class_name = 'EssenceDescriptor' with aaf2.open(result_file, 'w') as f: test_classdef = f.metadict.register_classdef( "TestClass", test_classdef_uuid, parent_class_name, True) assert isinstance(test_classdef, aaf2.metadict.ClassDef) p = test_classdef.register_propertydef("TheAnswer", test_prop_uuid, test_prop_pid, 'aafInt64', True, False) assert isinstance(p, aaf2.metadict.PropertyDef) with aaf2.open(result_file, 'r') as f: parent_classdef = f.metadict.lookup_classdef(parent_class_name) test_classdef = f.metadict.lookup_classdef('TestClass') self.assertTrue(test_classdef.uuid == test_classdef_uuid) self.assertTrue(test_classdef.class_name == "TestClass") self.assertTrue(test_classdef.parent is parent_classdef) p = test_classdef['Properties'].value[0] self.assertTrue(p.uuid == test_prop_uuid) self.assertTrue(p.pid == test_prop_pid) self.assertTrue(p.property_name == "TheAnswer") prop_typedef = f.metadict.lookup_typedef("aafInt64") self.assertTrue(p.typedef is prop_typedef)
def test_basic_video_link(self): profile_name = 'dnx_1080p_36_23.97' video_sample = common.generate_dnxhd(profile_name, "mxf_link_video.mxf", 10, fmt='mxf_opatom') meta = common.probe(video_sample) video_mob_id = mobid.MobID( meta['format']['tags']['material_package_umid']) video_source_mob_id = mobid.MobID( meta['streams'][0]['tags']['file_package_umid']) new_file = os.path.join(common.sandbox(), 'mxf_link_video.aaf') with aaf2.open(new_file, 'w') as f: f.content.link_external_mxf(video_sample) with aaf2.open(new_file, 'r') as f: assert len(f.content.mobs) == 2 for mob in f.content.mobs: if isinstance(mob, mobs.MasterMob): assert mob.mob_id == video_mob_id elif isinstance(mob, mobs.SourceMob): if isinstance(mob.descriptor, essence.CDCIDescriptor): assert mob.mob_id == video_source_mob_id
def test_dnxhr(self): frame_rate = '23.97' uhd2160 = (960, 540) frames = 3 timecode_fps = 30 start_time = int(timecode_fps * 60 * 60) # 1 hour for profile_name in ['dnxhr_lb', 'dnxhr_sq', 'dnxhr_hq']: new_file = os.path.join(common.sandbox(), '%s_import_essence.aaf' % profile_name) with aaf2.open(new_file, 'w') as f: profile = video.dnx_profiles.get(profile_name) sample = common.generate_dnxhd(profile_name, "%s-import.dnxhd" % profile_name, frames=frames, size=uhd2160, frame_rate=frame_rate) # create a tape tape_mob = f.create.SourceMob() tape_mob.create_tape_slots(profile_name, frame_rate, timecode_fps) f.content.mobs.append(tape_mob) tape = tape_mob.create_source_clip(1, start=start_time) mob = f.create.MasterMob(profile_name) f.content.mobs.append(mob) timecode = f.create.Timecode(timecode_fps) mob.import_dnxhd_essence(sample, frame_rate, tape=tape) with aaf2.open(new_file, 'r') as f: source_mobs = [] tape_mobs = [] for mob in f.content.sourcemobs(): if isinstance(mob.descriptor, aaf2.essence.TapeDescriptor): tape_mobs.append(mob) else: source_mobs.append(mob) mob = source_mobs[0] stream = mob.essence.open('r') dump_path = os.path.join(common.sample_dir(), '%s-import-dump.dnxhd' % profile_name) with io.open(dump_path, 'wb') as out: out.write(stream.read()) assert common.compare_files(dump_path, sample) assert mob.slots[0].segment.length == frames assert mob.slots[0].segment.start == start_time assert mob.descriptor.length == frames
def test_wav(self): # name, sample_rate = 48000, duration = 2, sample_fmt='s16le', format='wav'): # profile_name = 'pcm_48000_s24le' frame_rate = 30 timecode_fps = 30 start_time = int(timecode_fps * 60 * 60) * 2 duration = 1.5 for profile_name in sorted(audio.pcm_profiles): sample_format = audio.pcm_profiles[profile_name]['sample_format'] sample_rate = audio.pcm_profiles[profile_name]['sample_rate'] sample = common.generate_pcm_audio_mono( profile_name, sample_format=sample_format, sample_rate=sample_rate, duration=duration) new_file = os.path.join(common.sandbox(), '%s_import_essence.aaf' % profile_name) with aaf2.open(new_file, 'w') as f: tape_mob = f.create.SourceMob() f.content.mobs.append(tape_mob) tape_mob.create_tape_slots(profile_name, frame_rate, timecode_fps, media_kind='sound') tape = tape_mob.create_source_clip(1, start_time) mob = f.create.MasterMob(profile_name) f.content.mobs.append(mob) mob.import_audio_essence(sample, frame_rate, tape) with aaf2.open(new_file, 'r') as f: source_mobs = [] tape_mobs = [] for mob in f.content.sourcemobs(): if isinstance(mob.descriptor, aaf2.essence.TapeDescriptor): tape_mobs.append(mob) else: source_mobs.append(mob) mob = source_mobs[0] tape_mob = tape_mobs[0] stream = mob.essence.open('r') dump_path = os.path.join(common.sample_dir(), '%s-import-dump.wav' % profile_name) mob.export_audio(dump_path) assert common.compare_files(dump_path, sample) audio_samples = mob.descriptor['Length'].value assert audio_samples == sample_rate * duration edit_length = duration * frame_rate assert mob.slots[0].segment.length == edit_length assert mob.slots[0].segment.start == start_time assert mob.slots[0].segment.mob_id == tape_mob.mob_id
def test_no_root_class(self): # make sure we don't write the root_class definition result_file = common.get_test_file('root_tess.aaf') with aaf2.open(result_file, 'w') as f: pass root_uuid = UUID('b3b398a5-1c90-11d4-8053-080036210804') with aaf2.open(result_file, 'r') as f: for classdef in f.metadict['ClassDefinitions'].value: self.assertFalse(classdef.class_name == "Root") self.assertFalse(classdef.uuid == root_uuid)
def test_mob_id_swap(self): new_file = os.path.join(common.sandbox(), 'swap_id.aaf') test_file = common.test_file_01() shutil.copy(test_file, new_file) new_mobid = aaf2.mobid.MobID.new() with aaf2.open(new_file, 'rw') as f: comp = next(f.content.compositionmobs()) comp.mob_id = new_mobid with aaf2.open(new_file, 'r') as f: comp = next(f.content.compositionmobs()) assert comp.mob_id == new_mobid
def test_save_as(self): new_file = os.path.join(common.sandbox(), 'save_r+.aaf') test_file = common.test_file_01() shutil.copy(test_file, new_file) with aaf2.open(new_file, 'r+') as f: f.save() # should contents compare! with aaf2.open(new_file, 'r') as f: common.walk_aaf(f.root)
def test_duplicate_pids_add(self): result_file = common.get_test_file('duplicate_pids_add.aaf') with aaf2.open(result_file, 'w', extensions=False) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'rw', extensions=True) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f))
def test_operationdef(self): result_file = common.get_test_file('operation_def.aaf') parm_id = uuid.uuid4() effect_id = uuid.uuid4() with aaf2.open(result_file, 'w') as f: typedef = f.dictionary.lookup_typedef("Rational") param = f.create.ParameterDef(parm_id, "AvidEffectID", "avid effect id", typedef) f.dictionary.register_def(param) op_def = f.create.OperationDef(effect_id, "MatteKey_2", "matte key def") op_def.media_kind = "Picture" f.dictionary.register_def(op_def) op_def['IsTimeWarp'].value = False op_def['Bypass'].value = 2 op_def['NumberInputs'].value = 3 op_def['OperationCategory'].value = "OperationCategory_Effect" op_def['ParametersDefined'].append(param) length = 100 operation = f.create.OperationGroup(op_def, length) mob = f.create.MasterMob() f.content.mobs.append(mob) slot = mob.create_picture_slot() slot.segment.components.append(operation) with aaf2.open(result_file, 'r') as f: param = f.dictionary.lookup_parameterdef('AvidEffectID') assert param.uuid == parm_id op_def = f.dictionary.lookup_operationdef("MatteKey_2") assert op_def.uuid == effect_id assert op_def.media_kind == 'Picture' assert op_def['IsTimeWarp'].value == False assert op_def['Bypass'].value == 2 assert op_def['NumberInputs'].value == 3 assert op_def[ 'OperationCategory'].value == "OperationCategory_Effect" assert param in op_def['ParametersDefined'].value mob = next(f.content.mobs.values()) slot = mob.slots.value[0] op = slot.segment.components.value[0] assert op.operation == op_def
def test_reattach512(self): new_file = os.path.join(common.sandbox(), 'test_reattach512.aaf') test_file = common.test_file_512() shutil.copy(test_file, new_file) mob_ids = [] original_child_count = 0 with aaf2.open(new_file, 'r+') as f: mobs = f.content['Mobs'].value for m in mobs: for item, streams in m.walk_references(): assert item.dir is not None original_child_count += 1 assert original_child_count > len(mobs) mob_ids = [m.mob_id for m in mobs] f.content['Mobs'].value = [] child_count = 0 for m in mobs: for item, streams in m.walk_references(): assert item.dir is None child_count += 1 assert child_count == original_child_count f.content['Mobs'].value = mobs child_count = 0 for m in mobs: for item, streams in m.walk_references(): assert item.dir is not None child_count += 1 assert child_count == original_child_count with aaf2.open(new_file, 'r') as f: for mob_id in mob_ids: assert f.content.mobs.get(mob_id, None) is not None mobs = f.content['Mobs'].value child_count = 0 for m in mobs: for item, streams in m.walk_references(): assert item.dir is not None child_count += 1 assert child_count == original_child_count
def test_duplicate_pids_existing(self): result_file = common.get_test_file('duplicate_pids_existing.aaf') shutil.copy(common.test_file_01(), result_file) with aaf2.open(result_file, 'w', extensions=False) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'rw', extensions=True) as f: self.assertFalse(has_duplicate_pid(f)) with aaf2.open(result_file, 'r') as f: self.assertFalse(has_duplicate_pid(f))
def test_write_dettached_clean(self): new_file = os.path.join(common.sandbox(), 'essencedata_dettached_clean.aaf') test_data = b"Essence Data!!" mob_id = aaf2.mobid.MobID() mob_id.int = 1 with aaf2.open(new_file, 'w') as f: e = f.create.EssenceData() e.mob_id = mob_id stream = e.open("w") stream.write(test_data) with aaf2.open(new_file, 'r') as f: assert not f.cfb.exists("/tmp")
def create_aaf(path, media_streams, mobname, tape_name=None, start_timecode=None): with aaf2.open(path, 'w') as f: mastermob = f.create.MasterMob(mobname) f.content.mobs.append(mastermob) edit_rate = None for stream in media_streams: if stream['type'] == 'video': edit_rate = fractions.Fraction(stream['frame_rate']) break alpha = False compmob = None for stream in media_streams: if stream.get('path_alpha', False): alpha = True compmob = f.create.CompositionMob(mastermob.name) compmob.usage = 'Usage_Template' f.content.mobs.append(compmob) # this hides the mastermob in avid bin mastermob['AppCode'].value = 1 mastermob.usage = "Usage_LowerLevel" break tapemob = None timecode_fps = int(round(float(edit_rate))) if tape_name: tapemob = f.create.SourceMob() tapemob.create_tape_slots(tape_name, edit_rate, timecode_fps) f.content.mobs.append(tapemob) for stream in media_streams: if stream['type'] == 'video': print "importing video..." start = time.time() import_video_essence(f, mastermob, stream, compmob, tapemob) print "imported video in %f secs" % (time.time() - start) for stream in media_streams: if stream['type'] == 'audio': print "importing audio..." start = time.time() sample_rate = stream['sample_rate'] slot = mastermob.import_audio_essence(stream['path'], edit_rate) if compmob: sound_slot = compmob.create_sound_slot(edit_rate) sound_slot.segment = mastermob.create_source_clip( slot.slot_id, length=slot.segment.length) print "imported audio in %f secs" % (time.time() - start)
def read_from_file(filepath, simplify=True): f = aaf2.open(filepath) storage = f.content # Note: We're skipping: f.header # Is there something valuable in there? __names.clear() masterMobs = {} result = _transcribe(storage, masterMobs=masterMobs) top = storage.toplevel() if top: # re-transcribe just the top-level mobs # but use all the master mobs we found in the 1st pass __names.clear() # reset the names back to 0 result = _transcribe(top, masterMobs=masterMobs) # AAF is typically more deeply nested than OTIO. # Lets try to simplify the structure by collapsing or removing # unnecessary stuff. if simplify: result = _simplify(result) # OTIO represents transitions a bit different than AAF, so # we need to iterate over them and modify the items on either side. # Note that we do this *after* simplifying, since the structure # may change during simplification. _fix_transitions(result) return result
def test_wav_link(self): test_outfile = os.path.join(common.sandbox(), 'wav_link.aaf') test_link_targets = [ common.generate_pcm_audio_mono('testmono', sample_rate=48000, duration=10, sample_format='pcm_s16le', fmt='wav'), common.generate_pcm_audio_mono('testmono24', sample_rate=48000, duration=10, sample_format='pcm_s24le', fmt='wav'), common.generate_pcm_audio_stereo('testmono', sample_rate=48000, duration=10, sample_format='pcm_s24le', fmt='wav') ] with aaf2.open(test_outfile, 'w') as f: for target in test_link_targets: meta = common.probe(target) mobs = f.content.link_external_wav(meta)
def list_headers_lengths(aaf_file): global curr_header_len global curr_file_len f = aaf2.open(aaf_file) lengths = [] for mob in f.content.mobs: if hasattr(mob, 'slots'): # We're looking for the long one - let's filter out all the shorter properties if (len(mob.slots) > 3): for i in range(len(mob.slots)): curr_track_name = mob.slot_at(i).name # get_length(mob.slot_at(i)) if hasattr(mob.slot_at(i), 'segment'): # print(type(mob)) if hasattr(mob.slot_at(i).segment, 'components'): for s in mob.slot_at(i).segment.components: get_length(s) # print(type(s)) if curr_track_name != "Timecode": lengths.append( [curr_track_name, curr_header_len, curr_file_len]) curr_header_len = 0 curr_file_len = 0 return lengths
def setFilePath(self, path): print(path) f = aaf2.open(file_path) root = f.content if options.toplevel: root = list(f.content.toplevel()) if options.compmobs: root = list(f.content.compositionmobs()) if options.mastermobs: root = list(f.content.mastermobs()) if options.sourcemobs: root = list(f.content.GetSourceMobs()) if options.dictionary: root = f.dictionary if options.metadict: root = f.metadict if options.root: root = f.root model = AAFModel(root) self.setModel(model) self.setWindowTitle(file_path) self.expandToDepth(1) self.resizeColumnToContents(0) self.resizeColumnToContents(1)
def avb2aaf_main(path): with avb.open(path) as avb_file: with aaf2.open(path + ".aaf", 'w') as aaf_file: register_definitions(aaf_file) avb_file.content.build_mob_dict() avb2aaf(aaf_file, avb_file)
def write_to_file(input_otio, filepath, **kwargs): with aaf2.open(filepath, "w") as f: timeline = aaf_writer._stackify_nested_groups(input_otio) aaf_writer.validate_metadata(timeline) otio2aaf = aaf_writer.AAFFileTranscriber(timeline, f, **kwargs) if not isinstance(timeline, otio.schema.Timeline): raise otio.exceptions.NotSupportedError( "Currently only supporting top level Timeline") for otio_track in timeline.tracks: # Ensure track must have clip to get the edit_rate if len(otio_track) == 0: continue transcriber = otio2aaf.track_transcriber(otio_track) for otio_child in otio_track: result = transcriber.transcribe(otio_child) if result: transcriber.sequence.components.append(result)
def test_prores(self): new_file = os.path.join(common.sandbox(), 'prores_mov.aaf') with aaf2.open(new_file, 'w') as f: for profile, name in prores_profiles: vcodec = ['-c:v', 'prores_ks', '-profile:v', str(profile)] mov = common.generate_mov('ama_prores_%s.mov' % (name, ), overwrite=False, vcodec=vcodec) meta = common.probe(mov) mobs = f.content.create_ama_link(mov, meta) # for (pix_fmt, profile) in avc_profiles: with aaf2.open(new_file, 'r') as f: common.walk_aaf(f.root)
def skip_test_retime_manually(self): test_file = os.path.join(common.test_files_dir(), 'retimes/spline02.aaf') test_file = os.path.join(common.test_files_dir(), 'retimes/spline04.aaf') # compare_speedmap_to_offset_map(test_file) # manual testing here import matplotlib.pyplot as plt import numpy as np with aaf2.open(test_file) as f: op_group, speed_map, offset_map = find_retime(f) target = [[], []] p0 = offset_map['PointList'].value[0] # p0.dump() sp0 = speed_map['PointList'].value[0] sp0.dump() # p0 = speed_map['PointList'].value[0] # for i in range(0, 200): # target[0].append(i) # target[1].append(offset_map.value_at(i)) for item in offset_map['PointList'].value: target[0].append(item.time) target[1].append(item.value) start = int(p0.time) print(p0.time) # op_group[1].dump() # print(end, p_last.time) pos = 0 error_list = [] offset_map_gen = generate_offset_map(speed_map, start, op_group[0].length) calcuated = [[], []] for t, v in offset_map_gen: calcuated[0].append(t) calcuated[1].append(v) tar = offset_map.value_at(t) error = abs(tar - v) print(t, error, tar, pos) error_list.append(error) print("average error:", sum(error_list) / len(error_list)) plt.plot(target[0], target[1]) plt.plot(calcuated[0], calcuated[1]) plt.show()
def test_avc_mov(self): new_file = os.path.join(common.sandbox(), 'avc_mov.aaf') audio_channel_count = 2 created_mastermob_ids = [] with aaf2.open(new_file, 'w') as f: for (pix_fmt, profile) in avc_profiles: vcodec = [ '-pix_fmt', pix_fmt, '-c:v', 'h264', '-profile:v', profile ] mov = common.generate_mov('ama_avc_%s.mov' % profile, overwrite=False, vcodec=vcodec, audio_channels=audio_channel_count) meta = common.probe(mov) # print(meta['streams'][0]['profile']) mobs = f.content.create_ama_link(mov, meta) self.assertEqual(len(mobs), 3) self.assertIsInstance(mobs[0], aaf2.mobs.MasterMob) self.assertIsInstance(mobs[1], aaf2.mobs.SourceMob) self.assertIsInstance(mobs[2], aaf2.mobs.SourceMob) created_mastermob_ids.append(mobs[0].mob_id) with aaf2.open(new_file, 'r') as f: common.walk_aaf(f.root) self.assertEqual( len(f.content.mobs), len(avc_profiles) * 3, "Failed to create exactly three MOBs per avc_profile") self.assertEqual( len(list(f.content.mastermobs())), len(avc_profiles), "Failed to create exactly one MasterMOB per avc_profile") for mastermob_id in created_mastermob_ids: mastermob = next( (mob for mob in f.content.mobs if mob.mob_id == mastermob_id), None) self.assert_mastermob_valid_edit_spec(mastermob, expected_picture_slots=1, expected_sound_slots=2) self.assert_valid_multiple_descriptor(mastermob, audio_channel_count)
def __init__(self, aaf_filepath, aaf_sr=44100): self.path = aaf_filepath self.f = aaf2.open(self.path, "w") self.aaf_sr = aaf_sr self.filepath_to_mob = {} self.alltrackcnt = 0 self.tracknames = [] self.comp_mob = self.f.create.CompositionMob("Composition") self.f.content.mobs.append(self.comp_mob)
def markers2titles(markers, pct_path, dest): with aaf2.open(dest, 'w') as f: setup_title_operation_def(f) # for text in ('title_01', 'cow', 'pig', 'dog', u'whatever', 'nik', 'mark'): for text in markers: print(text) pct_data = apply_template(pct_path, text) create_title(f, pct_data, text)