Problem
Hi,
I was trying to roundtrip a multi-video-track AAF file through otioconvert and I noticed the output file doesnt behave the same as the input when I tried to open it in DaVinci Resolve. Resolve interprets each video track as a separate independent timeline instead of a single multi-track composition.
Im not sure whether Im not using the adapter correctly or if this is a genuine bug, so I wanted to share what I observed.
What I observed in the reference file
Inspecting sample multitrack.aaf with:
import aaf2
with aaf2.open('multitrack.aaf') as f:
for mob in f.content.compositionmobs():
for slot in mob.slots:
print('slot_id:', slot.slot_id,
'physical:', slot['PhysicalTrackNumber'].value,
'type:', type(slot.segment).__name__)
gives
slot_id: 1 physical: 1 type: Timecode
slot_id: 2 physical: 1 type: NestedScope
slot_id: 3 physical: 1 type: Sequence (Audio 1)
slot_id: 4 physical: 2 type: Sequence (Audio 2)
All three video tracks live inside a single NestedScope in slot_id: 2. So when I open this file in Resolve, all 3 video tracks are reconstructed correctly.
Roundtrip with simplify=True (default)
Then I roundtrip the file with
otioconvert -i multitrack.aaf -o multitrack.otio
otioconvert -i multitrack.otio -o multitrack2.aaf
Then the NestedScope gets flattened into three independent top level tracks in the OTIO, as the simplify=True is applied. So then when written back to AAF:
slot_id: 2 type: Sequence : was V1, now independent slot
slot_id: 3 type: Sequence : was V2, now independent slot
slot_id: 4 type: Sequence : was V3, now independent slot
slot_id: 5 type: Sequence : Audio 1
slot_id: 6 type: Sequence : Audio 2
slot_id: 7 type: Timecode
Everything is normal here
Roundtrip with simplify=False
But when I try
otioconvert -i multitrack.aaf -o multitrack.otio -a simplify=False
otioconvert -i multitrack.otio -o multitrack2.aaf
With simplify=False the NestedScope is correctly preserved in the OTIO as a nested Stack. However the write step fails with two different errors depending on how it's invoked:
Error 1, when passing the file directly, the read produces a SerializableCollection and the writer crashes:
AttributeError: 'SerializableCollection' object has no attribute 'tracks'
File "aaf_writer.py", line 374, in _stackify_nested_groups
error 2, when extracting the Timeline manually from the collection and passing it directly to write_to_file, the writer crashes in _stackify_nested_groups:
ValueError
File "aaf_writer.py", line 380, in _stackify_nested_groups
track.remove(child)
Question
Then am I using the adapter incorrectly, or is the multi-video-track roundtrip currently not supported despite being listed in the README feature matrix? I couldnt find any example or documentation showing how to correctly roundtrip a multi-video-track AAF.
Also, the documentation for read_from_file states it returns otio.schema.Timeline, but with simplify=False on a multi-mob AAF file it returns a SerializableCollection.
Full bash code :
python3 -c "
import aaf2
with aaf2.open('/path/to/samples/multitrack.aaf') as f:
for mob in f.content.compositionmobs():
for slot in mob.slots:
print('slot_id:', slot.slot_id, 'physical:', slot['PhysicalTrackNumber'].value, 'type:', type(slot.segment).__name__)
"
slot_id: 10 physical: 1 type: Timecode
slot_id: 11 physical: 3 type: Pulldown
slot_id: 12 physical: 2 type: Timecode
slot_id: 13 physical: 4 type: Timecode
slot_id: 14 physical: 5 type: Pulldown
slot_id: 15 physical: 6 type: Pulldown
slot_id: 16 physical: 7 type: Pulldown
slot_id: 17 physical: 1 type: EdgeCode
slot_id: 9 physical: 1 type: NestedScope
slot_id: 1008 physical: 1 type: Sequence
slot_id: 1009 physical: 2 type: Sequence
slot_id: 1010 physical: 3 type: Sequence
slot_id: 20 physical: 1 type: Sequence
slot_id: 21 physical: 1 type: OperationGroup
slot_id: 22 physical: 2 type: OperationGroup
otioconvert -i /path/to/samples/multitrack.aaf -o /tmp/multitrack.otio
otioconvert -i /tmp/multitrack.otio -o /tmp/multitrack2.aaf
python3 -c "
import aaf2
with aaf2.open('/tmp/multitrack2.aaf') as f:
for mob in f.content.compositionmobs():
for slot in mob.slots:
print('slot_id:', slot.slot_id, 'physical:', slot['PhysicalTrackNumber'].value, 'type:', type(slot.segment).__name__)
"
slot_id: 1 physical: None type: Sequence
slot_id: 2 physical: None type: Sequence
slot_id: 3 physical: None type: Sequence
slot_id: 4 physical: None type: OperationGroup
slot_id: 5 physical: None type: OperationGroup
slot_id: 6 physical: 1 type: Timecode
python3 -c "
import opentimelineio as otio
result = otio.adapters.read_from_file('/tmp/multitrack_nosimplify.otio')
print(type(result).__name__)
"
otioconvert -i /tmp/multitrack_nosimplify.otio -o /tmp/multitrack2.aaf
Traceback (most recent call last):
File ".../bin/otioconvert", line 8, in <module>
sys.exit(main())
File ".../site-packages/opentimelineio/console/otioconvert.py", line 273, in main
otio.adapters.write_to_file(
...
File ".../opentimelineio/adapters/__init__.py", line 203, in write_to_file
return adapter.write_to_file(...)
File ".../otio_aaf_adapter/adapters/advanced_authoring_format.py", line 1941, in write_to_file
timeline = aaf_writer._stackify_nested_groups(hook_tl)
File ".../otio_aaf_adapter/adapters/aaf_adapter/aaf_writer.py", line 374, in _stackify_nested_groups
for track in copied.tracks:
AttributeError: 'SerializableCollection' object has no attribute 'tracks'
python3 -c "
import opentimelineio as otio
col = otio.adapters.read_from_file('/tmp/multitrack_nosimplify.otio')
for item in col:
if isinstance(item, otio.schema.Timeline):
otio.adapters.write_to_file(item, '/tmp/multitrack2.aaf', use_empty_mob_ids=True)
break
"
Traceback (most recent call last):
File "<string>", line 6, in <module>
otio.adapters.write_to_file(...)
File ".../opentimelineio/adapters/__init__.py", line 203, in write_to_file
return adapter.write_to_file(...)
File ".../otio_aaf_adapter/adapters/advanced_authoring_format.py", line 1941, in write_to_file
timeline = aaf_writer._stackify_nested_groups(hook_tl)
File ".../otio_aaf_adapter/adapters/aaf_adapter/aaf_writer.py", line 380, in _stackify_nested_groups
track.remove(child)
ValueError
Problem
Hi,
I was trying to roundtrip a multi-video-track AAF file through otioconvert and I noticed the output file doesnt behave the same as the input when I tried to open it in DaVinci Resolve. Resolve interprets each video track as a separate independent timeline instead of a single multi-track composition.
Im not sure whether Im not using the adapter correctly or if this is a genuine bug, so I wanted to share what I observed.
What I observed in the reference file
Inspecting sample multitrack.aaf with:
gives
All three video tracks live inside a single NestedScope in slot_id: 2. So when I open this file in Resolve, all 3 video tracks are reconstructed correctly.
Roundtrip with simplify=True (default)
Then I roundtrip the file with
Then the NestedScope gets flattened into three independent top level tracks in the OTIO, as the simplify=True is applied. So then when written back to AAF:
Everything is normal here
Roundtrip with simplify=False
But when I try
With simplify=False the NestedScope is correctly preserved in the OTIO as a nested Stack. However the write step fails with two different errors depending on how it's invoked:
Error 1, when passing the file directly, the read produces a SerializableCollection and the writer crashes:
error 2, when extracting the Timeline manually from the collection and passing it directly to write_to_file, the writer crashes in _stackify_nested_groups:
Question
Then am I using the adapter incorrectly, or is the multi-video-track roundtrip currently not supported despite being listed in the README feature matrix? I couldnt find any example or documentation showing how to correctly roundtrip a multi-video-track AAF.
Also, the documentation for read_from_file states it returns otio.schema.Timeline, but with simplify=False on a multi-mob AAF file it returns a SerializableCollection.
Full bash code :