scenechange

Scene change detection plugin for VapourSynth.

View on GitHub

scenechange

Python versions PyPI - Version GitHub tag (with filter) License GitHub commits since latest release (by SemVer including pre-releases) QA Tests Coverage Status Dependabot Documentation Status mypy uv pytest Ruff Downloads Stargazers pre-commit Prettier

@Tatsh Buy Me A Coffee Libera.Chat Mastodon Follow Patreon

Scene change detection plugin for VapourSynth.

The project builds two VapourSynth plugins:

The vapoursynth-scenechange Python package bundles both compiled plugins together with a small wrapper (scenechange.TemporalSoften) that stitches them into a single function call.

Building and installing

Requirements:

Configure, build, and install:

meson setup build
meson compile -C build
meson install -C build

By default the plugins install to <libdir>/vapoursynth. Override the location with -Dplugins_dir=/path/to/plugins at configure time. Other options are -Dtests=enabled (build the cmocka test suite), -Dforce_generic=true (use the scalar kernel on SIMD-capable hosts), -Ddocs=true (build the Doxygen API documentation), and -Dfetch_vapoursynth_headers=false (never download VapourSynth4.h).

Python package

Prebuilt wheels that bundle both plugins are published to PyPI, so most users do not need to build anything from source:

pip install vapoursynth-scenechange

Following the VapourSynth packaging conventions, the wheel installs the compiled plugins into <site-packages>/vapoursynth/plugins, which VapourSynth autoloads. Nothing needs to be imported or loaded to make scd and focus2 available. The scenechange Python module is installed alongside them and declares vapoursynth as a dependency. Building the plugins from source with Meson (above) is only needed for development or for platforms without a published wheel. See Python wrapper for usage.

Usage

scd.Detect

clip = core.scd.Detect(clip, thresh, interval_h, interval_v, log)

Detect scene changes and attach _SceneChangePrev and _SceneChangeNext properties to the clip.

scd.ApplyLog

clip = core.scd.ApplyLog(clip, log)

Apply _SceneChangePrev and _SceneChangeNext properties to the clip from a log previously produced by scd.Detect.

Supported colour families are GRAY (8-bit and 16-bit) and YUV (8-bit, 9-bit, 10-bit, and 16-bit).

focus2.TemporalSoften2

clip = core.focus2.TemporalSoften2(
    clip, radius, luma_threshold, chroma_threshold, scenechange, mode
)

YUV or Gray example. The plugins autoload from the VapourSynth plugins directory, so core.std.LoadPlugin is only needed when they were installed somewhere else:

import vapoursynth as vs

core = vs.core

clip = core.scd.Detect(clip, thresh=20)
clip = core.focus2.TemporalSoften2(clip)

RGB example (scene detection requires GRAY8, so the properties must be copied back):

def copy_sc(n, f):
    fout = f[0].copy()
    fout.props._SceneChange = f[1].props._SceneChange[0]
    return fout


tmp = core.resize.Point(clip, format=vs.GRAY8)
tmp = core.scd.Detect(tmp, thresh=20)
clip = core.std.ModifyFrame([clip, tmp], copy_sc)
clip = core.focus2.TemporalSoften2(clip)

Python wrapper

The TemporalSoften class in the scenechange package collapses the boilerplate above into a single call and handles the RGB property-copy step automatically:

import vapoursynth as vs
from scenechange import TemporalSoften

core = vs.core
clip = TemporalSoften(core).soften(clip, luma_threshold=4)

Credits

Original plugins by Oka Motofumi (chikuzen.mo at gmail dot com).