lvsfunc.comparison

Comparison and analysis functions and wrappers.

lvsfunc.comparison.compare(clip_a, clip_b[, ...])

Compare the same frames from two different clips by interleaving them into a single clip.

lvsfunc.comparison.diff()

Create a standard lvsfunc.comparison.Stack between frames from two clips that have differences.

lvsfunc.comparison.diff_hardsub_mask(a, b, ...)

Diff func for lvsfunc.comparison.diff() to use a hardsub mask.

lvsfunc.comparison.interleave(*clips, ...)

Small convenience function for interleaving clips.

lvsfunc.comparison.split(*clips, **namedclips)

Small convenience function for splitting clips along the x-axis and then stacking.

lvsfunc.comparison.stack_compare(*clips[, ...])

Compare two clips by stacking them.

lvsfunc.comparison.stack_horizontal(*clips, ...)

Small convenience function for stacking clips horizontally.

lvsfunc.comparison.stack_planes(clip, /[, ...])

Stacks the planes of a clip.

lvsfunc.comparison.stack_vertical(*clips, ...)

Small convenience function for stacking clips vertically.

lvsfunc.comparison.tile(*clips, **namedclips)

Small convenience function for tiling clips in a rectangular pattern.

class lvsfunc.comparison.Comparer(clips, /, *, label_alignment=7)

Bases: ABC

Base class for comparison functions.

Parameters
  • clips (Union[dict[str, VideoNode], Sequence[VideoNode]]) – A dict mapping names to clips or simply a sequence of clips in a tuple or a list. If given a dict, the names will be overlaid on the clips using vapoursynth.core.text.Text(). If given a simple sequence of clips, the label_alignment parameter will have no effect and the clips will not be labeled. The order of the clips in either a dict or a sequence will be kept in the comparison.

  • label_alignment (int) – An integer from 1-9, corresponding to the positions of the keys on a numpad. Only used if clips is a dict. Determines where to place clip name using vapoursynth.core.text.Text() (Default: 7).

Raises
  • ValueError – Less than two clips passed.

  • ValueErrorlabel_alignment is not between 1–9.

  • ValueError – Unexpected type passed to clips.

property clip: vapoursynth.VideoNode

Return the comparison as a single VideoNode for further manipulation or attribute inspection.

comp_clip = Comparer(...).clip is the intended use in encoding scripts.

Return type

VideoNode

class lvsfunc.comparison.Interleave(clips, /, *, label_alignment=7)

Bases: Comparer

Returns a clip with the frames from all clips interleaved.

For example, Interleave(A=clip1, B=clip2) will return A.Frame 0, B.Frame 0, A.Frame 1, B.Frame 1, …

Acts as a convenience combination function of vapoursynth.core.text.Text() and vapoursynth.core.std.Interleave().

Parameters
  • clips (Union[dict[str, VideoNode], Sequence[VideoNode]]) – A dict mapping names to clips or simply a sequence of clips in a tuple or a list. If given a dict, the names will be overlaid on the clips using vapoursynth.core.text.Text(). If given a simple sequence of clips, the label_alignment parameter will have no effect and the clips will not be labeled. The order of the clips in either a dict or a sequence will be kept in the comparison.

  • label_alignment (int) – An integer from 1-9, corresponding to the positions of the keys on a numpad. Only used if clips is a dict. Determines where to place clip name using vapoursynth.core.text.Text() (Default: 7).

class lvsfunc.comparison.Split(clips, /, *, direction=Direction.HORIZONTAL, label_alignment=7)

Bases: Stack

Split an unlimited amount of clips into one VideoNode with the same dimensions as the original clips.

Handles odd-sized resolutions or resolutions that can’t be evenly split by the amount of clips specified.

The remaining pixel width/height (clip.dimension % number_of_clips) will be always given to the last clip specified. For example, five 104 x 200 clips will result in a ((20 x 200) * 4) + (24 x 200) horizontal stack of clips.

Parameters
  • clips (Union[dict[str, VideoNode], Sequence[VideoNode]]) – A dict mapping names to clips or simply a sequence of clips in a tuple or a list. If given a dict, the names will be overlaid on the clips using vapoursynth.core.text.Text(). If given a simple sequence of clips, the label_alignment parameter will have no effect and the clips will not be labeled. The order of the clips in either a dict or a sequence will be kept in the comparison.

  • direction (Direction) – Determines the axis to split the clips on. (Default: lvsfunc.comparison.Direction.HORIZONTAL)

  • label_alignment (int) – An integer from 1-9, corresponding to the positions of the keys on a numpad. Only used if clips is a dict. Determines where to place clip name using vapoursynth.core.text.Text() (Default: 7).

Raises
  • ValueError – Clip heights and widths don’t match.

  • ValueError – Resulting cropped width or height violates subsampling rules.

class lvsfunc.comparison.Stack(clips, /, *, direction=Direction.HORIZONTAL, label_alignment=7)

Bases: Comparer

Stacks clips horizontally or vertically.

Acts as a convenience combination function of vapoursynth.core.text.Text() and either vapoursynth.core.std.StackHorizontal() or vapoursynth.core.std.StackVertical().

Parameters
  • clips (Union[dict[str, VideoNode], Sequence[VideoNode]]) – A dict mapping names to clips or simply a sequence of clips in a tuple or a list. If given a dict, the names will be overlaid on the clips using vapoursynth.core.text.Text(). If given a simple sequence of clips, the label_alignment parameter will have no effect and the clips will not be labeled. The order of the clips in either a dict or a sequence will be kept in the comparison.

  • direction (Direction) – Direction of the stack (Default: lvsfunc.comparison.Direction.HORIZONTAL).

  • label_alignment (int) – An integer from 1-9, corresponding to the positions of the keys on a numpad. Only used if clips is a dict. Determines where to place clip name using vapoursynth.core.text.Text() (Default: 7).

Raises
  • ValueError – Clips are not the same height for StackHorizontal.

  • ValueError – Clips are not the same width for StackVertical.

class lvsfunc.comparison.Tile(clips, /, *, arrangement=None, label_alignment=7)

Bases: Comparer

Tiles clips in a mosaic manner, filling rows first left-to-right, then stacking.

The arrangement of the clips can be specified with the arrangement parameter. Rows are specified as lists of ints inside of a larger list specifying the order of the rows. Think of this as a 2-dimensional array of 0s and 1s with 0 representing an empty slot and 1 representing the next clip in the sequence.

If arrangement is not specified, the function will attempt to fill a square with dimensions n x n where n is equivalent to math.ceil(math.sqrt(len(clips)). The bottom rows will be dropped if empty.

# For example, for 3 clips, the automatic arrangement becomes:
[
 [1, 1],
 [1, 0]
]

# For 10 clips, the automatic arrangement becomes:
[
 [1, 1, 1, 1],
 [1, 1, 1, 1],
 [1, 1, 0, 0]
]

# For custom arrangements, such as (for 4 clips):
[
 [0, 1, 0, 1],
 [1],
 [0, 1]
]
# the rows will be auto-padded with 0's to be the same length.
Parameters
  • clips (Union[dict[str, VideoNode], Sequence[VideoNode]]) – A dict mapping names to clips or simply a sequence of clips in a tuple or a list. If given a dict, the names will be overlaid on the clips using vapoursynth.core.text.Text(). If given a simple sequence of clips, the label_alignment parameter will have no effect and the clips will not be labeled. The order of the clips in either a dict or a sequence will be kept in the comparison.

  • arrangement (Optional[list[list[int]]]) – 2-dimension array (list of lists) of 0s and 1s representing a list of rows of clips(1) or blank spaces(0) (Default: None)

  • label_alignment (int) – An integer from 1-9, corresponding to the positions of the keys on a numpad. Only used if clips is a dict. Determines where to place clip name using vapoursynth.core.text.Text() (Default: 7).

Raises
  • ValueError – Clip heights and widths don’t match.

  • ValueError – Array is one-dimensional and you should be using lvsfunc.comparison.Stack instead.

  • ValueError – Specified arrangement has an invalid number of clips.

lvsfunc.comparison.compare(clip_a, clip_b, frames=None, rand_total=None, force_resample=True, print_frame=True, mismatch=False)

Compare the same frames from two different clips by interleaving them into a single clip.

Clips are automatically resampled to 8 bit YUV -> RGB24 to emulate how a monitor shows the frame. This can be disabled by setting force_resample to False.

This is not recommended over setting multiple outputs and checking between those, but in the event that is unavailable to you, this function may be useful.

Alias for this function is lvsfunc.comp.

Parameters
  • clip_a (VideoNode) – Clip to compare.

  • clip_b (VideoNode) – Second clip to compare.

  • frames (Optional[list[int]]) – List of frames to compare (Default: None).

  • rand_total (Optional[int]) – Number of random frames to pick (Default: None).

  • force_resample (bool) – Forcibly resamples the clip to RGB24 (Default: True).

  • print_frame (bool) – Print frame numbers (Default: True).

  • mismatch (bool) – Allow for clips with different formats and dimensions to be compared (Default: False).

Return type

VideoNode

Returns

Interleaved clip containing specified frames from clip_a and clip_b.

Raises
  • ValueError – More comparisons requested than frames available.

  • NotEqualFormatsError – Format of given clips don’t match.

lvsfunc.comparison.diff(*clips: vapoursynth.VideoNode, thr: float = 96, height: int = 288, interleave: bool = False, return_ranges: ~typing.Literal[True] = True, exclusion_ranges: ~typing.Optional[~typing.Sequence[int | tuple[int, int]]] = None, diff_func: ~typing.Callable[[vapoursynth.VideoNode, vapoursynth.VideoNode], vapoursynth.VideoNode] = <function <lambda>>, **namedclips: vapoursynth.VideoNode) tuple[vapoursynth.VideoNode, list[tuple[int, int]]]
lvsfunc.comparison.diff(*clips: vapoursynth.VideoNode, thr: float = 96, height: int = 288, interleave: bool = False, return_ranges: ~typing.Literal[False], exclusion_ranges: ~typing.Optional[~typing.Sequence[int | tuple[int, int]]] = None, diff_func: ~typing.Callable[[vapoursynth.VideoNode, vapoursynth.VideoNode], vapoursynth.VideoNode] = <function <lambda>>, **namedclips: vapoursynth.VideoNode) vapoursynth.VideoNode

Create a standard lvsfunc.comparison.Stack between frames from two clips that have differences.

Useful for making comparisons between TV and BD encodes, as well as clean and hardsubbed sources.

There are two methods used here to find differences: If thr is below 1, PlaneStatsDiff is used to figure out the differences. Else, if thr is equal than or higher than 1, PlaneStatsMin/Max are used.

Recommended is PlaneStatsMin/Max, as those seem to catch more outrageous differences without returning too many starved frames.

Note that this might catch artifacting as differences! Make sure you verify every frame with your own eyes!

Alias for this function is lvsfunc.diff.

Parameters
  • clips (vs.VideoNode) – Clips for comparison (order is kept).

  • namedclips (vs.VideoNode) – Keyword arguments of name=clip for all clips in the comparison. Clips will be labeled at the top left with their name.

  • thr (float) – Threshold, <= 1 uses PlaneStatsDiff, > 1 uses Max/Min. Higher values will catch more differences. Value must be lower than 128

  • height (int) – Height in px to downscale clips to if interleave is False. (MakeDiff clip will be twice this resolution)

  • interleave (bool) – Return clip as an interleaved comparison. (using lvsfunc.comparison.Interleave). This will not return a diff clip

  • return_ranges (bool) – Return a list of ranges in addition to the comparison clip.

  • exclusion_ranges (Sequence[int | tuple[int, int]] | None) – Excludes a list of frame ranges from difference checking output (but not processing).

  • diff_func (Callable[[vs.VideoNode, vs.VideoNode], vs.VideoNode]) – Function for calculating diff in PlaneStatsMin/Max mode.

Return type

vs.VideoNode | tuple[vs.VideoNode, list[tuple[int, int]]]

Returns

Either an interleaved clip of the differences between the two clips or a stack of both input clips on top of MakeDiff clip. Furthermore, the function will print the ranges of all the diffs found.

Raises
  • ClipsAndNamedClipsError – Both positional and named clips are given.

  • ValueError – More or less than two clips are given.

  • ValueErrorthr is 128 or higher.

  • VariableFormatError – One of the clips is of a variable format.

  • StopIteration – No differences are found.

lvsfunc.comparison.diff_hardsub_mask(a, b, **kwargs)

Diff func for lvsfunc.comparison.diff() to use a hardsub mask.

This is kinda slow.

Parameters
  • a (VideoNode) – Clip A.

  • b (VideoNode) – Clip B.

Return type

VideoNode

Returns

Diff masked with lvsfunc.dehardsub.hardsub_mask().

lvsfunc.comparison.interleave(*clips, **namedclips)

Small convenience function for interleaving clips.

Parameters
  • clips (VideoNode) – Clips for comparison (order is kept).

  • namedclips (VideoNode) – Keyword arguments of name=clip for all clips in the comparison. Clips will be labeled at the top left with their name.

Return type

VideoNode

Returns

An interleaved clip of all the clips/namedclips specified.

Raises

ClipsAndNamedClipsError – Both positional and named clips are given.

lvsfunc.comparison.split(*clips, **namedclips)

Small convenience function for splitting clips along the x-axis and then stacking.

Accounts for odd-resolution clips by giving overflow columns to the last clip specified. All clips must have the same dimensions (width and height).

Parameters
  • clips (VideoNode) – Clips for comparison (order is kept left to right).

  • namedclips (VideoNode) – Keyword arguments of name=clip for all clips in the comparison. Clips will be labeled at the bottom with their name.

Return type

VideoNode

Returns

A clip with the same dimensions as any one of the input clips. with all clips/namedclips represented as individual vertical slices.

Raises

ClipsAndNamedClipsError – Both positional and named clips are given.

lvsfunc.comparison.stack_compare(*clips, height=None)

Compare two clips by stacking them.

Best to use when trying to match two sources frame-accurately. Alias for this function is lvsfunc.scomp.

Parameters
  • clips (VideoNode) – Clips to compare.

  • height (Optional[int]) – Height in px to rescale clips to. (MakeDiff clip will be twice this resolution). This function will not scale above the first clip’s height (Default: 288).

Return type

VideoNode

Returns

Clip with clips stacked.

Raises

ValueError – More or less than 2 clips are given.

lvsfunc.comparison.stack_horizontal(*clips, **namedclips)

Small convenience function for stacking clips horizontally.

Parameters
  • clips (VideoNode) – Clips for comparison (order is kept left to right).

  • namedclips (VideoNode) – Keyword arguments of name=clip for all clips in the comparison. Clips will be labeled at the top left with their name.

Return type

VideoNode

Returns

A horizontal stack of the clips/namedclips.

Raises

ClipsAndNamedClipsError – Both positional and named clips are given.

lvsfunc.comparison.stack_planes(clip, /, stack_vertical=False)

Stacks the planes of a clip.

For 4:2:0 subsampled clips, the two half-sized planes will be stacked in the opposite direction specified (vertical by default), then stacked with the full-sized plane in the direction specified (horizontal by default).

Parameters
  • clip (VideoNode) – Clip to process (must be in YUV or RGB planar format).

  • stack_vertical (bool) – Stack the planes vertically (Default: False).

Return type

VideoNode

Returns

Clip with stacked planes.

Raises
  • InvalidFormatError – Clip is not YUV or RGB.

  • TypeError – Clip is of an unexpected color family.

  • TypeError – Clip returns an unexpected subsampling.

lvsfunc.comparison.stack_vertical(*clips, **namedclips)

Small convenience function for stacking clips vertically.

Parameters
  • clips (VideoNode) – Clips for comparison (order is kept top to bottom).

  • namedclips (VideoNode) – Keyword arguments of name=clip for all clips in the comparison. Clips will be labeled at the top left with their name.

Return type

VideoNode

Returns

A vertical stack of the clips/namedclips.

Raises

ClipsAndNamedClipsError – Both positional and named clips are given.

lvsfunc.comparison.tile(*clips, **namedclips)

Small convenience function for tiling clips in a rectangular pattern.

All clips must have the same dimensions (width and height). If 3 clips are given, a 2x2 square with one blank slot will be returned. If 6 clips are given, a 3x2 rectangle will be returned.

Parameters
  • clips (VideoNode) – Clips for comparison.

  • namedclips (VideoNode) – Keyword arguments of name=clip for all clips in the comparison. Clips will be labeled at the top left with their name.

Return type

VideoNode

Returns

A clip with all input clips/namedclips automatically tiled most optimally into a rectangular arrrangement.

Raises

ClipsAndNamedClipsError – Both positional and named clips are given.