Effects & Generators Version 1.0Updated 26 Sep 2026

Video effects

Register a video effect with register_video_effect():

Python
import numpy as np

from editor.plugin_api import PluginParameterDefinition


def process(frame, parameters, context):
    strength = float(parameters["strength"])
    result = frame.astype(np.float32)
    result *= strength
    return np.clip(result, 0, 255).astype(np.uint8)


def register(api):
    api.register_video_effect(
        effect_id="gain",
        name="RGB Gain",
        processor=process,
        description="Simple RGB multiplier.",
        parameters=(
            PluginParameterDefinition(
                key="strength",
                label="Strength",
                control="slider",
                default=1.0,
                minimum=0.0,
                maximum=2.0,
                step=0.01,
            ),
        ),
    )

Caution: Return a valid frame with the expected dimensions and channel layout. Invalid output is rejected by the runtime.

Video processor contract

Python
def process(frame, parameters, context):
    ...

frame is a contiguous numpy.ndarray with shape:

(height, width, 3)

The normal dtype is uint8. The processor may return another array with the same shape. If the dtype is not uint8, Yrendr clips it to 0..255 and converts it.

If the returned shape is different, the result is ignored. If the processor raises, Yrendr skips that effect for the frame instead of bringing down the compositor.

The source surface alpha channel is preserved by the host around normal video effect processing.

Video context

Track-scoped video effects receive a context containing values such as:

Python
{
    "playhead": 12.34,
    "project_duration": 90.0,
    "render_scale": 0.5,
    "clip": clip,
    "project": project,
    "track": 2,
}

Master video effects receive the final composited frame and a context with:

Python
{
    "playhead": ...,
    "project_duration": ...,
    "render_scale": ...,
    "project": project,
    "clip": None,
    "track": None,
    "scope": "master",
}

The concrete project/clip objects in effect contexts are host runtime objects, not a public mutation API. Treat them as read-only context.

clip_types

clip_types restricts track-scoped effects to compatible clip categories:

Python
api.register_video_effect(
    effect_id="video_only",
    name="Video Only",
    processor=process,
    clip_types=("video",),
)

Master effects are project-wide and are not rejected based on clip type.

time_dependent

Set time_dependent=True when output can change with timeline time even if the input frame and parameters do not:

Python
api.register_video_effect(
    effect_id="shake",
    name="Camera Shake",
    processor=process,
    time_dependent=True,
)

This flag informs the renderer's caching decisions. Marking a time-dependent effect as static can produce stale preview frames.

Custom editor support

register_video_effect() also accepts custom_editor= and window_options=. Use them when an effect needs a visual editor instead of the native parameter form. The processing contract does not change: the returned parameter dictionary is still passed to process(frame, parameters, context) during preview and export.

See Custom editors and plugin windows for the callback signature, PluginWindowOptions, content_renderer, custom topbars and singleton window_key behavior.