FFix.Graph (ffix v0.1.0)

Copy Markdown View Source

Filtergraph data model.

A graph is a pure Elixir value containing input references, filter nodes, exported streams, terminal sinks, and graph-level settings. It is serialized to ffmpeg syntax only at FFix.to_filtergraph/1, FFix.to_argv/1, or FFix.run/1.

Most users build filter pipelines inside FFix.command/3 callbacks:

FFix.command(
  "input.mp4",
  fn src ->
    src[:video] |> FFix.Filter.scale(w: 1280, h: -1)
  end,
  fn video, src ->
    FFix.output("out.mp4", video: video, audio: src[:audio])
  end
)

Use input/2 when building a reusable graph outside a command callback:

video = FFix.Graph.input(0, :video)

graph =
  FFix.graph(
    outputs: [
      preview: video |> FFix.Filter.scale(w: 320, h: -1)
    ]
  )

graph[:name] and graph[index] return exported streams from a %FFix.Graph{} value. In FFix.command/3, callback input and graph output shapes are preserved, so use normal Elixir access for the shape you return.

Selectors

  • :input maps the whole input, like -map 0
  • :video maps/selects the video stream class, like 0:v
  • :audio maps/selects the audio stream class, like 0:a
  • {:video, 1} or {:audio, 1} selects a stream-class index
  • {:raw, "s?"} keeps an ffmpeg selector escape hatch

Summary

Inputs

Builds a stream reference for an ffmpeg command input.

Builds a stream reference from a raw ffmpeg input selector.

Exports

Looks up a graph export by name or zero-based position.

Looks up a graph export by name or position, raising when it is missing.

Returns graph exports in declaration order.

Parsing and serialization

Parses a filtergraph string into %FFix.Graph{}.

Serializes a graph to ffmpeg filtergraph syntax.

Inputs

input(input, selector)

@spec input(input_id(), input_selector()) :: FFix.Stream.t()

Builds a stream reference for an ffmpeg command input.

Use this outside command callbacks, where callback input values are not available. Inside FFix.command/3, prefer the input value you received, such as src[:video] or inputs[:src][:video].

Examples

video = FFix.Graph.input(0, :video)
audio = FFix.Graph.input(0, :audio)

graph =
  FFix.graph(
    outputs: [
      main: video |> FFix.Filter.scale(w: 1280, h: -1)
    ]
  )

FFix.Command.new(
  inputs: [FFix.input("input.mp4")],
  graph: graph,
  outputs: [FFix.Command.output("out.mp4", [graph[:main], audio])]
)

input_raw(spec)

@spec input_raw(String.t()) :: FFix.Stream.t()

Builds a stream reference from a raw ffmpeg input selector.

This is an escape hatch for selectors that do not have a structured form yet. It currently expects an indexed selector such as "0:v" or "1:s?".

Exports

export(graph, name)

@spec export(t(), FFix.Graph.Export.name() | non_neg_integer()) ::
  FFix.Graph.Export.t() | nil

Looks up a graph export by name or zero-based position.

Returns nil when the export does not exist.

export!(graph, key)

Looks up a graph export by name or position, raising when it is missing.

exports(graph)

@spec exports(t()) :: [FFix.Graph.Export.t()]

Returns graph exports in declaration order.

Parsing and serialization

parse!(source)

@spec parse!(String.t()) :: t()

Parses a filtergraph string into %FFix.Graph{}.

The parser is pragmatic: it targets graphs produced by FFix and common ffmpeg filtergraph syntax. It is not meant to accept every hand-written filtergraph form.

Examples

graph = FFix.Graph.parse!("[0:v]scale=w=320:h=-1[preview]")
FFix.to_filtergraph(graph)
#=> "[0:v]scale=w=320:h=-1[preview];"

to_filtergraph(graph)

@spec to_filtergraph(t()) :: String.t()

Serializes a graph to ffmpeg filtergraph syntax.

Prefer FFix.to_filtergraph/1 when you want validation before serialization.

Types

input_id()

@type input_id() :: non_neg_integer() | atom() | String.t() | reference()

input_selector()

@type input_selector() ::
  :input
  | :video
  | :audio
  | {:video, non_neg_integer()}
  | {:audio, non_neg_integer()}
  | {:raw, String.t()}

node_id()

@type node_id() :: pos_integer()

setting()

@type setting() :: {atom() | String.t(), term()}

t()

@type t() :: %FFix.Graph{
  exports: [FFix.Graph.Export.t()],
  nodes: %{required(node_id()) => term()},
  order: [node_id()],
  settings: [setting()],
  terminals: [node_id()]
}