Skip to content

props

Functions:

  • get_clip_filepath

    Helper function to get the file path from a clip.

  • get_prop

    Get FrameProp prop from frame frame with expected type t.

  • get_props

    Get multiple frame properties from a clip.

  • merge_clip_props

    Merge frame properties from all provided clips.

CT module-attribute

CT = TypeVar('CT')

DT module-attribute

DT = TypeVar('DT')

get_clip_filepath

get_clip_filepath(
    clip: VideoNode,
    fallback: SPathLike | None = None,
    func: FuncExcept | None = None,
) -> SPath

Helper function to get the file path from a clip.

This functions checks for the IdxFilePath frame property. It also checks to ensure the file exists, and throws an error if it doesn't.

Parameters:

  • clip

    (VideoNode) –

    The clip to get the file path from.

  • fallback

    (SPathLike | None, default: None ) –

    Fallback file path to use if the prop is not found.

  • strict

    If True, will raise an error if the prop is not found. Default: False.

  • func

    (FuncExcept | None, default: None ) –

    Function returned for error handling. This should only be set by VS package developers.

Raises:

  • FileWasNotFoundError

    The file path was not found.

  • FramePropError

    The property was not found in the clip.

Source code in vstools/utils/props.py
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
def get_clip_filepath(clip: vs.VideoNode, fallback: SPathLike | None = None, func: FuncExcept | None = None) -> SPath:
    """
    Helper function to get the file path from a clip.

    This functions checks for the `IdxFilePath` frame property.
    It also checks to ensure the file exists, and throws an error if it doesn't.

    Args:
        clip: The clip to get the file path from.
        fallback: Fallback file path to use if the `prop` is not found.
        strict: If True, will raise an error if the `prop` is not found. Default: False.
        func: Function returned for error handling. This should only be set by VS package developers.

    Raises:
        FileWasNotFoundError: The file path was not found.
        FramePropError: The property was not found in the clip.
    """
    func = func or get_clip_filepath

    path = get_prop(
        clip, "IdxFilePath", str, SPath, default=SPath(fallback) if fallback is not None else None, func=func
    )

    if path is None or not path.exists():
        raise FileWasNotFoundError("File not found!", func)

    return path

get_prop

get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: type[_PropValueT],
    *,
    default: DT = ...,
    func: FuncExcept | None = None
) -> _PropValueT | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: tuple[type[_PropValueT], type[_PropValueT0]],
    *,
    default: DT = ...,
    func: FuncExcept | None = None
) -> _PropValueT | _PropValueT0 | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: tuple[type[_PropValueT], type[_PropValueT0], type[_PropValueT1]],
    *,
    default: DT = ...,
    func: FuncExcept | None = None
) -> _PropValueT | _PropValueT0 | _PropValueT1 | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: tuple[type[_PropValueT], ...],
    *,
    default: DT = ...,
    func: FuncExcept | None = None
) -> Any | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: type[_PropValueT] | tuple[type[_PropValue], ...],
    cast: Callable[[_PropValueT], CT],
    default: DT = ...,
    func: FuncExcept | None = None,
) -> CT | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: Literal["Callable"],
    *,
    default: DT = ...,
    func: FuncExcept | None = None
) -> Callable[..., Any] | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: type[Any] | tuple[type[Any], ...] | Literal["Callable"],
    cast: Callable[[Any], CT] = ...,
    default: DT = ...,
    func: FuncExcept | None = None,
) -> Any | CT | DT
get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: type[Any] | tuple[type[Any], ...] | Literal["Callable"],
    cast: Callable[[Any], CT] | MissingT = MISSING,
    default: DT | MissingT = MISSING,
    func: FuncExcept | None = None,
) -> Any | CT | DT

Get FrameProp prop from frame frame with expected type t.

Parameters:

  • obj

    (HoldsPropValue) –

    Clip or frame containing props.

  • key

    (str | type[PropEnum]) –

    Prop to get.

  • t

    (type[Any] | tuple[type[Any], ...] | Literal['Callable']) –

    Expected type of the prop.

  • cast

    (Callable[[Any], CT] | MissingT, default: MISSING ) –

    Optional cast to apply to the value.

  • default

    (DT | MissingT, default: MISSING ) –

    Fallback value if missing or invalid.

  • func

    (FuncExcept | None, default: None ) –

    Function returned for custom error handling. This should only be set by VS package developers.

Returns:

  • Any | CT | DT

    The property value (possibly cast).

Source code in vstools/utils/props.py
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
194
195
196
197
198
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
def get_prop(
    obj: HoldsPropValue,
    key: str | type[PropEnum],
    t: type[Any] | tuple[type[Any], ...] | Literal["Callable"],
    cast: Callable[[Any], CT] | MissingT = MISSING,
    default: DT | MissingT = MISSING,
    func: FuncExcept | None = None,
) -> Any | CT | DT:
    """
    Get FrameProp ``prop`` from frame ``frame`` with expected type ``t``.

    Args:
        obj: Clip or frame containing props.
        key: Prop to get.
        t: Expected type of the prop.
        cast: Optional cast to apply to the value.
        default: Fallback value if missing or invalid.
        func: Function returned for custom error handling. This should only be set by VS package developers.

    Returns:
        The property value (possibly cast).

    Raises:
        FramePropError if key is missing or wrong type and no default is provided.
    """
    func = func or get_prop

    if isinstance(obj, vs.RawNode):
        props = _get_prop_cache.get((obj, 0), MISSING)

        if props is MISSING:
            with obj.get_frame(0) as f:
                props = f.props.copy()

            _get_prop_cache[(obj, 0)] = props

    elif isinstance(obj, vs.RawFrame):
        props = obj.props
    else:
        props = obj

    resolved_key = key.prop_key if isinstance(key, type) and issubclass(key, PropEnum) else str(key)

    prop = props.get(resolved_key, MISSING)

    if prop is MISSING:
        if default is not MISSING:
            return default

        raise FramePropError(func, resolved_key, f'Key "{resolved_key}" not present in props!')

    if t == "Callable":
        if callable(prop):
            return prop
        if default is not MISSING:
            return default

        raise FramePropError(func, resolved_key)

    norm_t = _normalize_types(t)

    if isinstance(prop, norm_t):
        if cast is MISSING:
            return prop
        try:
            return cast(prop)
        except Exception:
            if default is not MISSING:
                return default
            raise FramePropError(func, resolved_key)

    if all(issubclass(ty, str) for ty in norm_t) and isinstance(prop, bytes):
        return prop.decode("utf-8")

    if default is not MISSING:
        return default

    raise FramePropError(
        func,
        resolved_key,
        f'Key "{resolved_key}" did not contain expected type: Expected "{t}" got "{type(prop)}"!',
    )

get_props

get_props(
    obj: HoldsPropValue,
    keys: Iterable[str | type[PropEnum]],
    t: type[_PropValueT],
    cast: Callable[[_PropValueT], CT] = ...,
    default: DT = ...,
    func: FuncExcept | None = None,
) -> dict[str, _PropValueT | CT | DT]
get_props(
    obj: HoldsPropValue,
    keys: Iterable[str | type[PropEnum]],
    t: tuple[type[Any], ...],
    cast: Callable[[Any], CT] = ...,
    default: DT = ...,
    func: FuncExcept | None = None,
) -> dict[str, Any | DT | CT]
get_props(
    obj: HoldsPropValue,
    keys: Iterable[str | type[PropEnum]],
    t: type[Any] | tuple[type[Any], ...],
    cast: Callable[[Any], CT] | MissingT = MISSING,
    default: Any | MissingT = MISSING,
    func: FuncExcept | None = None,
) -> dict[str, Any]

Get multiple frame properties from a clip.

Parameters:

  • obj

    (HoldsPropValue) –

    Clip or frame containing props.

  • keys

    (Iterable[str | type[PropEnum]]) –

    List of props to get.

  • t

    (type[Any] | tuple[type[Any], ...]) –

    Expected type of the prop.

  • cast

    (Callable[[Any], CT] | MissingT, default: MISSING ) –

    Optional cast to apply to the value.

  • default

    (Any | MissingT, default: MISSING ) –

    Fallback value if missing or invalid.

  • func

    (FuncExcept | None, default: None ) –

    Function returned for custom error handling. This should only be set by VS package developers.

Returns:

  • dict[str, Any]

    Dictionary mapping property names to their values. Values will be of type specified by cast if provided,

  • dict[str, Any]

    otherwise of the type(s) specified in t or a default value if provided.

Source code in vstools/utils/props.py
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
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
def get_props(
    obj: HoldsPropValue,
    keys: Iterable[str | type[PropEnum]],
    t: type[Any] | tuple[type[Any], ...],
    cast: Callable[[Any], CT] | MissingT = MISSING,
    default: Any | MissingT = MISSING,
    func: FuncExcept | None = None,
) -> dict[str, Any]:
    """
    Get multiple frame properties from a clip.

    Args:
        obj: Clip or frame containing props.
        keys: List of props to get.
        t: Expected type of the prop.
        cast: Optional cast to apply to the value.
        default: Fallback value if missing or invalid.
        func: Function returned for custom error handling. This should only be set by VS package developers.

    Returns:
        Dictionary mapping property names to their values. Values will be of type specified by cast if provided,
        otherwise of the type(s) specified in ``t`` or a default value if provided.
    """
    func = func or get_props

    if not keys:
        return {}

    props = dict[str, Any]()
    exceptions = list[Exception]()

    kwargs: dict[str, Any] = {"t": t, "func": func}

    if cast is not MISSING:
        kwargs["cast"] = cast

    if default is not MISSING:
        kwargs["default"] = default

    for k in keys:
        try:
            prop = get_prop(obj, k, **kwargs)
        except Exception as e:
            exceptions.append(e)
        else:
            props[k if isinstance(k, str) else k.prop_key] = prop

    if exceptions:
        if sys.version_info >= (3, 11):
            raise ExceptionGroup("Multiple exceptions occurred!", exceptions) from None  # noqa: F821

        raise Exception(exceptions)

    return props

merge_clip_props

merge_clip_props(
    *clips: ConstantFormatVideoNode, main_idx: int = 0
) -> ConstantFormatVideoNode
merge_clip_props(*clips: VideoNode, main_idx: int = 0) -> VideoNode
merge_clip_props(*clips: VideoNode, main_idx: int = 0) -> VideoNode

Merge frame properties from all provided clips.

The props of the main clip (defined by main_idx) will be overwritten, and all other props will be added to it.

Parameters:

  • *clips

    (VideoNode, default: () ) –

    Clips which will be merged.

  • main_idx

    (int, default: 0 ) –

    Index of the main clip to which all other clips props will be merged.

Returns:

  • VideoNode

    First clip with all the frameprops of every other given clip merged into it.

Source code in vstools/utils/props.py
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
def merge_clip_props(*clips: vs.VideoNode, main_idx: int = 0) -> vs.VideoNode:
    """
    Merge frame properties from all provided clips.

    The props of the main clip (defined by main_idx) will be overwritten,
    and all other props will be added to it.

    Args:
        *clips: Clips which will be merged.
        main_idx: Index of the main clip to which all other clips props will be merged.

    Returns:
        First clip with all the frameprops of every other given clip merged into it.
    """

    if len(clips) == 1:
        return clips[0]

    def _merge_props(f: list[vs.VideoFrame], n: int) -> vs.VideoFrame:
        fdst = f[main_idx].copy()

        for i, frame in enumerate(f):
            if i == main_idx:
                continue

            fdst.props.update(frame.props)

        return fdst

    return clips[0].std.ModifyFrame(clips, _merge_props)