Skip to content

helpers

Classes:

Functions:

  • get_gpu

    Return the GPU available for the requested device id.

  • is_gpu_available

    Check if a GPU is available for the requested device id.

  • pre_ss

    Supersamples the input clip, applies a given function to the higher-resolution version, and then downscales it back to the original resolution.

  • pscale_blend

    Apply pscale-based error correction/scaling expression.

  • scale_var_clip

    Scale a variable clip to constant or variable resolution.

logger module-attribute

logger = getLogger(__name__)

BottomCrop

BottomCrop = int

LeftCrop

LeftCrop = int

RightCrop

RightCrop = int

TopCrop

TopCrop = int

CropAbs

Bases: NamedTuple

Methods:

Attributes:

height instance-attribute

height: int

left class-attribute instance-attribute

left: int = 0

top class-attribute instance-attribute

top: int = 0

width instance-attribute

width: int

to_rel

to_rel(base_clip: VideoNode) -> CropRel
Source code in vsscale/helpers.py
124
125
126
127
def to_rel(self, base_clip: vs.VideoNode) -> CropRel:
    return CropRel(
        self.left, base_clip.width - self.width - self.left, self.top, base_clip.height - self.height - self.top
    )

CropRel

Bases: NamedTuple

Attributes:

bottom class-attribute instance-attribute

bottom: int = 0

left class-attribute instance-attribute

left: int = 0

right class-attribute instance-attribute

right: int = 0

top class-attribute instance-attribute

top: int = 0

ScalingArgs dataclass

ScalingArgs(
    width: int,
    height: int,
    src_width: float,
    src_height: float,
    src_top: float,
    src_left: float,
    mode: str = "hw",
)

Methods:

Attributes:

height instance-attribute

height: int

mode class-attribute instance-attribute

mode: str = 'hw'

src_height instance-attribute

src_height: float

src_left instance-attribute

src_left: float

src_top instance-attribute

src_top: float

src_width instance-attribute

src_width: float

width instance-attribute

width: int

from_args classmethod

from_args(
    base_clip: VideoNode,
    height: int,
    width: int | None = None,
    *,
    src_top: float = ...,
    src_left: float = ...,
    sample_grid_model: int = MATCH_EDGES,
    mode: str = "hw",
) -> Self
from_args(
    base_clip: VideoNode,
    height: float,
    width: float | None = ...,
    base_height: int | None = ...,
    base_width: int | None = ...,
    src_top: float = ...,
    src_left: float = ...,
    crop: tuple[LeftCrop, RightCrop, TopCrop, BottomCrop]
    | CropRel
    | CropAbs
    | None = ...,
    sample_grid_model: int = MATCH_EDGES,
    mode: str = "hw",
) -> Self
from_args(
    base_clip: VideoNode,
    height: int | float,
    width: int | float | None = None,
    base_height: int | None = None,
    base_width: int | None = None,
    src_top: float = 0,
    src_left: float = 0,
    crop: tuple[LeftCrop, RightCrop, TopCrop, BottomCrop]
    | CropRel
    | CropAbs
    | None = None,
    sample_grid_model: int = MATCH_EDGES,
    mode: str = "hw",
) -> Self

Get (de)scaling arguments for integer scaling.

Parameters:

  • base_clip

    (VideoNode) –

    Source clip.

  • height

    (int | float) –

    Target (de)scaling height. Casting to float will ensure fractional calculations.

  • width

    (int | float | None, default: None ) –

    Target (de)scaling width. Casting to float will ensure fractional calculations. If None, it will be calculated from the height and the aspect ratio of the base_clip.

  • base_height

    (int | None, default: None ) –

    The height from which to contain the clip. If None, it will be calculated from the height.

  • base_width

    (int | None, default: None ) –

    The width from which to contain the clip. If None, it will be calculated from the width.

  • src_top

    (float, default: 0 ) –

    Vertical offset.

  • src_left

    (float, default: 0 ) –

    Horizontal offset.

  • crop

    (tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] | CropRel | CropAbs | None, default: None ) –

    Tuple of cropping values, or relative/absolute crop specification.

  • mode

    (str, default: 'hw' ) –

    Scaling mode:

    • "w" means only the width is calculated.
    • "h" means only the height is calculated.
    • "hw" or "wh" mean both width and height are calculated.
  • sample_grid_model

    (int, default: MATCH_EDGES ) –

    Model used to align sampling grid.

Returns:

  • Self

    ScalingArgs object suitable for scaling functions.

Source code in vsscale/helpers.py
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
@classmethod
def from_args(
    cls,
    base_clip: vs.VideoNode,
    height: int | float,  # noqa: PYI041
    width: int | float | None = None,  # noqa: PYI041
    base_height: int | None = None,
    base_width: int | None = None,
    src_top: float = 0,
    src_left: float = 0,
    crop: tuple[LeftCrop, RightCrop, TopCrop, BottomCrop] | CropRel | CropAbs | None = None,
    sample_grid_model: int = SampleGridModel.MATCH_EDGES,
    mode: str = "hw",
) -> Self:
    """
    Get (de)scaling arguments for integer scaling.

    Args:
        base_clip: Source clip.
        height: Target (de)scaling height. Casting to float will ensure fractional calculations.
        width: Target (de)scaling width. Casting to float will ensure fractional calculations. If None, it will be
            calculated from the height and the aspect ratio of the base_clip.
        base_height: The height from which to contain the clip. If None, it will be calculated from the height.
        base_width: The width from which to contain the clip. If None, it will be calculated from the width.
        src_top: Vertical offset.
        src_left: Horizontal offset.
        crop: Tuple of cropping values, or relative/absolute crop specification.
        mode: Scaling mode:

               - "w" means only the width is calculated.
               - "h" means only the height is calculated.
               - "hw" or "wh" mean both width and height are calculated.

        sample_grid_model: Model used to align sampling grid.

    Returns:
        ScalingArgs object suitable for scaling functions.
    """
    if crop:
        if isinstance(crop, CropAbs):
            crop = crop.to_rel(base_clip)
        elif not isinstance(crop, CropRel):
            crop = CropRel(*crop)
    else:
        crop = CropRel()

    ratio_height = height / base_clip.height

    if width is None:
        # Integer scaling -> compute width from aspect ratio
        # Fractional scaling -> proportional scaling
        width = get_w(height, base_clip, 2) if isinstance(height, int) else ratio_height * base_clip.width

    ratio_width = width / base_clip.width

    if all(
        [
            isinstance(height, int),
            isinstance(width, int),
            base_height is None,
            base_width is None,
            crop == (0, 0, 0, 0),
            not sample_grid_model,
        ]
    ):
        return cls(int(width), int(height), int(width), int(height), src_top, src_left, mode)

    if base_height is None:
        base_height = mod2(ceil(height))

    if base_width is None:
        base_width = mod2(ceil(width))

    # half of (container - target), plus cropped portion
    margin_left = (base_width - width) / 2 + ratio_width * crop.left
    margin_right = (base_width - width) / 2 + ratio_width * crop.right
    # Cropped output = container minus floored margins
    cropped_width = base_width - floor(margin_left) - floor(margin_right)

    margin_top = (base_height - height) / 2 + ratio_height * crop.top
    margin_bottom = (base_height - height) / 2 + ratio_height * crop.bottom
    cropped_height = base_height - floor(margin_top) - floor(margin_bottom)

    # Compute src width/height after crop and scaling

    if isinstance(width, int) and crop.left == crop.right == 0:
        # Fully integer width + no crop = source width equals cropped container width
        cropped_src_width = float(cropped_width)
    else:
        # Otherwise scale from cropped source region
        cropped_src_width = ratio_width * (base_clip.width - crop.left - crop.right)

    # Horizontal source offset: fractional remainder + user offset
    cropped_src_left = margin_left - floor(margin_left) + src_left

    if isinstance(height, int) and crop.top == crop.bottom == 0:
        cropped_src_height = float(cropped_height)
    else:
        cropped_src_height = ratio_height * (base_clip.height - crop.top - crop.bottom)

    cropped_src_top = margin_top - floor(margin_top) + src_top

    if sample_grid_model:
        sgm = SampleGridModel.from_param(sample_grid_model, cls.from_args)

        # sample_grid_model() adjusts sampling grid and may modify src_top/left and src dimensions
        kw, (cropped_src_top, cropped_src_left) = sgm(
            cropped_src_width,
            cropped_src_height,
            base_clip.width - crop.left - crop.right,
            base_clip.height - crop.top - crop.bottom,
            (cropped_src_top, cropped_src_left),
            {},
        )
        cropped_src_width, cropped_src_height = kw["src_width"], kw["src_height"]

    return cls(
        cropped_width,
        cropped_height,
        cropped_src_width,
        cropped_src_height,
        cropped_src_top,
        cropped_src_left,
        mode,
    )

kwargs

kwargs(clip_or_rate: VideoNode | float | None = None) -> dict[str, Any]
Source code in vsscale/helpers.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
def kwargs(self, clip_or_rate: vs.VideoNode | float | None = None, /) -> dict[str, Any]:
    kwargs = dict[str, Any]()

    do_h, do_w = self._do()

    if isinstance(clip_or_rate, (vs.VideoNode, NoneType)):
        up_rate_h, up_rate_w = self._up_rate(clip_or_rate)
    else:
        up_rate_h, up_rate_w = clip_or_rate, clip_or_rate

    if do_h:
        kwargs.update(src_height=self.src_height * up_rate_h, src_top=self.src_top * up_rate_h)

    if do_w:
        kwargs.update(src_width=self.src_width * up_rate_w, src_left=self.src_left * up_rate_w)

    return kwargs

get_gpu cached

get_gpu(device_id: int = 0) -> Device | None

Return the GPU available for the requested device id.

Source code in vsscale/helpers.py
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
@cache
def get_gpu(device_id: int = 0) -> Device | None:
    """
    Return the GPU available for the requested device id.
    """
    from pyopencl import device_type, get_platforms

    if not (platforms := get_platforms()):
        logger.debug("No OpenCL platforms found.")
        return None

    try:
        # platform also resolves any software/cpu targets
        # but it doesn't seem like any one platform can have multiple devices
        gpus = [device for device in [pl.get_devices()[0] for pl in platforms] if device.type == device_type.GPU]
    except Exception as e:
        logger.debug(e, exc_info=e)
        return None

    try:
        return gpus[device_id]
    except KeyError:
        raise CustomValueError(f"No GPU found for device_id {device_id}!") from None

is_gpu_available

is_gpu_available(device_id: int = 0) -> bool

Check if a GPU is available for the requested device id.

Source code in vsscale/helpers.py
553
554
555
556
557
def is_gpu_available(device_id: int = 0) -> bool:
    """
    Check if a GPU is available for the requested device id.
    """
    return get_gpu(device_id) is not None

pre_ss

pre_ss(
    clip: VideoNode,
    function: VSFunctionNoArgs,
    rfactor: float = 2.0,
    sp: type[MixedScalerProcess[Any, Any]] = ComplexSuperSamplerProcess,
    *,
    mod: int = 4,
    pscale: float = 1.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> VideoNode
pre_ss(
    clip: VideoNode,
    *,
    rfactor: float = 2.0,
    sp: MixedScalerProcess[Any, Any],
    mod: int = 4,
    pscale: float = 1.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> VideoNode
pre_ss(
    clip: VideoNode,
    function: VSFunctionNoArgs,
    rfactor: float = 2.0,
    *,
    supersampler: ScalerLike | Callable[[VideoNode, int, int], VideoNode],
    downscaler: ScalerLike | Callable[[VideoNode, int, int], VideoNode],
    mod: int = 4,
    pscale: float = 1.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> VideoNode
pre_ss(
    clip: VideoNode,
    function: VSFunctionNoArgs | None = None,
    rfactor: float = 2.0,
    sp: type[MixedScalerProcess[Any, Any]]
    | MixedScalerProcess[Any, Any] = ComplexSuperSamplerProcess,
    supersampler: ScalerLike
    | Callable[[VideoNode, int, int], VideoNode]
    | None = None,
    downscaler: ScalerLike
    | Callable[[VideoNode, int, int], VideoNode]
    | None = None,
    mod: int = 4,
    pscale: float = 1.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> VideoNode

Supersamples the input clip, applies a given function to the higher-resolution version, and then downscales it back to the original resolution.

This function generalizes the behavior of SuperSamplerProcess and ComplexSuperSamplerProcess.

  • Examples:

    out = pre_ss(clip, lambda clip: cool_function(clip, ...), planes=0)
    

    • Passing NNEDI3 as a supersampler:
      from vsaa import SuperSamplerProcess
      
      out = pre_ss(clip, lambda clip: cool_function(clip, ...), SuperSamplerProcess)
      
    • This works too:

      from vsaa import SuperSamplerProcess
      
      out = pre_ss(clip, sp=SuperSamplerProcess(function=lambda clip: cool_function(clip, ...)))
      

    • Specifying supersampler and downscaler:

      from vskernels import Point
      
      out = pre_ss(clip, lambda clip: cool_function(clip, ...), supersampler=Point, downscaler=Point, planes=0)
      

Parameters:

Returns:

  • VideoNode

    A clip with the given function applied at higher resolution, then downscaled back.

Source code in vsscale/helpers.py
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
def pre_ss(
    clip: vs.VideoNode,
    function: VSFunctionNoArgs | None = None,
    rfactor: float = 2.0,
    sp: type[MixedScalerProcess[Any, Any]] | MixedScalerProcess[Any, Any] = ComplexSuperSamplerProcess,
    supersampler: ScalerLike | Callable[[vs.VideoNode, int, int], vs.VideoNode] | None = None,
    downscaler: ScalerLike | Callable[[vs.VideoNode, int, int], vs.VideoNode] | None = None,
    mod: int = 4,
    pscale: float = 1.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> vs.VideoNode:
    """
    Supersamples the input clip, applies a given function to the higher-resolution version, and then downscales it back to the original resolution.

    This function generalizes the behavior of
    [SuperSamplerProcess][vsaa.deinterlacers.SuperSamplerProcess] and
    [ComplexSuperSamplerProcess][vsscale.various.ComplexSuperSamplerProcess].

    - Examples:
        ```py
        out = pre_ss(clip, lambda clip: cool_function(clip, ...), planes=0)
        ```

        - Passing NNEDI3 as a supersampler:
        ```py
        from vsaa import SuperSamplerProcess

        out = pre_ss(clip, lambda clip: cool_function(clip, ...), SuperSamplerProcess)
        ```
        - This works too:
        ```py
        from vsaa import SuperSamplerProcess

        out = pre_ss(clip, sp=SuperSamplerProcess(function=lambda clip: cool_function(clip, ...)))
        ```

        - Specifying `supersampler` and `downscaler`:
        ```py
        from vskernels import Point

        out = pre_ss(clip, lambda clip: cool_function(clip, ...), supersampler=Point, downscaler=Point, planes=0)
        ```

    Args:
        clip: Source clip.
        function: A function to apply on the supersampled clip.
        rfactor: Scaling factor for supersampling. Defaults to 2.
        sp: A [MixedScalerProcess][vskernels.MixedScalerProcess] instance or class.
            Default is [ComplexSuperSamplerProcess[Lanczos]][vsscale.ComplexSuperSamplerProcess].
            It upscales with [Lanczos][vskernels.Lanczos] and downscales with [Point][vskernels.Point].
        supersampler: Scaler used to upscale the input clip if `sp` is not specified.
        downscaler: Downscaler used for undoing the upscaling done by the supersampler if `sp` is not specified.
        mod: Ensures the supersampled resolution is a multiple of this value. Defaults to 4.
        pscale: Scaling correction strength.
        planes: Which planes to process.
        func: An optional function to use for error handling.

    Returns:
        A clip with the given function applied at higher resolution, then downscaled back.
    """  # noqa: E501
    func_util = FunctionUtil(clip, func or pre_ss, planes)

    args = (
        func_util.work_clip,
        mod_x(func_util.work_clip.width * rfactor, mod),
        mod_x(func_util.work_clip.height * rfactor, mod),
    )

    if isinstance(sp, MixedScalerProcess):
        if pscale != 1.0:
            raise CustomValueError("pscale is not supported when using a MixedScalerProcess!", func_util.func)
        return func_util.return_clip(sp.scale(*args))

    if supersampler and downscaler and function:
        ss = _get_scaled(supersampler, *args, func_util.func)

        processed = function(ss)

        down = _get_scaled(downscaler, processed, clip.width, clip.height, func_util.func)
        down = pscale_blend(
            func_util.work_clip,
            down,
            lambda: _get_scaled(downscaler, ss, clip.width, clip.height, func_util.func),
            pscale,
            func=func_util.func,
        )

        return func_util.return_clip(down)

    if function:
        return pre_ss(clip, sp=sp(function=function), rfactor=rfactor, mod=mod, pscale=pscale, planes=planes, func=func)

    raise CustomTypeError

pscale_blend

pscale_blend(
    clip: VideoNode,
    processed: VideoNode,
    unprocessed: VideoNode | Callable[[], VideoNode],
    pscale: float = 0.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> VideoNode

Apply pscale-based error correction/scaling expression.

This function calculates a blend of the processed clip, the original clip, and an unprocessed, re-scaled and downscaled clip to correct downscaling artifacts/ringing.

The formula evaluated is

y + (1 - pscale) * (x - z)

Where
  • x is clip (original input clip)
  • y is processed (processed and downscaled clip)
  • z is unprocessed (unprocessed and downscaled clip)
  • Behavior of pscale:
    • 1.0: No correction is applied (y is returned).
    • 0.5: The scaling change is blended back at half strength.
    • 0.0: The scaling change is blended back at full strength.
    • > 1.0: Subtracts scaling changes (acts as a low-pass/blur).
    • < 0.0: Amplifies scaling changes (acts as a low-quality sharpen).

Parameters:

  • clip

    (VideoNode) –

    Original input clip (x).

  • processed

    (VideoNode) –

    Processed and resampled/downscaled clip (y).

  • unprocessed

    (VideoNode | Callable[[], VideoNode]) –

    Unprocessed resampled/downscaled clip or a callable that returns it (z).

  • pscale

    (float, default: 0.0 ) –

    Scale factor/correction strength.

  • planes

    (Planes, default: None ) –

    Planes to process.

  • func

    (FuncExcept | None, default: None ) –

    Function returned for custom error handling.

Returns: The blended/corrected clip.

Source code in vsscale/helpers.py
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
def pscale_blend(
    clip: vs.VideoNode,
    processed: vs.VideoNode,
    unprocessed: vs.VideoNode | Callable[[], vs.VideoNode],
    pscale: float = 0.0,
    planes: Planes = None,
    func: FuncExcept | None = None,
) -> vs.VideoNode:
    """
    Apply pscale-based error correction/scaling expression.

    This function calculates a blend of the processed clip, the original clip,
    and an unprocessed, re-scaled and downscaled clip to correct downscaling artifacts/ringing.

    The formula evaluated is:
        `y + (1 - pscale) * (x - z)`

    Where:
        - `x` is `clip` (original input clip)
        - `y` is `processed` (processed and downscaled clip)
        - `z` is `unprocessed` (unprocessed and downscaled clip)

    - Behavior of `pscale`:
        - `1.0`: No correction is applied (`y` is returned).
        - `0.5`: The scaling change is blended back at half strength.
        - `0.0`: The scaling change is blended back at full strength.
        - `> 1.0`: Subtracts scaling changes (acts as a low-pass/blur).
        - `< 0.0`: Amplifies scaling changes (acts as a low-quality sharpen).

    Args:
        clip: Original input clip (x).
        processed: Processed and resampled/downscaled clip (y).
        unprocessed: Unprocessed resampled/downscaled clip or a callable that returns it (z).
        pscale: Scale factor/correction strength.
        planes: Planes to process.
        func: Function returned for custom error handling.
    Returns:
        The blended/corrected clip.
    """
    func = func or pscale_blend

    if pscale == 1.0:
        return processed

    if callable(unprocessed):
        unprocessed = unprocessed()

    return norm_expr([clip, processed, unprocessed], f"x z - {1.0 - pscale} * y +", planes, func=func)

scale_var_clip

scale_var_clip(
    clip: VideoNode,
    scaler: Scaler | Callable[[tuple[int, int]], Scaler],
    width: int | Callable[[tuple[int, int]], int] | None,
    height: int | Callable[[tuple[int, int]], int],
    shift: tuple[float, float]
    | Callable[[tuple[int, int]], tuple[float, float]] = (0, 0),
    debug: bool = False,
) -> VideoNode

Scale a variable clip to constant or variable resolution.

Parameters:

  • clip

    (VideoNode) –

    Source clip.

  • scaler

    (Scaler | Callable[[tuple[int, int]], Scaler]) –

    A scaler instance or a callable that returns a scaler instance.

  • width

    (int | Callable[[tuple[int, int]], int] | None) –

    A width integer or a callable that returns the width. If None, it will be calculated from the height and the aspect ratio of the clip.

  • height

    (int | Callable[[tuple[int, int]], int]) –

    A height integer or a callable that returns the height.

  • shift

    (tuple[float, float] | Callable[[tuple[int, int]], tuple[float, float]], default: (0, 0) ) –

    Optional top shift, left shift tuple or a callable that returns the shifts. Defaults to no shift.

  • debug

    (bool, default: False ) –

    If True, the var_width and var_height props will be added to the clip.

Returns:

  • VideoNode

    Scaled clip.

Source code in vsscale/helpers.py
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def scale_var_clip(
    clip: vs.VideoNode,
    scaler: Scaler | Callable[[tuple[int, int]], Scaler],
    width: int | Callable[[tuple[int, int]], int] | None,
    height: int | Callable[[tuple[int, int]], int],
    shift: tuple[float, float] | Callable[[tuple[int, int]], tuple[float, float]] = (0, 0),
    debug: bool = False,
) -> vs.VideoNode:
    """
    Scale a variable clip to constant or variable resolution.

    Args:
        clip: Source clip.
        scaler: A scaler instance or a callable that returns a scaler instance.
        width: A width integer or a callable that returns the width. If None, it will be calculated from the height and
            the aspect ratio of the clip.
        height: A height integer or a callable that returns the height.
        shift: Optional top shift, left shift tuple or a callable that returns the shifts. Defaults to no shift.
        debug: If True, the `var_width` and `var_height` props will be added to the clip.

    Returns:
        Scaled clip.
    """
    cached_clips = dict[str, vs.VideoNode]()

    no_accepts_var = list[Scaler]()

    def _eval_scale(f: vs.VideoFrame, n: int) -> vs.VideoNode:
        key = f"{f.width}_{f.height}"

        if key not in cached_clips:
            res = (f.width, f.height)

            norm_scaler = scaler(res) if callable(scaler) else scaler
            norm_shift = shift(res) if callable(shift) else shift
            norm_height = height(res) if callable(height) else height

            if width is None:
                norm_width = get_w(norm_height, f.width / f.height)
            else:
                norm_width = width(res) if callable(width) else width

            part_scaler = partial(norm_scaler.scale, width=norm_width, height=norm_height, shift=norm_shift)

            scaled = clip
            if (scaled.width, scaled.height) != (norm_width, norm_height):
                if norm_scaler not in no_accepts_var:
                    try:
                        scaled = part_scaler(clip)
                    except Exception:  # noqa: BLE001
                        no_accepts_var.append(norm_scaler)

                if norm_scaler in no_accepts_var:
                    const_clip = clip.resize.Point(f.width, f.height)

                    scaled = part_scaler(const_clip)

            if debug:
                scaled = scaled.std.SetFrameProps(var_width=f.width, var_height=f.height)

            cached_clips[key] = scaled

        return cached_clips[key]

    out_clip = clip if callable(width) or callable(height) else clip.std.BlankClip(width, height)

    return out_clip.std.FrameEval(_eval_scale, clip, clip)