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.1.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.1-py3-none-any.whl (23.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: nativeres-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 64b56313d2429645c97cf6bf4f6c2da004fbcaa607579a83a12f6a7cd642e9b0
MD5 70c274288349540c10344c491311121e
BLAKE2b-256 eebd9d30b9d6af817b1b9fc8287ca3dbfe0352ec721bb9bd6aca72ef6b82fb66

See more details on using hashes here.

Provenance

The following attestation bundles were made for nativeres-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: nativeres-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 23.7 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9047434967b9f27b6a09545a829d2da526f9957b76280b0ca455b8cf9b2041ef
MD5 79ea4edf1c06908daf6a4a4d416bfb5e
BLAKE2b-256 eadf1acef0709844876b44d4d5fc7764332463e2383771c23b502e290fc384aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for nativeres-0.1.1-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