Skip to content

ivtc

Functions:

  • jivtc

    This function should only be used when a normal ivtc or ivtc + bobber leaves chroma blend to a every fourth frame.

  • sivtc

    Simplest form of a fieldmatching function.

  • vdecimate

    Perform frame decimation using VDecimate.

  • vfm

    Perform field matching using VFM.

jivtc

jivtc(
    clip: VideoNode,
    pattern: int,
    tff: FieldBasedT | bool | None = None,
    chroma_only: bool = True,
    postprocess: VSFunctionKwArgs = deblend,
    postdecimate: IVTCycles | None = cycle_05,
    ivtc_cycle: IVTCycles = cycle_10,
    final_ivtc_cycle: IVTCycles = cycle_08,
    **kwargs: Any
) -> VideoNode

This function should only be used when a normal ivtc or ivtc + bobber leaves chroma blend to a every fourth frame. You can disable chroma_only to use in luma as well, but it is not recommended.

Parameters:

  • clip

    (VideoNode) –

    Clip to process. Has to be 60i.

  • pattern

    (int) –

    First frame of any clean-combed-combed-clean-clean sequence.

  • tff

    (FieldBasedT | bool | None, default: None ) –

    Set top field first (True) or bottom field first (False).

  • chroma_only

    (bool, default: True ) –

    Decide whether luma too will be processed.

  • postprocess

    (VSFunctionKwArgs, default: deblend ) –

    Function to run after second decimation. Should be either a bobber or a deblender.

  • postdecimate

    (IVTCycles | None, default: cycle_05 ) –

    If the postprocess function doesn't decimate itself, put True.

Returns:

  • VideoNode

    Inverse Telecined clip.

Source code
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
def jivtc(
    clip: vs.VideoNode, pattern: int, tff: FieldBasedT | bool | None = None, chroma_only: bool = True,
    postprocess: VSFunctionKwArgs = deblend, postdecimate: IVTCycles | None = IVTCycles.cycle_05,
    ivtc_cycle: IVTCycles = IVTCycles.cycle_10, final_ivtc_cycle: IVTCycles = IVTCycles.cycle_08,
    **kwargs: Any
) -> vs.VideoNode:
    """
    This function should only be used when a normal ivtc or ivtc + bobber leaves chroma blend to a every fourth frame.
    You can disable chroma_only to use in luma as well, but it is not recommended.

    :param clip:            Clip to process. Has to be 60i.
    :param pattern:         First frame of any clean-combed-combed-clean-clean sequence.
    :param tff:             Set top field first (True) or bottom field first (False).
    :param chroma_only:     Decide whether luma too will be processed.
    :param postprocess:     Function to run after second decimation. Should be either a bobber or a deblender.
    :param postdecimate:    If the postprocess function doesn't decimate itself, put True.

    :return:                Inverse Telecined clip.
    """

    tff = FieldBased.from_param_or_video(tff, clip, True, jivtc).is_tff

    InvalidFramerateError.check(jivtc, clip, (30000, 1001))

    ivtced = clip.std.SeparateFields(tff).std.DoubleWeave(tff)
    ivtced = ivtc_cycle.decimate(ivtced, pattern)

    pprocess = postprocess(clip if postdecimate else ivtced, **kwargs)

    if postdecimate:
        pprocess = postdecimate.decimate(pprocess, pattern)

    inter = core.std.Interleave([ivtced, pprocess])
    final = final_ivtc_cycle.decimate(inter, pattern)

    final = join(ivtced, final) if chroma_only else final

    return FieldBased.ensure_presence(final, FieldBased.PROGRESSIVE)

sivtc

sivtc(
    clip: VideoNode,
    pattern: int = 0,
    tff: FieldBasedT | bool | None = None,
    ivtc_cycle: IVTCycles = cycle_10,
) -> VideoNode

Simplest form of a fieldmatching function.

This is essentially a stripped-down JIVTC offering JUST the basic fieldmatching and decimation part. As such, you may need to combine multiple instances if patterns change throughout the clip.

Parameters:

  • clip

    (VideoNode) –

    Clip to process.

  • pattern

    (int, default: 0 ) –

    First frame of any clean-combed-combed-clean-clean sequence.

  • tff

    (FieldBasedT | bool | None, default: None ) –

    Top-Field-First.

Returns:

  • VideoNode

    IVTC'd clip.

Source code
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def sivtc(
    clip: vs.VideoNode, pattern: int = 0, tff: FieldBasedT | bool | None = None, ivtc_cycle: IVTCycles = IVTCycles.cycle_10
) -> vs.VideoNode:
    """
    Simplest form of a fieldmatching function.

    This is essentially a stripped-down JIVTC offering JUST the basic fieldmatching and decimation part.
    As such, you may need to combine multiple instances if patterns change throughout the clip.

    :param clip:        Clip to process.
    :param pattern:     First frame of any clean-combed-combed-clean-clean sequence.
    :param tff:         Top-Field-First.

    :return:            IVTC'd clip.
    """

    tff = FieldBased.from_param_or_video(tff, clip, True, sivtc).is_tff

    ivtc = clip.std.SeparateFields(tff=tff).std.DoubleWeave()
    ivtc = ivtc_cycle.decimate(ivtc, pattern)

    return FieldBased.PROGRESSIVE.apply(ivtc)

vdecimate

vdecimate(clip: VideoNode, weight: float = 0.0, **kwargs: Any) -> VideoNode

Perform frame decimation using VDecimate.

This function uses VIVTC's VDecimate plugin to remove duplicate frames from telecined content. It's recommended to use the vfm function before running this.

Parameters:

  • clip

    (VideoNode) –

    Input clip to decimate.

  • weight

    (float, default: 0.0 ) –

    Weight for frame blending. If > 0, blends duplicate frames before dropping one. Default: 0.0 (frames are dropped, not blended).

  • kwargs

    (Any, default: {} ) –

    Additional keyword arguments to pass to VDecimate. For a list of parameters, see the VIVTC documentation.

Returns:

  • VideoNode

    Decimated clip with duplicate frames removed or blended.

Source code
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
def vdecimate(clip: vs.VideoNode, weight: float = 0.0, **kwargs: Any) -> vs.VideoNode:
    """
    Perform frame decimation using VDecimate.

    This function uses VIVTC's VDecimate plugin to remove duplicate frames from telecined content.
    It's recommended to use the vfm function before running this.

    :param clip:            Input clip to decimate.
    :param weight:          Weight for frame blending. If > 0, blends duplicate frames before dropping one.
                            Default: 0.0 (frames are dropped, not blended).
    :param kwargs:          Additional keyword arguments to pass to VDecimate.
                            For a list of parameters, see the VIVTC documentation.

    :return:                Decimated clip with duplicate frames removed or blended.
    """

    func = FunctionUtil(clip, vdecimate, None, (vs.YUV, vs.GRAY), (8, 16))

    vdecimate_kwargs = dict[str, Any]()

    if block := kwargs.pop('block', None):
        if isinstance(block, int):
            vdecimate_kwargs |= dict(blockx=block, blocky=block)
        else:
            vdecimate_kwargs |= dict(blockx=block[0], blocky=block[1])

    if not kwargs.get('clip2', None) and func.work_clip.format is not clip.format:
        vdecimate_kwargs |= dict(clip2=clip)

    dryrun = kwargs.pop('dryrun', False)

    if dryrun or weight:
        stats = func.work_clip.vivtc.VDecimate(dryrun=True, **(vdecimate_kwargs | kwargs))

        if dryrun:
            return func.return_clip(stats)

        clip = kwargs.pop('clip2', clip)

        avg = clip.std.AverageFrames(weights=[0, 1 - weight, weight])
        splice = find_prop_rfs(clip, avg, "VDecimateDrop", "==", 1, stats)
        vdecimate_kwargs |= dict(clip2=splice)

    decimate = func.work_clip.vivtc.VDecimate(**(vdecimate_kwargs | kwargs))

    return func.return_clip(decimate)

vfm

vfm(
    clip: VideoNode,
    tff: FieldBasedT | bool | None = None,
    mode: VFMMode = TWO_WAY_MATCH_THIRD_COMBED,
    postprocess: VideoNode | VSFunctionNoArgs | None = None,
    **kwargs: Any
) -> VideoNode

Perform field matching using VFM.

This function uses VIVTC's VFM plugin to detect and match pairs of fields in telecined content.

You can pass a post-processing clip or function that will act on leftover combed frames. If you pass a clip, it will replace combed frames with that clip. If you pass a function, it will run that function on your input clip and replace combed frames with it.

Example usage:

.. code-block:: python

# Run vsaa.Nnedi3 on combed frames
>>> vfm(clip, postprocess=lambda x: Nnedi3().interpolate(x, double_y=False))

Parameters:

  • clip

    (VideoNode) –

    Input clip to field matching telecine on.

  • tff

    (FieldBasedT | bool | None, default: None ) –

    Field order of the input clip. If None, it will be automatically detected.

  • mode

    (VFMMode, default: TWO_WAY_MATCH_THIRD_COMBED ) –

    VFM matching mode. For more information, see :py:class:VFMMode. Default: VFMMode.TWO_WAY_MATCH_THIRD_COMBED.

  • postprocess

    (VideoNode | VSFunctionNoArgs | None, default: None ) –

    Optional function or clip to process combed frames. If a function is passed, it should take a clip as input and return a clip as output. If a clip is passed, it will be used as the postprocessed clip.

  • kwargs

    (Any, default: {} ) –

    Additional keyword arguments to pass to VFM. For a list of parameters, see the VIVTC documentation.

Returns:

  • VideoNode

    Field matched clip with progressive frames.

Source code
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
def vfm(
    clip: vs.VideoNode, tff: FieldBasedT | bool | None = None,
    mode: VFMMode = VFMMode.TWO_WAY_MATCH_THIRD_COMBED,
    postprocess: vs.VideoNode | VSFunctionNoArgs | None = None,
    **kwargs: Any
) -> vs.VideoNode:
    """
    Perform field matching using VFM.

    This function uses VIVTC's VFM plugin to detect and match pairs of fields in telecined content.

    You can pass a post-processing clip or function that will act on leftover combed frames.
    If you pass a clip, it will replace combed frames with that clip. If you pass a function,
    it will run that function on your input clip and replace combed frames with it.

    Example usage:

    .. code-block:: python

        # Run vsaa.Nnedi3 on combed frames
        >>> vfm(clip, postprocess=lambda x: Nnedi3().interpolate(x, double_y=False))

    :param clip:            Input clip to field matching telecine on.
    :param tff:             Field order of the input clip.
                            If None, it will be automatically detected.
    :param mode:            VFM matching mode. For more information, see :py:class:`VFMMode`.
                            Default: VFMMode.TWO_WAY_MATCH_THIRD_COMBED.
    :param postprocess:     Optional function or clip to process combed frames.
                            If a function is passed, it should take a clip as input and return a clip as output.
                            If a clip is passed, it will be used as the postprocessed clip.
    :param kwargs:          Additional keyword arguments to pass to VFM.
                            For a list of parameters, see the VIVTC documentation.

    :return:                Field matched clip with progressive frames.
    """

    func = FunctionUtil(clip, vfm, None, (vs.YUV, vs.GRAY), 8)

    tff = FieldBased.from_param_or_video(tff, clip, True, func.func).field

    vfm_kwargs = dict[str, Any](order=tff, mode=mode)

    if block := kwargs.pop('block', None):
        if isinstance(block, int):
            vfm_kwargs |= dict(blockx=block, blocky=block)
        else:
            vfm_kwargs |= dict(blockx=block[0], blocky=block[1])

    if (y := kwargs.pop('y', None)) and not isinstance(y, int):
        vfm_kwargs |= dict(y0=y[0], y1=y[1])

    if not kwargs.get('clip2', None) and func.work_clip.format is not clip.format:
        vfm_kwargs |= dict(clip2=clip)

    fieldmatch = func.work_clip.vivtc.VFM(**(vfm_kwargs | kwargs))

    if postprocess:
        if callable(postprocess):
            postprocess = postprocess(kwargs.get('clip2', clip))

        fieldmatch = find_prop_rfs(fieldmatch, postprocess, "_Combed", "==", 1)

    return func.return_clip(fieldmatch)