A Timeline and all of the Tracks and Stacks it contains work together to place the Clips, Gaps and Transitions relative to each other in time. You can think of this as a 1-dimensional coordinate system. Simple cases of assembling Clips into a Track will lay the Clips end-to-end, but more complex cases involve nesting, cross-dissolves, trimming, and speed-up/slow-down effects which can lead to confusion. In an attempt to make this easy to work with OpenTimelineIO uses the following terminology and API for dealing with time ranges.
Note: You probably also want to refer to Timeline Structure.
There are several ranges you might want from a Clip. For each of these, it is important to note which time frame (the 1-dimensional coordinate system of time) the range is relative to. We call these the “Clip time frame” and the “parent time frame” (usually the Clip’s parent Track).
Ranges within the Clip and its media:¶
available_range() method on Clip returns a TimeRange that tells you
how much media is available via the Clip’s
media_reference. If a Clip
points to a movie file on disk, then this should tell you how long that
movie is and what timecode it starts at. For example: “wedding.mov” starts
at timecode 01:00:00:00 and is 30 minutes long.
available_range() may return
None if the range is not known.
source_range property on a Clip will trim the Clip to only
that range of media.
source_range is specified in the Clip time frame.
source_range may be
None indicating that the Clip should use
available_range() whatever that may be. If both
available_range() are None, then the Clip is invalid. You need at
least one of those.
Usually this will be a shorter segment than the
available_range() but this
is not a hard constraint. Some use cases will intentionally ask for
a Clip that is longer (or starts earlier) than the available media as a way
to request that new media (a newly animated take, or newly recorded audio)
be made to fill the requested
This will return the Clip’s
source_range if it is set, otherwise it will
available_range(). This tells you how long the Clip is meant to
be in its parent Track or Stack.
trimmed_range() is specified in the Clip time frame.
This will return the same thing as
trimmed_range() but also takes any
adjacent Transitions into account. For example, a Clip that is trimmed to
end at frame 10, but is followed by a cross-dissolve with
out_offset of 5
frames, will have a
visible_range() that ends at frame 15.
visible_range() is specified in the Clip time frame.
This is the way to ask for the Clip’s “natural” duration. In
most common non-linear editors, this is the duration of the Clip you will
see in the timeline user interface.
Clip.duration() is a convenience for
If you want a
different duration, then you can ask for
Clip.visible_range().duration() explicitly. This makes it clear in your
code when you are asking for a different duration.
Ranges of the Clip in its parent Track or Stack:¶
The answer to this depends on what type of the Clip’s parent. In the
typical case, the Clip is inside a Track, so the
will give you the range within that Track where this Clip is visible.
Each clip within the Track will have a start time that is directly after
the previous clip’s end. So, given a Track with clipA and clipB in it,
this is always true:
range_in_parent() is specified in the parent time frame.
clipA.range_in_parent().end_time_exclusive() == clipB.range_in_parent().start_time
If the parent is a Stack, then
range_in_parent() is less interesting. The
start time will always have
.value == 0 and the duration is the Clip’s
duration. This means that the start of each clip in a Stack is aligned. If you
want to shift them around, then use a Stack of Tracks (like the top-level
Timeline has by default) and then you can use Gaps to shift the contents of each
This is the same as
Clip.range_in_parent() but trimmed to the parent
source_range. In most cases the parent has a
source_range of None, so
there is no trimming, but in cases where the parent is trimmed, you may
want to ask where a Clip is relative to the trimmed parent. In cases where
the Clip is completely trimmed by the parent, the
Clip.trimmed_range_in_parent() will be None.
trimmed_range_in_parent() is specified in the parent time frame.
Markers can be attached to any Item (Clips, Tracks, Stacks, Gaps, etc.)
Each Marker has a
marked_range which specifies the position and duration of
the Marker relative to the object it is attached to.
marked_range of a Marker on a Clip is in the Clip’s time frame (same as
marked_range of a Marker on a Track is in the Track’s time frame (same as
marked_range.duration.value may be 0 if the Marker is meant to be a
instantaneous moment in time, or some other duration if it spans a length of