Skip to content

Commit a415c43

Browse files
committed
Update style spec and added fallback OTIO comment if style does not have a spec
1 parent 16607cd commit a415c43

File tree

2 files changed

+154
-58
lines changed

2 files changed

+154
-58
lines changed

src/py-opentimelineio/opentimelineio/adapters/cmx_3600.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ class EDLParseError(exceptions.OTIOError):
6464
# the comment string for the media reference:
6565
# 'avid': '* FROM CLIP:' (default)
6666
# 'nucoda': '* FROM FILE:'
67-
# 'premiere': '' (If Adobe Premiere's imports an EDL that uses
68-
# a "FROM" comment will cause the clips
69-
# to be name UNKNOWN)
67+
# 'premiere': None (If Adobe Premiere's imports an EDL that uses
68+
# a "FROM" comment will cause the clips
69+
# to be name UNKNOWN)
7070
# When adding a new style, please be sure to add sufficient tests
7171
# to verify both the new and existing styles.
7272
VALID_EDL_STYLES = {
7373
'avid': 'CLIP',
7474
'nucoda': 'FILE',
75-
'premiere': '',
75+
'premiere': None,
7676
}
7777

7878

@@ -726,6 +726,7 @@ class CommentHandler:
726726
('ASC_SAT', 'asc_sat'),
727727
('M2', 'motion_effect'),
728728
('\\* FREEZE FRAME', 'freeze_frame'),
729+
('\\* OTIO REFERENCE [a-zA-Z]+', 'media_reference'),
729730
])
730731

731732
def __init__(self, comments):
@@ -979,7 +980,13 @@ def __init__(
979980
reelname_len
980981
):
981982

982-
line = EventLine(kind, rate, reel=_reel_from_clip(clip, reelname_len))
983+
# Premiere style uses AX for the reel name
984+
if style == 'premiere':
985+
reel = 'AX'
986+
else:
987+
reel = _reel_from_clip(clip, reelname_len)
988+
989+
line = EventLine(kind, rate, reel=reel)
983990
line.source_in = clip.source_range.start_time
984991
line.source_out = clip.source_range.end_time_exclusive()
985992

@@ -1219,6 +1226,10 @@ def _generate_comment_lines(
12191226
elif hasattr(clip.media_reference, 'abstract_target_url'):
12201227
url = _get_image_sequence_url(clip)
12211228

1229+
if url:
1230+
# Premiere style uses the base name of the media reference
1231+
if style == 'premiere':
1232+
clip.name = os.path.basename(clip.media_reference.target_url)
12221233
else:
12231234
url = clip.name
12241235

@@ -1247,27 +1258,37 @@ def _generate_comment_lines(
12471258
lines.append(
12481259
"* {from_or_to} CLIP NAME: {name}{suffix}".format(
12491260
from_or_to=from_or_to,
1250-
name=clip.name,
1261+
name=os.path.basename(url) if style == 'premiere' else clip.name,
12511262
suffix=suffix
12521263
)
12531264
)
12541265
if timing_effect and timing_effect.effect_name == "FreezeFrame":
12551266
lines.append('* * FREEZE FRAME')
12561267

12571268
# If the style has a spec, apply it and add it as a comment
1258-
style = VALID_EDL_STYLES.get(style)
1259-
if url and style:
1260-
lines.append("* {from_or_to} {style}: {url}".format(
1261-
from_or_to=from_or_to,
1262-
style=style,
1263-
url=url
1264-
))
1269+
style_spec = VALID_EDL_STYLES.get(style)
1270+
if url:
1271+
if style_spec:
1272+
lines.append("* {from_or_to} {style_spec}: {url}".format(
1273+
from_or_to=from_or_to,
1274+
style_spec=style_spec,
1275+
url=_flip_windows_slashes(url)
1276+
))
1277+
else:
1278+
lines.append("* OTIO REFERENCE {from_or_to}: {url}".format(
1279+
from_or_to=from_or_to,
1280+
url=_flip_windows_slashes(url)
1281+
))
12651282

12661283
if reelname_len and not clip.metadata.get('cmx_3600', {}).get('reel'):
12671284
lines.append("* OTIO TRUNCATED REEL NAME FROM: {url}".format(
12681285
url=os.path.basename(_flip_windows_slashes(url or clip.name))
12691286
))
12701287

1288+
if style == 'premiere':
1289+
clip.metadata.setdefault('cmx_3600', {})
1290+
clip.metadata['cmx_3600'].update({'reel': 'AX'})
1291+
12711292
cdl = clip.metadata.get('cdl')
12721293
if cdl:
12731294
asc_sop = cdl.get('asc_sop')

tests/test_cmx_3600_adapter.py

Lines changed: 120 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
from tempfile import TemporaryDirectory # noqa: F401
1717
import tempfile
1818

19-
2019
SAMPLE_DATA_DIR = os.path.join(os.path.dirname(__file__), "sample_data")
2120
SCREENING_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "screening_example.edl")
21+
AVID_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "avid_example.edl")
2222
NUCODA_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "nucoda_example.edl")
23+
PREMIERE_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "premiere_example.edl")
2324
EXEMPLE_25_FPS_PATH = os.path.join(SAMPLE_DATA_DIR, "25fps.edl")
2425
NO_SPACES_PATH = os.path.join(SAMPLE_DATA_DIR, "no_spaces_test.edl")
2526
DISSOLVE_TEST = os.path.join(SAMPLE_DATA_DIR, "dissolve_test.edl")
@@ -30,10 +31,7 @@
3031
WIPE_TEST = os.path.join(SAMPLE_DATA_DIR, "wipe_test.edl")
3132
TIMECODE_MISMATCH_TEST = os.path.join(SAMPLE_DATA_DIR, "timecode_mismatch.edl")
3233
SPEED_EFFECTS_TEST = os.path.join(SAMPLE_DATA_DIR, "speed_effects.edl")
33-
SPEED_EFFECTS_TEST_SMALL = os.path.join(
34-
SAMPLE_DATA_DIR,
35-
"speed_effects_small.edl"
36-
)
34+
SPEED_EFFECTS_TEST_SMALL = os.path.join(SAMPLE_DATA_DIR, "speed_effects_small.edl")
3735
MULTIPLE_TARGET_AUDIO_PATH = os.path.join(SAMPLE_DATA_DIR, "multi_audio.edl")
3836
TRANSITION_DURATION_TEST = os.path.join(SAMPLE_DATA_DIR, "transition_duration.edl")
3937
ENABLED_TEST = os.path.join(SAMPLE_DATA_DIR, "enabled.otio")
@@ -714,47 +712,81 @@ def test_read_generators(self):
714712
'SMPTEBars'
715713
)
716714

717-
def test_nucoda_edl_read(self):
718-
edl_path = NUCODA_EXAMPLE_PATH
719-
fps = 24
720-
timeline = otio.adapters.read_from_file(edl_path)
721-
self.assertTrue(timeline is not None)
722-
self.assertEqual(len(timeline.tracks), 1)
723-
self.assertEqual(len(timeline.tracks[0]), 2)
724-
self.assertEqual(
725-
timeline.tracks[0][0].name,
726-
"take_1"
727-
)
728-
self.assertEqual(
729-
timeline.tracks[0][0].source_range.duration,
730-
otio.opentime.from_timecode("00:00:01:07", fps)
731-
)
732-
self.assertIsOTIOEquivalentTo(
733-
timeline.tracks[0][0].media_reference,
734-
otio.schema.ExternalReference(
735-
target_url=r"S:\path\to\ZZ100_501.take_1.0001.exr"
715+
def test_style_edl_read(self):
716+
edl_paths = [AVID_EXAMPLE_PATH, NUCODA_EXAMPLE_PATH, PREMIERE_EXAMPLE_PATH]
717+
for edl_path in edl_paths:
718+
fps = 24
719+
timeline = otio.adapters.read_from_file(edl_path)
720+
self.assertTrue(timeline is not None)
721+
self.assertEqual(len(timeline.tracks), 1)
722+
self.assertEqual(len(timeline.tracks[0]), 2)
723+
print(edl_path)
724+
725+
# If cannot assertEqual fails with clip name
726+
# Attempt to assertEqual with
727+
try:
728+
self.assertEqual(
729+
timeline.tracks[0][0].name,
730+
"take_1"
731+
)
732+
except AssertionError:
733+
self.assertEqual(
734+
timeline.tracks[0][0].name,
735+
"ZZ100_501.take_1.0001.exr"
736+
)
737+
self.assertEqual(
738+
timeline.tracks[0][0].source_range.duration,
739+
otio.opentime.from_timecode("00:00:01:07", fps)
736740
)
737-
)
738-
self.assertEqual(
739-
timeline.tracks[0][1].name,
740-
"take_2"
741-
)
742-
self.assertEqual(
743-
timeline.tracks[0][1].source_range.duration,
744-
otio.opentime.from_timecode("00:00:02:02", fps)
745-
)
746-
self.assertIsOTIOEquivalentTo(
747-
timeline.tracks[0][1].media_reference,
748-
otio.schema.ExternalReference(
749-
target_url=r"S:\path\to\ZZ100_502A.take_2.0101.exr"
741+
print(timeline.tracks[0][0].media_reference)
742+
743+
try:
744+
self.assertIsOTIOEquivalentTo(
745+
timeline.tracks[0][0].media_reference,
746+
otio.schema.ExternalReference(
747+
target_url=r"S:\path\to\ZZ100_501.take_1.0001.exr"
748+
)
749+
)
750+
except AssertionError:
751+
self.assertIsOTIOEquivalentTo(
752+
timeline.tracks[0][0].media_reference,
753+
otio.schema.MissingReference()
754+
)
755+
756+
try:
757+
self.assertEqual(
758+
timeline.tracks[0][1].name,
759+
"take_2"
760+
)
761+
except AssertionError:
762+
self.assertEqual(
763+
timeline.tracks[0][1].name,
764+
"ZZ100_502A.take_2.0101.exr"
765+
)
766+
767+
self.assertEqual(
768+
timeline.tracks[0][1].source_range.duration,
769+
otio.opentime.from_timecode("00:00:02:02", fps)
750770
)
751-
)
752771

753-
def test_nucoda_edl_write(self):
772+
try:
773+
self.assertIsOTIOEquivalentTo(
774+
timeline.tracks[0][1].media_reference,
775+
otio.schema.ExternalReference(
776+
target_url=r"S:\path\to\ZZ100_502A.take_2.0101.exr"
777+
)
778+
)
779+
except AssertionError:
780+
self.assertIsOTIOEquivalentTo(
781+
timeline.tracks[0][1].media_reference,
782+
otio.schema.MissingReference()
783+
)
784+
785+
def test_style_edl_write(self):
754786
track = otio.schema.Track()
755-
tl = otio.schema.Timeline("test_nucoda_timeline", tracks=[track])
787+
tl = otio.schema.Timeline("temp", tracks=[track])
756788
rt = otio.opentime.RationalTime(5.0, 24.0)
757-
mr = otio.schema.ExternalReference(target_url=r"S:\var\tmp\test.exr")
789+
mr = otio.schema.ExternalReference(target_url=r"S:/var/tmp/test.exr")
758790

759791
tr = otio.opentime.TimeRange(
760792
start_time=otio.opentime.RationalTime(0.0, 24.0),
@@ -781,6 +813,7 @@ def test_nucoda_edl_write(self):
781813
tl.tracks[0].append(gap)
782814
tl.tracks[0].append(cl2)
783815

816+
tl.name = 'test_nucoda_timeline'
784817
result = otio.adapters.write_to_string(
785818
tl,
786819
adapter_name='cmx_3600',
@@ -791,11 +824,53 @@ def test_nucoda_edl_write(self):
791824
792825
001 test V C 00:00:00:00 00:00:00:05 00:00:00:00 00:00:00:05
793826
* FROM CLIP NAME: test clip1
794-
* FROM FILE: S:\var\tmp\test.exr
827+
* FROM FILE: S:/var/tmp/test.exr
828+
* OTIO TRUNCATED REEL NAME FROM: test.exr
829+
002 test V C 00:00:00:00 00:00:00:05 00:00:01:05 00:00:01:10
830+
* FROM CLIP NAME: test clip2
831+
* FROM FILE: S:/var/tmp/test.exr
832+
* OTIO TRUNCATED REEL NAME FROM: test.exr
833+
'''
834+
835+
self.assertMultiLineEqual(result, expected)
836+
837+
tl.name = 'test_avid_timeline'
838+
result = otio.adapters.write_to_string(
839+
tl,
840+
adapter_name='cmx_3600',
841+
style='avid'
842+
)
843+
844+
expected = r'''TITLE: test_avid_timeline
845+
846+
001 test V C 00:00:00:00 00:00:00:05 00:00:00:00 00:00:00:05
847+
* FROM CLIP NAME: test clip1
848+
* FROM CLIP: S:/var/tmp/test.exr
795849
* OTIO TRUNCATED REEL NAME FROM: test.exr
796850
002 test V C 00:00:00:00 00:00:00:05 00:00:01:05 00:00:01:10
797851
* FROM CLIP NAME: test clip2
798-
* FROM FILE: S:\var\tmp\test.exr
852+
* FROM CLIP: S:/var/tmp/test.exr
853+
* OTIO TRUNCATED REEL NAME FROM: test.exr
854+
'''
855+
856+
self.assertMultiLineEqual(result, expected)
857+
858+
tl.name = 'test_premiere_timeline'
859+
result = otio.adapters.write_to_string(
860+
tl,
861+
adapter_name='cmx_3600',
862+
style='premiere'
863+
)
864+
865+
expected = r'''TITLE: test_premiere_timeline
866+
867+
001 AX V C 00:00:00:00 00:00:00:05 00:00:00:00 00:00:00:05
868+
* FROM CLIP NAME: test.exr
869+
* OTIO REFERENCE FROM: S:/var/tmp/test.exr
870+
* OTIO TRUNCATED REEL NAME FROM: test.exr
871+
002 AX V C 00:00:00:00 00:00:00:05 00:00:01:05 00:00:01:10
872+
* FROM CLIP NAME: test.exr
873+
* OTIO REFERENCE FROM: S:/var/tmp/test.exr
799874
* OTIO TRUNCATED REEL NAME FROM: test.exr
800875
'''
801876

@@ -807,10 +882,10 @@ def test_reels_edl_round_trip_string2mem2string(self):
807882
808883
001 ZZ100_50 V C 01:00:04:05 01:00:05:12 00:59:53:11 00:59:54:18
809884
* FROM CLIP NAME: take_1
810-
* FROM FILE: S:\path\to\ZZ100_501.take_1.0001.exr
885+
* FROM FILE: S:/path/to/ZZ100_501.take_1.0001.exr
811886
002 ZZ100_50 V C 01:00:06:13 01:00:08:15 00:59:54:18 00:59:56:20
812887
* FROM CLIP NAME: take_2
813-
* FROM FILE: S:\path\to\ZZ100_502A.take_2.0101.exr
888+
* FROM FILE: S:/path/to/ZZ100_502A.take_2.0101.exr
814889
'''
815890

816891
timeline = otio.adapters.read_from_string(sample_data, adapter_name="cmx_3600")

0 commit comments

Comments
 (0)