View Source Vtc.Framestamp.Range (vtc v0.17.5)
Holds a framestamp range.
struct-fields
Struct Fields
in
: Start TC. Must be less than or equal toout
.out
: End TC. Must be greater than or equal toin
.inclusive
: See below for more information. Default:false
inclusive-vs-exclusive-ranges
Inclusive vs. Exclusive Ranges
Inclusive ranges treat the out
framestamp as the last visible frame of a piece of
footage. This style of timecode range is most often associated with AVID.
Exclusive framestamp ranges treat the out
framestamp as the boundary where the
range ends. This style of timecode range is most often associated with Final Cut and
Premiere.
In mathematical notation, inclusive ranges are [in, out]
, while exclusive ranges are
[in, out)
.
Link to this section Summary
Types
Whether the end point should be treated as the Range's boundary (:exclusive), or its last element (:inclusive).
Range struct type.
Parse
Creates a new Range.
As new/3
, but raises on error.
Returns a range with an :in
value of stamp_in
and a duration of duration
.
As with_duration/3, but raises on error.
Manipulate
Adds scalar
to both range.in
and range.out
.
Wraps range with smpte_wrap_tod/1
, then splits on SMPTE midnight, returning two
ranges
As smpte_split_tod/1
, but raises on error.
Wrap range.in
to the nearest valid TOD (time-of-day) timecode.
As smpte_wrap_tod/1
, but raises on error.
Adjusts range to have an exclusive out framestamp.
Adjusts range to have an inclusive out framestamp.
Inspect
Returns the duration in Framestamp of range
.
Compare
Returns true
if range
contains framestamp
. framestamp
may be any value that
implements Frames.
Returns the the range where a
and b
overlap/intersect.
As intersection
, but returns a Range from 00:00:00:00
- 00:00:00:00
when there
is no overlap.
Returns true
if there is overlap between a
and b
.
Returns the range between two, non-overlapping ranges.
As separation
, but returns a Range from 00:00:00:00
- 00:00:00:00
when there
is overlap.
Functions
Callback implementation for Ecto.Type.embed_as/1
.
Callback implementation for Ecto.Type.equal?/2
.
Link to this section Types
@type out_type() :: :inclusive | :exclusive
Whether the end point should be treated as the Range's boundary (:exclusive), or its last element (:inclusive).
@type t() :: %Vtc.Framestamp.Range{ in: Vtc.Framestamp.t(), out: Vtc.Framestamp.t(), out_type: out_type() }
Range struct type.
Link to this section Parse
@spec new( stamp_in :: Vtc.Framestamp.t(), stamp_out :: Vtc.Framestamp.t() | Vtc.Source.Frames.t(), opts :: [{:out_type, out_type()}] ) :: {:ok, t()} | {:error, Exception.t() | Vtc.Framestamp.ParseError.t()}
Creates a new Range.
out_tc
may be a Framestamp value for any value that implements the
Frames protocol.
Returns an error if the resulting range would not have a duration greater or equal to
0, or if stamp_in
and stamp_out
do not have the same rate
.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("02:00:00:00", Rates.f23_98())
iex>
iex> result = Range.new(stamp_in, stamp_out)
iex> inspect(result)
"{:ok, <01:00:00:00 - 02:00:00:00 :exclusive <23.98 NTSC>>}"
Using a timecode string as b
:
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex>
iex> result = Range.new(stamp_in, "02:00:00:00")
iex> inspect(result)
"{:ok, <01:00:00:00 - 02:00:00:00 :exclusive <23.98 NTSC>>}"
Making a range with an inclusive out:
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex>
iex> result = Range.new(stamp_in, "02:00:00:00", out_type: :inclusive)
iex> inspect(result)
"{:ok, <01:00:00:00 - 02:00:00:00 :inclusive <23.98 NTSC>>}"
@spec new!(Vtc.Framestamp.t(), Vtc.Framestamp.t(), opts :: [{:out_type, out_type()}]) :: t()
As new/3
, but raises on error.
@spec with_duration( stamp_in :: Vtc.Framestamp.t(), duration :: Vtc.Framestamp.t() | Vtc.Source.Frames.t(), opts :: [{:out_type, out_type()}] ) :: {:ok, t()} | {:error, Exception.t() | Vtc.Framestamp.ParseError.t()}
Returns a range with an :in
value of stamp_in
and a duration of duration
.
duration
may be a Framestamp value for any value that implements the
Frames protocol. Returns an error if duration
is less than
0
seconds or if stamp_in
and stamp_out
do not have the same rate
.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> duration = Framestamp.with_frames!("00:30:00:00", Rates.f23_98())
iex>
iex> result = Range.with_duration(stamp_in, duration)
iex> inspect(result)
"{:ok, <01:00:00:00 - 01:30:00:00 :exclusive <23.98 NTSC>>}"
Using a timecode string as b
:
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex>
iex> result = Range.with_duration(stamp_in, "00:30:00:00")
iex> inspect(result)
"{:ok, <01:00:00:00 - 01:30:00:00 :exclusive <23.98 NTSC>>}"
Making a range with an inclusive out:
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex>
iex> result = Range.with_duration(stamp_in, "00:30:00:00", out_type: :inclusive)
iex> inspect(result)
"{:ok, <01:00:00:00 - 01:29:59:23 :inclusive <23.98 NTSC>>}"
@spec with_duration!( Vtc.Framestamp.t(), Vtc.Framestamp.t(), opts :: [{:out_type, out_type()}] ) :: t()
As with_duration/3, but raises on error.
Link to this section Manipulate
@spec shift( t(), Vtc.Framestamp.t() | Vtc.Source.Frames.t(), opts :: [ inherit_rate: Vtc.Framestamp.inherit_opt(), round: Vtc.Framestamp.round() ] ) :: t()
Adds scalar
to both range.in
and range.out
.
auto-casts Frames values.
options
Options
inherit_rate
: Which side to inherit the framerate from in mixed-rate calculations. Iffalse
, this function will raise ifrange.in.rate
does not matchscalar.rate
. Default:false
.round
: How to round the result with respect to whole-frames when mixing framerates. Default::closest
.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, "02:00:00:00")
iex>
iex> scalar = Framestamp.with_frames!("00:00:01:00", Rates.f23_98())
iex>
iex> Framestamp.Range.shift(range, scalar) |> inspect()
"<01:00:01:00 - 02:00:01:00 :exclusive <23.98 NTSC>>"
@spec smpte_split_tod(t()) :: {:ok, pre_midnight :: t(), next_day :: t() | nil} | {:error, Vtc.Framerate.InvalidSMPTEValueError.t()}
Wraps range with smpte_wrap_tod/1
, then splits on SMPTE midnight, returning two
ranges:
pre_midnight
: Usesrange.in
.range.out
is clipped to24:00:00:00
, inclusive.next_day
:range.in
is set to00:00:00:00
.range.out
is wrapped to valid TOD (time-of-day) timecode value. Ifrange
does not cross SMPTE midnight will benil
instead.
Returns error if range.in.rate
is not NTSC or whole-frame. Time-of-day timecode is
not defined for non-SMPTE framerates.
examples
Examples
Splits range that crosses midnight line:
iex> stamp_in = Framestamp.with_frames!("23:59:59:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("24:01:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out)
iex> {:ok, pre_midnight, next_day} = Framestamp.Range.smpte_split_tod(range)
iex> inspect(pre_midnight)
"<23:59:59:00 - 24:00:00:00 :exclusive <23.98 NTSC>>"
iex> inspect(next_day)
"<00:00:00:00 - 00:01:00:00 :exclusive <23.98 NTSC>>"
With inclusive out:
iex> stamp_in = Framestamp.with_frames!("23:59:59:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("24:01:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out, out_type: :inclusive)
iex> {:ok, pre_midnight, next_day} = Framestamp.Range.smpte_split_tod(range)
iex> inspect(pre_midnight)
"<23:59:59:00 - 23:59:59:23 :inclusive <23.98 NTSC>>"
iex> inspect(next_day)
"<00:00:00:00 - 00:01:00:00 :inclusive <23.98 NTSC>>"
Leaves alone ranges that do not cross midnight:
iex> stamp_in = Framestamp.with_frames!("22:59:59:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("23:01:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out)
iex> {:ok, pre_midnight, nil} = Framestamp.Range.smpte_split_tod(range)
iex> inspect(pre_midnight)
"<22:59:59:00 - 23:01:00:00 :exclusive <23.98 NTSC>>"
Wraps invalid TOD (time-of-day) timecode:
iex> stamp_in = Framestamp.with_frames!("24:00:00:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("24:01:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out)
iex> {:ok, pre_midnight, nil} = Framestamp.Range.smpte_split_tod(range)
iex> inspect(pre_midnight)
"<00:00:00:00 - 00:01:00:00 :exclusive <23.98 NTSC>>"
As smpte_split_tod/1
, but raises on error.
raises
Raises
- InvalidSMPTEValueError if
range.in.rate
is not NTSC or whole-frame. Time-of-day timecode is not defined for non-SMPTE framerates.
@spec smpte_wrap_tod(t()) :: {:ok, t()} | {:error, Vtc.Framerate.InvalidSMPTEValueError.t()}
Wrap range.in
to the nearest valid TOD (time-of-day) timecode.
Framestamps with a SMPTE timecode of less than 00:00:00:00
will have 24:00:00:00
recursively added until they are positive.
Framestamps with a SMPTE timecode of greater than or equal to 24:00:00:00
will have
24:00:00:00
subtracted until they are less than 24:00:00:00
.
Returned out point is always greater than in point, and may exceed 24:00:00:00
if
required for duration. If this behavior is not desirable, see smpte_split_tod/1
.
Returns error if range.in.rate
is not NTSC or whole-frame. Time-of-day timecode is
not defined for non-SMPTE
framerates.
examples
Examples
Adjusts ranges entirely outside of valid time-of-day timecode:
iex> stamp_in = Framestamp.with_frames!("24:00:00:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("24:01:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out)
iex> {:ok, wrapped} = Framestamp.Range.smpte_wrap_tod(range)
iex> inspect(wrapped)
"<00:00:00:00 - 00:01:00:00 :exclusive <23.98 NTSC>>"
Does not adjust ranges with an in-point that is valid for time-of-day timecode:
iex> stamp_in = Framestamp.with_frames!("23:59:59:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("24:01:00:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out)
iex> {:ok, wrapped} = Framestamp.Range.smpte_wrap_tod(range)
iex> inspect(wrapped)
"<23:59:59:00 - 24:01:00:00 :exclusive <23.98 NTSC>>"
Adjust negative ranges to wrap back from 24:00:00:00
:
iex> stamp_in = Framestamp.with_frames!("-01:00:00:00", Rates.f23_98())
iex> stamp_out = Framestamp.with_frames!("-00:59:50:00", Rates.f23_98())
iex> range = Framestamp.Range.new!(stamp_in, stamp_out)
iex> {:ok, wrapped} = Framestamp.Range.smpte_wrap_tod(range)
iex> inspect(wrapped)
"<23:00:00:00 - 23:00:10:00 :exclusive <23.98 NTSC>>"
As smpte_wrap_tod/1
, but raises on error.
raises
Raises
- InvalidSMPTEValueError if
range.in.rate
is not NTSC or whole-frame. Time-of-day timecode is not defined for non-SMPTE framerates.
Adjusts range to have an exclusive out framestamp.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> range = Range.new!(stamp_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> result = Range.with_exclusive_out(range)
iex> inspect(result)
"<01:00:00:00 - 02:00:00:01 :exclusive <23.98 NTSC>>"
Adjusts range to have an inclusive out framestamp.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> range = Range.new!(stamp_in, "02:00:00:00")
iex>
iex> result = Range.with_inclusive_out(range)
iex> inspect(result)
"<01:00:00:00 - 01:59:59:23 :inclusive <23.98 NTSC>>"
Link to this section Inspect
@spec duration(t()) :: Vtc.Framestamp.t()
Returns the duration in Framestamp of range
.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> range = Range.new!(stamp_in, "01:30:00:00")
iex>
iex> result = Range.duration(range)
iex> inspect(result)
"<00:30:00:00 <23.98 NTSC>>"
Link to this section Compare
@spec contains?(t(), Vtc.Framestamp.t() | Vtc.Source.Frames.t()) :: boolean()
Returns true
if range
contains framestamp
. framestamp
may be any value that
implements Frames.
examples
Examples
iex> stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> range = Range.new!(stamp_in, "01:30:00:00")
iex>
iex> Range.contains?(range, "01:10:00:00")
true
iex> Range.contains?(range, "01:40:00:00")
false
@spec intersection( t(), t(), inherit_rate: Vtc.Framestamp.inherit_opt(), inherit_out_type: Vtc.Framestamp.inherit_opt() ) :: {:ok, t()} | {:error, :none}
Returns the the range where a
and b
overlap/intersect.
Returns {:error, :none}
if the two ranges do not intersect.
options
Options
inherit_rate
: Which side to inherit the framerate from in mixed-rate calculations. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.inherit_out_type
: Which side to inherit the out type from whena.out_type
does not matchb.out_type
. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.
examples
Examples
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("01:50:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "02:30:00:00", out_type: :inclusive)
iex>
iex> result = Range.intersection(a, b)
iex> inspect(result)
"{:ok, <01:50:00:00 - 02:00:00:00 :inclusive <23.98 NTSC>>}"
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("02:10:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "03:30:00:00", out_type: :inclusive)
iex> Range.intersection(a, b)
{:error, :none}
@spec intersection!( t(), t(), inherit_rate: Vtc.Framestamp.inherit_opt(), inherit_out_type: Vtc.Framestamp.inherit_opt() ) :: t()
As intersection
, but returns a Range from 00:00:00:00
- 00:00:00:00
when there
is no overlap.
options
Options
inherit_rate
: Which side to inherit the framerate from in mixed-rate calculations. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.inherit_out_type
: Which side to inherit the out type from whena.out_type
does not matchb.out_type
. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.
examples
Examples
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("02:10:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "03:30:00:00", out_type: :inclusive)
iex>
iex> result = Range.intersection!(a, b)
iex> inspect(result)
"<00:00:00:00 - -00:00:00:01 :inclusive <23.98 NTSC>>"
Returns true
if there is overlap between a
and b
.
examples
Examples
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("01:50:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "02:30:00:00", out_type: :inclusive)
iex> Range.overlaps?(a, b)
true
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("02:10:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "03:30:00:00", out_type: :inclusive)
iex> Range.overlaps?(a, b)
false
@spec separation( t(), t(), inherit_rate: Vtc.Framestamp.inherit_opt(), inherit_out_type: Vtc.Framestamp.inherit_opt() ) :: {:ok, t()} | {:error, :none}
Returns the range between two, non-overlapping ranges.
Returns {:error, :none}
if the two ranges are not separated.
options
Options
inherit_rate
: Which side to inherit the framerate from in mixed-rate calculations. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.inherit_out_type
: Which side to inherit the out type from whena.out_type
does not matchb.out_type
. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.
examples
Examples
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("02:10:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "03:30:00:00", out_type: :inclusive)
iex>
iex> result = Range.separation(a, b)
iex> inspect(result)
"{:ok, <02:00:00:01 - 02:09:59:23 :inclusive <23.98 NTSC>>}"
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("01:50:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "02:30:00:00", out_type: :inclusive)
iex> Range.separation(a, b)
{:error, :none}
@spec separation!( t(), t(), inherit_rate: Vtc.Framestamp.inherit_opt(), inherit_out_type: Vtc.Framestamp.inherit_opt() ) :: t()
As separation
, but returns a Range from 00:00:00:00
- 00:00:00:00
when there
is overlap.
options
Options
inherit_rate
: Which side to inherit the framerate from in mixed-rate calculations. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.inherit_out_type
: Which side to inherit the out type from whena.out_type
does not matchb.out_type
. Iffalse
, this function will raise ifa
's rate does not matchb
's rate. Default:false
.
examples
Examples
iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
iex> a = Range.new!(a_in, "02:00:00:00", out_type: :inclusive)
iex>
iex> b_in = Framestamp.with_frames!("01:50:00:00", Rates.f23_98())
iex> b = Range.new!(b_in, "02:30:00:00", out_type: :inclusive)
iex>
iex> result = Range.separation!(a, b)
iex> inspect(result)
"<00:00:00:00 - -00:00:00:01 :inclusive <23.98 NTSC>>"
Link to this section Functions
Callback implementation for Ecto.Type.embed_as/1
.
Callback implementation for Ecto.Type.equal?/2
.