Skip to content

Commit e684d8c

Browse files
committed
Update style spec and added fallback OTIO comment if style does not have a spec
1 parent 3609d52 commit e684d8c

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
@@ -86,15 +86,15 @@ class EDLParseError(exceptions.OTIOError):
8686
# the comment string for the media reference:
8787
# 'avid': '* FROM CLIP:' (default)
8888
# 'nucoda': '* FROM FILE:'
89-
# 'premiere': '' (If Adobe Premiere's imports an EDL that uses
90-
# a "FROM" comment will cause the clips
91-
# to be name UNKNOWN)
89+
# 'premiere': None (If Adobe Premiere's imports an EDL that uses
90+
# a "FROM" comment will cause the clips
91+
# to be name UNKNOWN)
9292
# When adding a new style, please be sure to add sufficient tests
9393
# to verify both the new and existing styles.
9494
VALID_EDL_STYLES = {
9595
'avid': 'CLIP',
9696
'nucoda': 'FILE',
97-
'premiere': '',
97+
'premiere': None,
9898
}
9999

100100

@@ -647,6 +647,7 @@ class CommentHandler(object):
647647
('ASC_SAT', 'asc_sat'),
648648
('M2', 'motion_effect'),
649649
('\\* FREEZE FRAME', 'freeze_frame'),
650+
('\\* OTIO REFERENCE [a-zA-Z]+', 'media_reference'),
650651
])
651652

652653
def __init__(self, comments):
@@ -1110,7 +1111,13 @@ def __init__(
11101111
reelname_len
11111112
):
11121113

1113-
line = EventLine(kind, rate, reel=_reel_from_clip(clip, reelname_len))
1114+
# Premiere style uses AX for the reel name
1115+
if style == 'premiere':
1116+
reel = 'AX'
1117+
else:
1118+
reel = _reel_from_clip(clip, reelname_len)
1119+
1120+
line = EventLine(kind, rate, reel=reel)
11141121
line.source_in = clip.source_range.start_time
11151122
line.source_out = clip.source_range.end_time_exclusive()
11161123

@@ -1350,6 +1357,10 @@ def _generate_comment_lines(
13501357
elif hasattr(clip.media_reference, 'abstract_target_url'):
13511358
url = _get_image_sequence_url(clip)
13521359

1360+
if url:
1361+
# Premiere style uses the base name of the media reference
1362+
if style == 'premiere':
1363+
clip.name = os.path.basename(clip.media_reference.target_url)
13531364
else:
13541365
url = clip.name
13551366

@@ -1378,27 +1389,37 @@ def _generate_comment_lines(
13781389
lines.append(
13791390
"* {from_or_to} CLIP NAME: {name}{suffix}".format(
13801391
from_or_to=from_or_to,
1381-
name=clip.name,
1392+
name=os.path.basename(url) if style == 'premiere' else clip.name,
13821393
suffix=suffix
13831394
)
13841395
)
13851396
if timing_effect and timing_effect.effect_name == "FreezeFrame":
13861397
lines.append('* * FREEZE FRAME')
13871398

13881399
# If the style has a spec, apply it and add it as a comment
1389-
style = VALID_EDL_STYLES.get(style)
1390-
if url and style:
1391-
lines.append("* {from_or_to} {style}: {url}".format(
1392-
from_or_to=from_or_to,
1393-
style=style,
1394-
url=url
1395-
))
1400+
style_spec = VALID_EDL_STYLES.get(style)
1401+
if url:
1402+
if style_spec:
1403+
lines.append("* {from_or_to} {style_spec}: {url}".format(
1404+
from_or_to=from_or_to,
1405+
style_spec=style_spec,
1406+
url=_flip_windows_slashes(url)
1407+
))
1408+
else:
1409+
lines.append("* OTIO REFERENCE {from_or_to}: {url}".format(
1410+
from_or_to=from_or_to,
1411+
url=_flip_windows_slashes(url)
1412+
))
13961413

13971414
if reelname_len and not clip.metadata.get('cmx_3600', {}).get('reel'):
13981415
lines.append("* OTIO TRUNCATED REEL NAME FROM: {url}".format(
13991416
url=os.path.basename(_flip_windows_slashes(url or clip.name))
14001417
))
14011418

1419+
if style == 'premiere':
1420+
clip.metadata.setdefault('cmx_3600', {})
1421+
clip.metadata['cmx_3600'].update({'reel': 'AX'})
1422+
14021423
cdl = clip.metadata.get('cdl')
14031424
if cdl:
14041425
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
@@ -41,10 +41,11 @@
4141
# XXX: python2.7 only
4242
from backports import tempfile
4343

44-
4544
SAMPLE_DATA_DIR = os.path.join(os.path.dirname(__file__), "sample_data")
4645
SCREENING_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "screening_example.edl")
46+
AVID_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "avid_example.edl")
4747
NUCODA_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "nucoda_example.edl")
48+
PREMIERE_EXAMPLE_PATH = os.path.join(SAMPLE_DATA_DIR, "premiere_example.edl")
4849
EXEMPLE_25_FPS_PATH = os.path.join(SAMPLE_DATA_DIR, "25fps.edl")
4950
NO_SPACES_PATH = os.path.join(SAMPLE_DATA_DIR, "no_spaces_test.edl")
5051
DISSOLVE_TEST = os.path.join(SAMPLE_DATA_DIR, "dissolve_test.edl")
@@ -55,10 +56,7 @@
5556
WIPE_TEST = os.path.join(SAMPLE_DATA_DIR, "wipe_test.edl")
5657
TIMECODE_MISMATCH_TEST = os.path.join(SAMPLE_DATA_DIR, "timecode_mismatch.edl")
5758
SPEED_EFFECTS_TEST = os.path.join(SAMPLE_DATA_DIR, "speed_effects.edl")
58-
SPEED_EFFECTS_TEST_SMALL = os.path.join(
59-
SAMPLE_DATA_DIR,
60-
"speed_effects_small.edl"
61-
)
59+
SPEED_EFFECTS_TEST_SMALL = os.path.join(SAMPLE_DATA_DIR, "speed_effects_small.edl")
6260
MULTIPLE_TARGET_AUDIO_PATH = os.path.join(SAMPLE_DATA_DIR, "multi_audio.edl")
6361
TRANSITION_DURATION_TEST = os.path.join(SAMPLE_DATA_DIR, "transition_duration.edl")
6462

@@ -674,47 +672,81 @@ def test_read_generators(self):
674672
'SMPTEBars'
675673
)
676674

677-
def test_nucoda_edl_read(self):
678-
edl_path = NUCODA_EXAMPLE_PATH
679-
fps = 24
680-
timeline = otio.adapters.read_from_file(edl_path)
681-
self.assertTrue(timeline is not None)
682-
self.assertEqual(len(timeline.tracks), 1)
683-
self.assertEqual(len(timeline.tracks[0]), 2)
684-
self.assertEqual(
685-
timeline.tracks[0][0].name,
686-
"take_1"
687-
)
688-
self.assertEqual(
689-
timeline.tracks[0][0].source_range.duration,
690-
otio.opentime.from_timecode("00:00:01:07", fps)
691-
)
692-
self.assertIsOTIOEquivalentTo(
693-
timeline.tracks[0][0].media_reference,
694-
otio.schema.ExternalReference(
695-
target_url=r"S:\path\to\ZZ100_501.take_1.0001.exr"
675+
def test_style_edl_read(self):
676+
edl_paths = [AVID_EXAMPLE_PATH, NUCODA_EXAMPLE_PATH, PREMIERE_EXAMPLE_PATH]
677+
for edl_path in edl_paths:
678+
fps = 24
679+
timeline = otio.adapters.read_from_file(edl_path)
680+
self.assertTrue(timeline is not None)
681+
self.assertEqual(len(timeline.tracks), 1)
682+
self.assertEqual(len(timeline.tracks[0]), 2)
683+
print(edl_path)
684+
685+
# If cannot assertEqual fails with clip name
686+
# Attempt to assertEqual with
687+
try:
688+
self.assertEqual(
689+
timeline.tracks[0][0].name,
690+
"take_1"
691+
)
692+
except AssertionError:
693+
self.assertEqual(
694+
timeline.tracks[0][0].name,
695+
"ZZ100_501.take_1.0001.exr"
696+
)
697+
self.assertEqual(
698+
timeline.tracks[0][0].source_range.duration,
699+
otio.opentime.from_timecode("00:00:01:07", fps)
696700
)
697-
)
698-
self.assertEqual(
699-
timeline.tracks[0][1].name,
700-
"take_2"
701-
)
702-
self.assertEqual(
703-
timeline.tracks[0][1].source_range.duration,
704-
otio.opentime.from_timecode("00:00:02:02", fps)
705-
)
706-
self.assertIsOTIOEquivalentTo(
707-
timeline.tracks[0][1].media_reference,
708-
otio.schema.ExternalReference(
709-
target_url=r"S:\path\to\ZZ100_502A.take_2.0101.exr"
701+
print(timeline.tracks[0][0].media_reference)
702+
703+
try:
704+
self.assertIsOTIOEquivalentTo(
705+
timeline.tracks[0][0].media_reference,
706+
otio.schema.ExternalReference(
707+
target_url=r"S:\path\to\ZZ100_501.take_1.0001.exr"
708+
)
709+
)
710+
except AssertionError:
711+
self.assertIsOTIOEquivalentTo(
712+
timeline.tracks[0][0].media_reference,
713+
otio.schema.MissingReference()
714+
)
715+
716+
try:
717+
self.assertEqual(
718+
timeline.tracks[0][1].name,
719+
"take_2"
720+
)
721+
except AssertionError:
722+
self.assertEqual(
723+
timeline.tracks[0][1].name,
724+
"ZZ100_502A.take_2.0101.exr"
725+
)
726+
727+
self.assertEqual(
728+
timeline.tracks[0][1].source_range.duration,
729+
otio.opentime.from_timecode("00:00:02:02", fps)
710730
)
711-
)
712731

713-
def test_nucoda_edl_write(self):
732+
try:
733+
self.assertIsOTIOEquivalentTo(
734+
timeline.tracks[0][1].media_reference,
735+
otio.schema.ExternalReference(
736+
target_url=r"S:\path\to\ZZ100_502A.take_2.0101.exr"
737+
)
738+
)
739+
except AssertionError:
740+
self.assertIsOTIOEquivalentTo(
741+
timeline.tracks[0][1].media_reference,
742+
otio.schema.MissingReference()
743+
)
744+
745+
def test_style_edl_write(self):
714746
track = otio.schema.Track()
715-
tl = otio.schema.Timeline("test_nucoda_timeline", tracks=[track])
747+
tl = otio.schema.Timeline("temp", tracks=[track])
716748
rt = otio.opentime.RationalTime(5.0, 24.0)
717-
mr = otio.schema.ExternalReference(target_url=r"S:\var\tmp\test.exr")
749+
mr = otio.schema.ExternalReference(target_url=r"S:/var/tmp/test.exr")
718750

719751
tr = otio.opentime.TimeRange(
720752
start_time=otio.opentime.RationalTime(0.0, 24.0),
@@ -741,6 +773,7 @@ def test_nucoda_edl_write(self):
741773
tl.tracks[0].append(gap)
742774
tl.tracks[0].append(cl2)
743775

776+
tl.name = 'test_nucoda_timeline'
744777
result = otio.adapters.write_to_string(
745778
tl,
746779
adapter_name='cmx_3600',
@@ -751,11 +784,53 @@ def test_nucoda_edl_write(self):
751784
752785
001 test V C 00:00:00:00 00:00:00:05 00:00:00:00 00:00:00:05
753786
* FROM CLIP NAME: test clip1
754-
* FROM FILE: S:\var\tmp\test.exr
787+
* FROM FILE: S:/var/tmp/test.exr
788+
* OTIO TRUNCATED REEL NAME FROM: test.exr
789+
002 test V C 00:00:00:00 00:00:00:05 00:00:01:05 00:00:01:10
790+
* FROM CLIP NAME: test clip2
791+
* FROM FILE: S:/var/tmp/test.exr
792+
* OTIO TRUNCATED REEL NAME FROM: test.exr
793+
'''
794+
795+
self.assertMultiLineEqual(result, expected)
796+
797+
tl.name = 'test_avid_timeline'
798+
result = otio.adapters.write_to_string(
799+
tl,
800+
adapter_name='cmx_3600',
801+
style='avid'
802+
)
803+
804+
expected = r'''TITLE: test_avid_timeline
805+
806+
001 test V C 00:00:00:00 00:00:00:05 00:00:00:00 00:00:00:05
807+
* FROM CLIP NAME: test clip1
808+
* FROM CLIP: S:/var/tmp/test.exr
755809
* OTIO TRUNCATED REEL NAME FROM: test.exr
756810
002 test V C 00:00:00:00 00:00:00:05 00:00:01:05 00:00:01:10
757811
* FROM CLIP NAME: test clip2
758-
* FROM FILE: S:\var\tmp\test.exr
812+
* FROM CLIP: S:/var/tmp/test.exr
813+
* OTIO TRUNCATED REEL NAME FROM: test.exr
814+
'''
815+
816+
self.assertMultiLineEqual(result, expected)
817+
818+
tl.name = 'test_premiere_timeline'
819+
result = otio.adapters.write_to_string(
820+
tl,
821+
adapter_name='cmx_3600',
822+
style='premiere'
823+
)
824+
825+
expected = r'''TITLE: test_premiere_timeline
826+
827+
001 AX V C 00:00:00:00 00:00:00:05 00:00:00:00 00:00:00:05
828+
* FROM CLIP NAME: test.exr
829+
* OTIO REFERENCE FROM: S:/var/tmp/test.exr
830+
* OTIO TRUNCATED REEL NAME FROM: test.exr
831+
002 AX V C 00:00:00:00 00:00:00:05 00:00:01:05 00:00:01:10
832+
* FROM CLIP NAME: test.exr
833+
* OTIO REFERENCE FROM: S:/var/tmp/test.exr
759834
* OTIO TRUNCATED REEL NAME FROM: test.exr
760835
'''
761836

@@ -767,10 +842,10 @@ def test_reels_edl_round_trip_string2mem2string(self):
767842
768843
001 ZZ100_50 V C 01:00:04:05 01:00:05:12 00:59:53:11 00:59:54:18
769844
* FROM CLIP NAME: take_1
770-
* FROM FILE: S:\path\to\ZZ100_501.take_1.0001.exr
845+
* FROM FILE: S:/path/to/ZZ100_501.take_1.0001.exr
771846
002 ZZ100_50 V C 01:00:06:13 01:00:08:15 00:59:54:18 00:59:56:20
772847
* FROM CLIP NAME: take_2
773-
* FROM FILE: S:\path\to\ZZ100_502A.take_2.0101.exr
848+
* FROM FILE: S:/path/to/ZZ100_502A.take_2.0101.exr
774849
'''
775850

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

0 commit comments

Comments
 (0)