Skip to main content

Descale analysis tools for VapourSynth

Project description

nativeres

nativeres is a set of descale analysis tools for VapourSynth.

It combines and supersedes the following tools:

The package provides:

  • A CLI for frame analysis
  • A Python API for VapourSynth scripts and tooling
  • An optional VSView plugin

What it does

nativeres helps answer three common descale questions:

  • getnative: What native resolution was this frame likely upscaled from?
  • getscaler: Which scaler most likely produced this upscale?
  • getfreq: Does the frame's frequency distribution show likely scaling artifacts or native-resolution clues?

Installation

# Install the package with `pip`
pip install nativeres
# Or with `uv`
uv tool install nativeres

VSView plugin

This repository also contains a VSView plugin package.

pip install nativeres[plugin]
# Or with uv
uv tool install nativeres[plugin]

The plugin registers as a VSView tool panel and tool dock under Native Resolution.

Usage can be found in the plugin README.

Usage

CLI

nativeres accepts regular media files, images, and VapourSynth scripts (.vpy / .py). For scripts, the first VapourSynth output is used.

  • Displays a plot to determine the native resolution height for the frame 15000 with the Bilinear kernel:

    nativeres getnative file.m2ts --frame 15000 --dim-mode height --kernel bilinear
    

    nativeres getnative

    Right-click the plot to open the context menu, where you can reset zoom and copy or export the plot as PNG, SVG, JSON, or CSV.

  • Displays a table showing the errors of the inverse scalers at height 800 for frame 15000.

    nativeres getscaler file.m2ts 800 --frame 15000 --dim-mode height
    

    nativeres getscaler

  • Compute and display a DCT-based frequency plot for the selected frame.

    nativeres getfreq file.m2ts --frame 15000
    

    nativeres getfreq

    The frequency plot uses the same right-click context menu for reset zoom plus copy/export actions.

Python

from nativeres import getnative
from vskernels import Bilinear

clip = ...  # Your VapourSynth clip

results = getnative(
    clip,
    frame_num=15000,
    dimensions=((clip.width, h) for h in range(540, 901)),
    kernel=Bilinear(),
)

best = min(results, key=lambda result: result.error)
print(best.dim.height, best.error)

CLI Reference

Main help:

nativeres --help

getnative help:

nativeres getnative --help

getscaler help:

nativeres getscaler --help

getfreq help:

nativeres getfreq --help

Python API

function getnative

getnative(
    clip: VideoNode,
    frame_num: int,
    dimensions: Iterable[tuple[float, float]],
    kernel: ComplexKernelLike,
    crop: tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] | None = None,
    shift: tuple[TopShift, LeftShift] = (0, 0),
    metric_mode: MetricMode = 'MAE',
    borders_aware: bool | int | tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] = 8,
    progress_cb: Callable[[int, int], None] | None = None,
    func: FuncExcept | None = None,
    **kwargs: Any
) -> list[GetNativeResult]

Determine the best (fractional) native resolution for a selected frame.

This checks a list of candidate resolutions by descaling the selected frame using kernel and comparing the result to the source frame using metric_mode.

Args:

  • clip: Source clip.
  • frame_num: Frame index in clip to evaluate.
  • dimensions: Iterable of candidate resolutions to test. Each item may be a (width, height) tuple.
  • kernel: Kernel used to perform each descale attempt.
  • crop: Optional crop to apply before descaling. Aspect ratio is preserved.
  • shift: Optional pixel shift applied during descaling: (top_shift, left_shift).
  • metric_mode: Error metric to use: "MSE", "MAE", or "RMSE".
  • borders_aware: Amount (or crop tuple) to ignore at image borders to avoid edge noise when computing the metric.
  • progress_cb: Optional progress callback called as progress_cb(current, total).
  • func: Function returned for custom error handling.
  • kwargs: Additional arguments passed to the Rescale class.

Returns: A list of GetNativeResult items. Each item contains the tested fractional resolution (dim) and its associated error.


function getscaler

getscaler(
    clip: VideoNode,
    frame_num: int,
    width: float,
    height: float,
    kernels: ComplexKernelLike | Sequence[ComplexKernelLike],
    base_width: int | None = None,
    base_height: int | None = None,
    crop: tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] | None = None,
    shift: tuple[TopShift, LeftShift] = (0, 0),
    metric_mode: MetricMode = 'MAE',
    mask: MaskLike | None = None,
    borders_aware: bool | int | tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] = 8,
    func: FuncExcept | None = None,
    **kwargs: Any
)  list[GetScalerResult]

Find the best inverse scaler (kernel) for a given frame of a clip.

Each supplied kernel is tested by descaling the selected frame to the provided (width, height) and computing an error metric.

Args:

  • clip: Source clip.
  • frame_num: Frame index in clip to evaluate.
  • width: Width to be descaled to. If passed as a float, a fractional descale is performed.
  • height: Height to be descaled to. If passed as a float, a fractional descale is performed.
  • kernels: A single kernel or a sequence of kernels to evaluate.
  • base_width: Optional integer height to contain the clip within.
  • base_height: Optional integer width to contain the clip within.
  • crop: Optional crop to apply before descaling. Aspect ratio is preserved.
  • shift: Pixel shifts applied during descaling: (top_shift, left_shift).
  • metric_mode: Error metric to use: "MSE", "MAE", or "RMSE".
  • mask: Optional edge-detection mask to reduce noise influence on the metric.
  • borders_aware: Amount (or crop tuple) to ignore at image borders to avoid edge noise when computing the metric.
  • func: Function returned for custom error handling.
  • kwargs: Additional arguments passed to the Rescale class.

Returns: A list of GetScalerResult items. Each item contains the evaluated kernel and its associated error.


function get_descale_error

get_descale_error(
    clip: VideoNode,
    frame_num: int,
    width: float,
    height: float,
    kernel: ComplexKernelLike,
    base_width: int | None = None,
    base_height: int | None = None,
    crop: tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] | None = None,
    shift: tuple[TopShift, LeftShift] = (0, 0),
    metric_mode: MetricMode = 'MAE',
    mask: MaskLike | None = None,
    borders_aware: bool | int | tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] = 8,
    func: FuncExcept | None = None,
    **kwargs: Any
)  float

Compute the descale error for a selected frame using a specific kernel.

Args:

  • clip: Source clip.
  • frame_num: Frame index in clip to evaluate.
  • width: Width to be descaled to. If passed as a float, a fractional descale is performed.
  • height: Height to be descaled to. If passed as a float, a fractional descale is performed.
  • kernel: Kernel used for the descale operation.
  • base_width: Optional integer height to contain the clip within.
  • base_height: Optional integer width to contain the clip within.
  • crop: Optional crop to apply before descaling. Aspect ratio is preserved.
  • shift: Pixel shifts applied during descaling: (top_shift, left_shift).
  • metric_mode: Error metric to use: "MSE", "MAE", or "RMSE".
  • mask: Optional edge-detection mask to reduce noise influence on the metric.
  • borders_aware: Amount (or crop tuple) to ignore at image borders to avoid edge noise when computing the metric.
  • func: Function returned for custom error handling.
  • kwargs: Additional arguments passed to the Rescale class.

Returns: The computed error as a float. Lower values indicate a better descale match.


function get_dct_distribution

get_dct_distribution(
    clip: VideoNode,
    frame_num: int,
    cull_rate: float = 3.0,
    func: FuncExcept | None = None
)  tuple[NpFloatArray1D, NpFloatArray1D]

Calculate DCT frequency distribution for both horizontal and vertical dimensions of a selected frame.

Args:

  • clip: Source clip.
  • frame_num: Frame index in clip to analyze.
  • cull_rate: Cull rate for DCT coefficients.
  • func: Function returned for custom error handling.

Returns: A tuple of (dct_h, dct_v).


class GetNativeResult

Result for getnative, pairing a fractional resolution with an error metric.


class GetScalerResult

Result for getscaler, pairing a kernel with its error.


class ResolutionFrac

Fractional resolution expressed as floating-point width and height.

Notes

  • You should always visually verify the results on multiple frames before committing to a descale setup.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nativeres-0.1.0.tar.gz (33.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nativeres-0.1.0-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

Details for the file nativeres-0.1.0.tar.gz.

File metadata

  • Download URL: nativeres-0.1.0.tar.gz
  • Upload date:
  • Size: 33.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nativeres-0.1.0.tar.gz
Algorithm Hash digest
SHA256 eaab3f142e5f387167385144c8959d75416e53993c9c85f5844aa7d1b4f0328d
MD5 03489d8e301f21330875d340db705ca4
BLAKE2b-256 136c0778746e495397e879a344c58e17f987fbac2aa80873c609c5d3c41795ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for nativeres-0.1.0.tar.gz:

Publisher: pypipublish.yml on Jaded-Encoding-Thaumaturgy/nativeres

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nativeres-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: nativeres-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nativeres-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e7d6c9bb7cd486721f552fd87d6b77327c300ab042b3c675af97ef95e509eaee
MD5 546deb22d99c4f11afd6429609705c7d
BLAKE2b-256 9a425642b19b79c196e076f0618c75678d0208df6ac9de814d2c1aa1c98cc41a

See more details on using hashes here.

Provenance

The following attestation bundles were made for nativeres-0.1.0-py3-none-any.whl:

Publisher: pypipublish.yml on Jaded-Encoding-Thaumaturgy/nativeres

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page