Open davidnorden opened 1 year ago
I think group clips are actually 'selector's - the active clip being selected and the others 'alternatives'.
Although chatgpt mentions 'essence groups' too
Still trying to get my head around it...
Yes GroupClips are called selectors. EssenceGroups are different, they are use for different quality levels of the same media. Essence is what AAF calls media.
I wouldn't trust any code chatgpt gives you for using this library. There aren't enough examples in the wild for it to steal code from.
This is as far as I can get by myself!
Something wrong in how I append the selector (e.g. do I need the selector_sequence?)
Hopefully someone (@markreidvfx) can point out the errors of my ways...
import sys
import aaf2
import json
import os
from datetime import datetime
file_name = "./testSelector.aaf"
edit_rate = 50
sequence_start = 1*60*60*edit_rate
sequence_length = 20*edit_rate
dictMobID = {}
with aaf2.open(file_name, "w") as f:
# Composition Mob created first
comp_mob = f.create.CompositionMob()
comp_mob.usage = "Usage_TopLevel"
comp_mob.name = "test"
# Create a TimelineMobSlot with a Timecode Segment for the start timecode
tc_segment = f.create.Timecode(edit_rate)
tc_segment.start = sequence_start
tc_slot = comp_mob.create_timeline_slot(edit_rate, slot_id=1)
tc_slot.segment = tc_segment
# Create Selector Composition Mob outside the Master MOBs loop
selector_comp_mob = f.create.CompositionMob()
selector_comp_mob.usage = "Usage_TopLevel"
selector_comp_mob.name = "GRP - sequence test"
selector_sequence = f.create.Sequence(media_kind="picture")
selector_timeline_slot = selector_comp_mob.create_timeline_slot(edit_rate)
selector_timeline_slot.segment = selector_sequence
selector_timeline_slot.name = "GRP-TrackC"
# Make the Master MOBs
for i in range(1,5):
tape_name= f"tapeName_{i}"
# Make the Tape MOB
tape_mob = f.create.SourceMob()
tape_slot, tape_timecode_slot = tape_mob.create_tape_slots(tape_name, edit_rate, edit_rate)
# Set start time for clip
tape_timecode_slot.segment.start = sequence_start
# Reduce from default 12 hour length
tape_slot.segment.length = sequence_length
f.content.mobs.append(tape_mob)
# Make a FileMob
file_mob = f.create.SourceMob()
file_description = f.create.CDCIDescriptor()
file_description['ComponentWidth'].value = 8
file_description['HorizontalSubsampling'].value = 4
file_description['ImageAspectRatio'].value = '16/9'
file_description['StoredWidth'].value = 1920
file_description['StoredHeight'].value = 1080
file_description['FrameLayout'].value = 'FullFrame'
file_description['VideoLineMap'].value = [42, 0]
file_description['SampleRate'].value = edit_rate
file_description['Length'].value = sequence_length
file_mob.descriptor = file_description
# This length affects length of master mob and in timeline
tape_clip = tape_mob.create_source_clip(slot_id=1, length=sequence_length)
slot = file_mob.create_picture_slot(edit_rate)
slot.segment.components.append(tape_clip)
f.content.mobs.append(file_mob)
master_mob = f.create.MasterMob()
master_mob.name = f"MM_name_{i}"
clip = file_mob.create_source_clip(slot_id=1)
slot = master_mob.create_picture_slot(edit_rate)
slot.segment.components.append(clip)
dictMobID[i] = master_mob
f.content.mobs.append(master_mob)
for i in range(1,2):
sequence = f.create.Sequence(media_kind="picture")
timeline_slot = comp_mob.create_timeline_slot(edit_rate)
timeline_slot.segment= sequence
timeline_slot.name = "SRC"
dictClipID = {}
clip_position = 200
for key in dictMobID:
mm = dictMobID[key]
# print(mm.mob_id)
clip_start = 0
clip_length = 2*edit_rate
# Create a SourceClip
clip = mm.create_source_clip(slot_id=1)
# print(str((clip.mob_id)))
# This is the start point of the master mob in the source clip?
clip.start = clip_position
# This is the length of the source clip - filled with the master mob
clip.length = clip_length
dictClipID[key] = clip
sequence.components.append(clip)
# Attempt at creating selector
selector = f.create.Selector()
selector.media_kind = "picture"
# Set the first clip as selected and rest as alternates
first_clip = True
for clip in dictClipID.values():
if first_clip:
selector['Selected'].value = clip
first_clip = False
# else:
selector['Alternates'].append(clip)
selector_sequence.components.append(selector)
sequence.components.append(selector_sequence)
# Append your main composition mob at the end
f.content.mobs.append(comp_mob)
errror message:
raise AAFAttachError("cannot attached obj to %s already attached to %s" % (dir_entry.path(), self.dir.path()))
aaf2.exceptions.AAFAttachError: cannot attached obj to /Header-2/Content-3b03/Mobs-1901{c}/Slots-4403{1}/Segment-4803/Components-1001{4}/Components-1001{0}/Selected-f01 already attached to /Header-2/Content-3b03/Mobs-1901{c}/Slots-4403{1}/Segment-4803/Components-1001{0}
You need to create a timeline (f.create.CompositionMob). Then in this timeline, create a sequence (f.create.Sequence). Then add in this sequence components the selectors (f.create.Selector). And in this selector, you need to create “sub clips”, depending on your needs, logic, it will vary, but usually create_source_clip method on your “object” with slot id, start and length.
On 1 Mar 2024, at 13:17, TrevorAyl @.***> wrote:
This is as far as I can get by myself!
Something wrong in how I append the selector (e.g. do I need the selector_sequence?)
Hopefully someone @.*** https://github.com/markreidvfx) can point out the errors of my ways...
import sys import aaf2 import json import os import logging from datetime import datetime
file_name = "./testSelector.aaf" edit_rate = 50 sequence_start = 16060edit_rate sequence_length = 20edit_rate dictMobID = {}
with aaf2.open(file_name, "w") as f:
Composition Mob created first
comp_mob = f.create.CompositionMob() comp_mob.usage = "Usage_TopLevel" comp_mob.name = "test" # Create a TimelineMobSlot with a Timecode Segment for the start timecode tc_segment = f.create.Timecode(edit_rate) tc_segment.start = sequence_start tc_slot = comp_mob.create_timeline_slot(edit_rate, slot_id=1) tc_slot.segment = tc_segment # nested_slot = comp_mob.create_timeline_slot(edit_rate) # nested_slot['PhysicalTrackNumber'].value = 1 # nested_scope = f.create.NestedScope() # nested_slot.segment= nested_scope # Create Selector Composition Mob outside the Master MOBs loop selector_comp_mob = f.create.CompositionMob() selector_comp_mob.usage = "Usage_TopLevel" selector_comp_mob.name = "GRP - sequence test" selector_sequence = f.create.Sequence(media_kind="picture") selector_timeline_slot = selector_comp_mob.create_timeline_slot(edit_rate) selector_timeline_slot.segment = selector_sequence selector_timeline_slot.name = "GRP-TrackC" # Make the Master MOBs for i in range(1,5): tape_name= f"tapeName_{i}" # Make the Tape MOB tape_mob = f.create.SourceMob() tape_slot, tape_timecode_slot = tape_mob.create_tape_slots(tape_name, edit_rate, edit_rate) # set start time for clip tape_timecode_slot.segment.start = sequence_start #Reduces from default 12 hours tape_slot.segment.length = sequence_length f.content.mobs.append(tape_mob) # Make a FileMob - not sure where this goes? file_mob = f.create.SourceMob() file_description = f.create.CDCIDescriptor() file_description['ComponentWidth'].value = 8 file_description['HorizontalSubsampling'].value = 4 file_description['ImageAspectRatio'].value = '16/9' file_description['StoredWidth'].value = 1920 file_description['StoredHeight'].value = 1080 file_description['FrameLayout'].value = 'FullFrame' file_description['VideoLineMap'].value = [42, 0] file_description['SampleRate'].value = edit_rate file_description['Length'].value = sequence_length file_mob.descriptor = file_description # This length affects length of master mob and in timeline tape_clip = tape_mob.create_source_clip(slot_id=1, length=sequence_length) slot = file_mob.create_picture_slot(edit_rate) slot.segment.components.append(tape_clip) f.content.mobs.append(file_mob) master_mob = f.create.MasterMob() master_mob.name = f"MM_name_{i}" clip = file_mob.create_source_clip(slot_id=1) slot = master_mob.create_picture_slot(edit_rate) slot.segment.components.append(clip) dictMobID[i] = master_mob f.content.mobs.append(master_mob) for i in range(1,2): sequence = f.create.Sequence(media_kind="picture") timeline_slot = comp_mob.create_timeline_slot(edit_rate) timeline_slot.segment= sequence timeline_slot.name = "SRC" dictClipID = {} clip_position = 200 for key in dictMobID: mm = dictMobID[key] # print(mm.mob_id) clip_start = 0 clip_length = 2*edit_rate # Create a SourceClip clip = mm.create_source_clip(slot_id=1) # print(str((clip.mob_id))) # This is the start point of the master mob in the source clip? clip.start = clip_position # This is the length of the source clip - filled with the master mob clip.length = clip_length dictClipID[key] = clip sequence.components.append(clip) # Attempt at creating selector selector = f.create.Selector() selector.media_kind = "picture" # Set the first clip as selected and rest as alternates first_clip = True for clip in dictClipID.values(): if first_clip: selector['Selected'].value = clip first_clip = False # else: # # This is pseudo-code; you'll need to adjust how alternates are added based on pyaaf2's API # selector.alternates.append(clip) selector_sequence.components.append(selector) sequence.components.append(selector_sequence) # # Finally, append selector_comp_mob to the content # f.content.mobs.append(selector_comp_mob) # Append your main composition mob at the end f.content.mobs.append(comp_mob)
— Reply to this email directly, view it on GitHub https://github.com/markreidvfx/pyaaf2/issues/118#issuecomment-1973088207, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH6PWVLAGMHPX72LIOOINLYWBWWBAVCNFSM6AAAAAAWT66PUWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNZTGA4DQMRQG4. You are receiving this because you are subscribed to this thread.
I am trying to export group clips from an avb-file, and assume it should be possible since there is already a script that exports a sequence as an aaf from a avb-file (using pyavb). Both are composition mobs, and exporting a group clip from Media Composer and importing into Premiere Pro will show that Premiere Pro interprets the aaf for a group clip as a sequence. So what is the unique identifier in the aaf-file that lets Media Composer know that the group clip is NOT a sequence (since both are composition mobs...) Does anyone know?