#
View Source
Quickstart

Let's take a little peek at what `Vtc` can do, for you! Note that printing calls like `inspect/1` have been elided from these examples.

These are the three main modules that make up the `Vtc` API:

    alias Vtc.Framerate
    alias Vtc.Rates
    alias Vtc.Framestamp

Let's start with a 23.98 NTSC timecode. We use the with_frames constructor here since timecode is really a human-readable way to represent frame count. The `Vtc.Rates` module defines a number of `Vtc.Framerate` values found in the wild. Most common, by far, is `23.98 NTSC`, which is shorthand for video footage running at `24000/1001` frames-per-second.

    iex> framestamp = Framestamp.with_frames!("17:23:13:02", Rates.f23_98())
    "<17:23:00:02 <23.98 NTSC>>"

Once we have a `Vtc.Framestamp` struct, we can render all sorts of commonly used framestamp representations, like SMPTE timecode:

##

unit-conversions

Unit Conversions

#### smpte_timecode/2

    iex> Framestamp.smpte_timecode(framestamp)
    "17:23:00:02"

#### frames/2

    iex> Framestamp.frames(framestamp)
    1501922

#### seconds

    iex> framestamp.seconds
    "Ratio.new(751711961, 12000)"

#### runtime/2

    iex> Framestamp.runtime(framestamp, 3)
    "17:24:15.676"

#### premiere_ticks/2

    iex> Framestamp.premiere_ticks(framestamp)
    15915544300656000

#### physical film length in feet_and_frames/2

    iex> Framestamp.feet_and_frames(framestamp)
    "<93889+10 :ff35mm_4perf>"

##

framerate-information

Framerate Information

#### ntsc

    iex> framestamp.rate.ntsc
    :non_drop

#### playback speed

    iex> framestamp.rate.playback
    "Ratio.new(24000, 1001)"

#### timebase/1 logical speed

    iex> Framerate.smpte_timebase(framestamp.rate)
    24

.

##

parsing

Parsing

Parsing is flexible, we can pass in partial or maformed timecode.

In `Vtc`, there are only two ways to parse framestamps, either with Timecode.with_frames/2 for formats that represnet a discrete frame count, or Timecode.with_seconds/2 for formats that represent a number of real-world, elapsed seconds were those frames to be played back at the framestamp's rate.

##

examples

Examples

###

frames-formats

Frames Formats

#### timecode

    iex> Framestamp.with_frames!("3:12", Rates.f23_98())
    "<03:00:00:12 <23.98 NTSC>>"

#### malformed timecode

    iex> Framestamp.with_frames!("3:12", Rates.f23_98())
    "<03:00:00:12 <23.98 NTSC>>"

#### frame count

    iex> Framestamp.with_frames!(24, Rates.f23_98())
    "<00:00:01:00 <23.98 NTSC>>"

#### physical film length in feet+frames

    iex> Framestamp.with_frames!("1+08", Rates.f23_98())
    "<00:00:01:00 <23.98 NTSC>>"

###

seconds-formats

Seconds Formats

#### seconds

    iex> Framestamp.with_seconds!(1.5, Rates.f23_98())
    "<00:05:23:04 <23.98 NTSC>>"

#### runtime

    iex> Framestamp.with_seconds!("00:05:23.5", Rates.f23_98())
    "<00:05:23:04 <23.98 NTSC>>"

#### malformed runtime

    iex> Framestamp.with_seconds!("5:23.5", Rates.f23_98())
    "<00:05:23:04 <23.98 NTSC>>"

#### premiere ticks

    iex> input = %PremiereTicks{in: 254_016_000_000}
    iex> Framestamp.with_seconds!(input, Rates.f23_98())
    "<00:00:01:00 <23.98 NTSC>>"

##

other-film-formats

Other film formats

By default, feet+frames is interpreted as 35mm, 4perf film. You can use the FeetAndFrames struct to parse other film formats.

#### 16mm feet + frames

    iex> alias Vtc.Source.Frames.FeetAndFrames
    iex>
    iex> {:ok, feet_and_frames} = FeetAndFrames.from_string("5400+00", film_format: :ff16mm)
    iex>
    iex> Framestamp.with_frames(feet_and_frames, Rates.f23_98())
    "{:ok, <01:15:00:00 <23.98 NTSC>>}"

##

arithmetic

Arithmetic

###

-1

.

#### add/3

    iex> a = Framestamp.with_frames!("18:23:13:02", Rates.f23_98())
    iex> b = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
    iex>
    iex> framestamp = Framestamp.add(a, b)
    "<18:23:13:02 <23.98 NTSC>>"

#### add/3 with string

    iex> Framestamp.add(tc, "00:10:00:00")
    "<18:33:13:02 <23.98 NTSC>>"

#### add/3 with ints means adding frames

    iex> Framestamp.add(tc, 38)
    "<18:33:14:16 <23.98 NTSC>>"

#### sub/3

    iex> Framestamp.sub(tc, "01:00:00:00")
    "<17:33:14:16 <23.98 NTSC>>"

### .

#### minus/1

    iex> Framestamp.minus(framestamp)
    "<-17:33:14:16 <23.98 NTSC>>"

#### abs/1

    iex> Framestamp.abs(framestamp)
    "<17:33:14:16 <23.98 NTSC>>"

#### mult/3

    iex> Framestamp.mult(framestamp, 2)
    "<35:06:29:08 <23.98 NTSC>>"

#### div/3

    iex> Framestamp.div(framestamp, 2)
    "<17:33:14:16 <23.98 NTSC>>"

#### divrem/3

    iex> {dividend, remainder} = Framestamp.divrem(framestamp, 3)
    iex> {dividend, remainder}
    "{<05:51:04:21 <23.98 NTSC>>, <00:00:00:01 <23.98 NTSC>>}"

##

eval

Eval

Special `Framestamp.eval do` blocks let us use native operators.

#### eval/2

    iex> require Framestamp
    iex>
    iex> a = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
    iex> b = Framestamp.with_frames!("00:30:00:00", Rates.f23_98())
    iex> c = Framestamp.with_frames!("00:15:00:00", Rates.f23_98())
    iex>
    iex> Framestamp.eval do
    iex>   a + b * 2 - c
    iex> end
    "<01:45:00:00 <23.98 NTSC>>"

Or even do some quick scratch calculations in a given framerate:

#### scratch calculation

    iex> Framestamp.eval at: 23.98 do
    iex>   "01:00:00:00" + "00:30:00:00" * 2 - "00:15:00:00"
    iex> end
    "<01:45:00:00 <23.98 NTSC>>"

##

framerates

Framerates

We can make dropframe framestamps for 29.97 or 59.94 using one of the pre-set framerates.

#### drop-frame

    iex> Framestamp.with_frames!(15_000, Rates.f29_97_df())
    "<00:08:20;18 <29.97 NTSC DF>>"

We can make new framestamps with arbitrary framerates if we want.

#### non-ntsc

    iex> Framestamp.with_frames!("01:00:00:00", Framerate.new!(240, nil))
    "<01:00:00:00 <240.0 fps>>"

Using `:non_drop` indicates this framestamp represents an NTSC timecode, and will convert whole-number timebases to the correct speed.

#### non-drop coersion

    iex> Framestamp.with_frames!("01:00:00:00", Framerate.new!(48, :non_drop))
    "<01:00:00:00 <47.95 NTSC>>"

We can also rebase the frames using a new framerate!

#### rebase

    iex> Framestamp.rebase(tc, Rates.f23_98())
    "<02:00:00:00 <23.98 NTSC>>"

##

comparisons-and-sorting

Comparisons and Sorting

It's easy to compare two framestamps.

#### compare/2

    iex> a = Framestamp.with_frames!("02:00:00:00", Rates.f23_98())
    iex> b = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
    iex>
    iex> Framestamp.compare(a, b)
    :lt

There a host of other specific comparison functions like eq?/2, gt?/2 that return booleans.

#### Specific comparison

    iex> Framestamp.lt?(a, b)
    true

Like arithmetic, we can compare directly with a timecode string:

#### compare/2 with string

    iex> Framestamp.compare(a, "00:59:00:00")
    :gt

Sorting is suported through the compare/2 function.

#### sort through Framestamp

    iex> framestamp_01 = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
    iex> framestamp_02 = Framestamp.with_frames!("02:00:00:00", Rates.f23_98())
    iex>
    iex> data_01 = %{id: 2, tc: framestamp_01}
    iex> data_02 = %{id: 1, tc: framestamp_02}
    iex>
    iex> Enum.sort_by([data_02, data_01], & &1.tc, Framestamp)
    "[%{id: 2, tc: <01:00:00:00 <23.98 NTSC>>}, %{id: 1, tc: <02:00:00:00 <23.98 NTSC>>}]"

##

ranges

Ranges

Range helps with common operations using in/out points. Let's set two of those up.

#### new/3

    iex> a_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
    iex> a_out = Framestamp.with_frames!("02:00:00:00", Rates.f23_98())
    iex>
    iex> a = Framestamp.Range.new!(a_in, a_out)
    "<01:00:00:00 - 02:00:00:00 :exclusive <23.98 NTSC>>"

By default, ranges are `exclusive`, meaning the `out` point represents the boundary where the clip ends, not the final frame that is part of the video clip. This way will be familiar to Premiere and Final Cut editors. But fear not, our Avid bretheren, inclusive out points like you are used to are available as well!

Just like addition, we can write a bare timecode string as the out value if we want.

#### new/3 with string

    iex> b_in = Framestamp.with_frames!("01:45:00:00", Rates.f23_98())
    iex>
    iex> b = Framestamp.Range.new!(b_in, "02:30:00:00")
    "<01:45:00:00 - 02:30:00:00 :exclusive <23.98 NTSC>>"

We can get the duration of a range.

#### duration/1

    iex> Framestamp.Range.duration(b)
    iex> "<00:45:00:00 <23.98 NTSC>>"

... see if a specific framestamp is in a range:

#### contains?/2

    iex> Framestamp.Range.contains?(b, "02:00:00:00")
    iex> true

... or see if it overlaps with another range.

#### overlaps?/2

    iex> Framestamp.Range.overlaps?(a, b)
    iex> true

We can even get the overlapping area as its own range!

#### intersection/2

    iex> Framestamp.Range.intersection!(a, b)
    "<01:45:00:00 - 02:00:00:00 :exclusive <23.98 NTSC>>"

##

postgres-types

Postgres Types

To include Postgres types with Ecto. Add the following into you applications configuration file:

    config :vtc,
      env: config_env(),
      include_postgres_types?: true

See each posgres type for information on it's configuration.

← Previous Page vtc-ex
Next Page → Ecto Quickstart