From 5184c36403e6ab94caae20acf6ced709f0dc9c0e Mon Sep 17 00:00:00 2001 From: Spencer Magnusson <46832095+semagnum@users.noreply.github.com> Date: Mon, 5 Aug 2024 23:09:47 -0700 Subject: [PATCH] #1677 otiotool verify ranges (#1779) Added --verify-ranges option to otiotool Signed-off-by: Spencer Magnusson --- .../opentimelineio/console/otiotool.py | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/py-opentimelineio/opentimelineio/console/otiotool.py b/src/py-opentimelineio/opentimelineio/console/otiotool.py index 4bbcd8676..1b1499b46 100755 --- a/src/py-opentimelineio/opentimelineio/console/otiotool.py +++ b/src/py-opentimelineio/opentimelineio/console/otiotool.py @@ -137,7 +137,8 @@ def main(): args.list_media or args.verify_media or args.list_tracks or - args.list_markers) + args.list_markers or + args.verify_ranges) if should_summarize: for timeline in timelines: summarize_timeline( @@ -146,6 +147,7 @@ def main(): args.list_media, args.verify_media, args.list_markers, + args.verify_ranges, timeline) # Final Phase: Output @@ -207,8 +209,8 @@ def parse_arguments(): 6. Inspect Options such as --stats, --list-clips, --list-tracks, --list-media, - --verify-media, --list-markers, and --inspect will examine the OTIO and - print information to standard output. + --verify-media, --list-markers, --verify-ranges, and --inspect + will examine the OTIO and print information to standard output. 7. Output Finally, if the "--output " option is specified, the resulting @@ -397,6 +399,13 @@ def parse_arguments(): action='store_true', help="List summary of all markers" ) + parser.add_argument( + "--verify-ranges", + action='store_true', + help="""Verify that each clip in a timeline has a source range + within the available range of media + (acceptable in some use cases, not in others)""" + ) parser.add_argument( "--inspect", type=str, @@ -852,7 +861,7 @@ def inspect_timelines(name_regex, timeline): def summarize_timeline(list_tracks, list_clips, list_media, verify_media, - list_markers, timeline): + list_markers, verify_ranges, timeline): """Print a summary of a timeline, optionally listing the tracks, clips, media, and/or markers inside it.""" print("TIMELINE:", timeline.name) @@ -861,8 +870,30 @@ def summarize_timeline(list_tracks, list_clips, list_media, verify_media, if list_tracks: print(f"TRACK: {child.name} ({child.kind})") if isinstance(child, otio.schema.Clip): - if list_clips: - print(" CLIP:", child.name) + if list_clips or verify_ranges: + if verify_ranges: + range_msg = "" + try: + source = child.source_range + available = child.available_range() + + # contains() uses end_time_exclusive(), + # does not handle case when + # the end of the source range + # meets available range exactly + available_start = available.start_time + available_end = available.end_time_inclusive() + src_start = source.start_time + src_end = source.end_time_inclusive() + if src_start < available_start or available_end < src_end: + range_msg = "SOURCE MEDIA OUT OF BOUNDS" + else: + range_msg = "IN BOUNDS" + except Exception: # available range is, well, unavailable + pass + print(" CLIP:", child.name, range_msg) + else: + print(" CLIP:", child.name) if list_media or verify_media: try: url = child.media_reference.target_url