Skip to content

Python Examples

Paulo Nogueira edited this page May 20, 2025 · 1 revision

Loading and running configs via the API (recommended)

import os
import pathlib
from kombi.Element import Element
from kombi.TaskHolder.Loader import Loader
from kombi.Dispatcher import Dispatcher

# ensure the Gaffer executable is set correctly
# replace <GAFFER_LOCATION> with the path where Gaffer is installed (also, make sure ffmpeg is provided on your PATH)
if 'KOMBI_GAFFER_EXECUTABLE' not in os.environ:
    os.environ['KOMBI_GAFFER_EXECUTABLE'] = '<GAFFER_LOCATION>/bin/gaffer'

# this data data is shipped with kombi under <kombi/data/examples/gafferBlurImageSequence>
gafferBlurImageSequenceExampleDirectory = pathlib.Path("<KOMBI>/data/examples/gafferBlurImageSequence")

# looking for all image sequences Path objects that we are interested as input
imageSequencePaths = gafferBlurImageSequenceExampleDirectory.joinpath("imageSequence").glob("*.png")

# creating elements based on the Path objects which will be used as input for the tasks.
imageSequenceElements = map(Element.create, imageSequencePaths)

# loading tasks defined based on a config
taskHolderLoader = Loader()
taskHolderLoader.loadFromFile(gafferBlurImageSequenceExampleDirectory.joinpath('config.json'))

# executing task holder through a dispatcher (kombi provides many ways to execute it)
dispatcher = Dispatcher.create('local')
for taskHolder in taskHolderLoader.taskHolders():
    dispatcher.dispatch(taskHolder, imageSequenceElements)

Implementation of the example above using only python

import os
import pathlib
from kombi.Element import Element
from kombi.Task import Task
from kombi.Template import Template
from kombi.TaskHolder import TaskHolder
from kombi.Dispatcher import Dispatcher

# ensure the Gaffer executable is set correctly by replacing <GAFFER_LOCATION> with the path where
# Gaffer (gafferhq.org) is installed. Also, make sure ffmpeg is provided on your PATH. 
# Otherwise, use the environment KOMBI_FFMPEG_EXECUTABLE to define the location of the ffmpeg executable.
if 'KOMBI_GAFFER_EXECUTABLE' not in os.environ:
    os.environ['KOMBI_GAFFER_EXECUTABLE'] = '<GAFFER_LOCATION>/bin/gaffer'

# define the directory containing the example data for the Gaffer blur image sequence
gafferBlurImageSequenceExampleDirectory = pathlib.Path("<KOMBI>/data/examples/gafferBlurImageSequence")

# retrieve all image sequence paths (PNG files) in the specified directory
imageSequencePaths = gafferBlurImageSequenceExampleDirectory.joinpath("imageSequence").glob("*.png")

# create Element objects for each image sequence path to be used as input for the tasks
imageSequenceElements = map(Element.create, imageSequencePaths)

# create the gaffer scene task
gafferSceneTask = Task.create('gafferScene')
gafferSceneTask.setOption('scene', str(gafferBlurImageSequenceExampleDirectory.joinpath('scene.gfr')))

# setting metadata (in this example we are using metadata to filter out the compatible elements)
gafferSceneTask.setMetadata(
    "match.types",
    ["png"]
)
gafferSceneTask.setMetadata(
    "match.vars.imageType", [
            "sequence"
        ]
    }
)

# create the ffmpeg task with specific options
ffmpegTask = Task.create('ffmpeg')
ffmpegTask.setOption('frameRate', 23.976)
ffmpegTask.setOption('sourceColorSpace', 'bt709')
ffmpegTask.setOption('targetColorSpace', 'smpte170m')

# since we want to define a task that will run after the gaffer scene task is done. We need to create a "Task Holder" object
# that is going to allow us to define the coupling and a few more features.
# We want also to use a template for the data that will be generated by the gaffer scene task. This template uses a built-in
# expression language made for kombi to simplify common operations (inspired by lisp).
gafferSceneTargetTemplate = Template("!kt {prefix}/gafferBlurImageSequence/(newver <parent> as <ver>)/{name}_<ver>.(pad {frame} 6).exr")

# creating the task holder object
taskHolder = TaskHolder(gafferSceneTask, gafferSceneTargetTemplate)

# the prefix variable is not defined by the elements. Therefore, we are injecting the value for that
# (feel free to replace /tmp for another path...)
taskHolder.addVar('prefix', "/tmp")

# now creating the sub task holder that will be called when the parent task holder is done
ffmpegTargetTemplate = Template("!kt (dirname {filePath})/{name}.mov")
taskHolder.addSubTaskHolder(TaskHolder(ffmpegTask, ffmpegTargetTemplate))

# executing task holder through a dispatcher (kombi provides many ways to execute it)
dispatcher = Dispatcher.create('local')
dispatcher.dispatch(taskHolder, imageSequenceElements)

Clone this wiki locally