Video effects
Register a video effect with register_video_effect():
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
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:
{
"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:
{
"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:
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:
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.