vsanalog 0.2.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
vsanalog/__init__.py ADDED
@@ -0,0 +1,120 @@
1
+ """VapourSynth plugin for working with digitized analog video signals."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ import platform
7
+ import sys
8
+ from collections.abc import Callable, Sequence
9
+ from importlib.metadata import version as _get_version
10
+ from pathlib import Path
11
+ from typing import Any, TypeVar
12
+
13
+ if sys.version_info >= (3, 10):
14
+ from typing import ParamSpec
15
+ else:
16
+ from typing_extensions import ParamSpec
17
+
18
+ import vapoursynth as vs
19
+
20
+ __all__ = ["decode_4fsc_video", "requires_plugin"]
21
+
22
+ __version__ = _get_version("vsanalog")
23
+
24
+ P = ParamSpec("P")
25
+ R = TypeVar("R")
26
+
27
+
28
+ def _get_plugin_path() -> Path:
29
+ """Derive the filesystem path of the bundled vsanalog shared library."""
30
+ suffix = {"Windows": ".dll", "Darwin": ".dylib"}.get(platform.system(), ".so")
31
+ _packages_root = Path(__file__).resolve().parent.parent
32
+ return _packages_root / "vapoursynth" / "plugins" / f"vsanalog{suffix}"
33
+
34
+
35
+ def _ensure_plugin_loaded() -> None:
36
+ """Load the vsanalog VapourSynth plugin if it isn't already available."""
37
+ if not hasattr(vs.core, "analog"):
38
+ plugin_path = _get_plugin_path()
39
+ if not plugin_path.is_file():
40
+ raise FileNotFoundError(
41
+ f"vsanalog plugin not found at {plugin_path}. "
42
+ "Ensure the vsanalog package is properly installed."
43
+ )
44
+ vs.core.std.LoadPlugin(plugin_path)
45
+
46
+
47
+ def requires_plugin(func: Callable[P, R]) -> Callable[P, R]:
48
+ """Decorator ensuring the vsanalog VapourSynth plugin is loaded."""
49
+
50
+ @functools.wraps(func)
51
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
52
+ _ensure_plugin_loaded()
53
+ return func(*args, **kwargs)
54
+
55
+ return wrapper
56
+
57
+
58
+ @requires_plugin
59
+ def decode_4fsc_video(
60
+ composite_or_luma_source: str | Path,
61
+ chroma_or_pb_source: str | Path | None = None,
62
+ pr_source: str | Path | None = None,
63
+ *,
64
+ decoder: str | None = None,
65
+ reverse_fields: bool = False,
66
+ chroma_gain: float = 1.0,
67
+ chroma_phase: float = 0.0,
68
+ chroma_nr: float = 0.0,
69
+ luma_nr: float = 0.0,
70
+ phase_compensation: bool = False,
71
+ padding_multiple: int = 8,
72
+ dropout_correct: bool = False,
73
+ dropout_overcorrect: bool = False,
74
+ dropout_intra: bool = False,
75
+ dropout_composite_or_luma_extra_sources: Sequence[str | Path] | None = None,
76
+ dropout_chroma_extra_sources: Sequence[str | Path] | None = None,
77
+ fpsnum: int | None = None,
78
+ fpsden: int = 1,
79
+ ) -> vs.VideoNode:
80
+ """Decode 4𝑓𝑠𝑐 (four times subcarrier frequency) digitized analog video.
81
+
82
+ Reads time-base corrected (TBC) captures produced by ld-decode or vhs-decode
83
+ and returns a VapourSynth clip in YUV444PS or GRAYS format (32-bit float).
84
+ """
85
+ kwargs: dict[str, Any] = {}
86
+
87
+ # Optional parameters — only pass when explicitly provided so the
88
+ # C++ side can distinguish "not given" from "given as default".
89
+ if chroma_or_pb_source is not None:
90
+ kwargs["chroma_or_pb_source"] = chroma_or_pb_source
91
+ if pr_source is not None:
92
+ kwargs["pr_source"] = pr_source
93
+ if decoder is not None:
94
+ kwargs["decoder"] = decoder
95
+ if dropout_composite_or_luma_extra_sources is not None:
96
+ kwargs["dropout_composite_or_luma_extra_sources"] = (
97
+ dropout_composite_or_luma_extra_sources
98
+ )
99
+ if dropout_chroma_extra_sources is not None:
100
+ kwargs["dropout_chroma_extra_sources"] = dropout_chroma_extra_sources
101
+ if fpsnum is not None:
102
+ kwargs["fpsnum"] = fpsnum
103
+ kwargs["fpsden"] = fpsden
104
+
105
+ # VapourSynth's Python bindings handle bool→int and Path→str
106
+ # coercion automatically, so remaining args pass through as-is.
107
+ return vs.core.analog.decode_4fsc_video(
108
+ composite_or_luma_source,
109
+ reverse_fields=reverse_fields,
110
+ chroma_gain=chroma_gain,
111
+ chroma_phase=chroma_phase,
112
+ chroma_nr=chroma_nr,
113
+ luma_nr=luma_nr,
114
+ phase_compensation=phase_compensation,
115
+ padding_multiple=padding_multiple,
116
+ dropout_correct=dropout_correct,
117
+ dropout_overcorrect=dropout_overcorrect,
118
+ dropout_intra=dropout_intra,
119
+ **kwargs,
120
+ )
@@ -0,0 +1,5 @@
1
+ from pathlib import Path
2
+
3
+
4
+ def get_hook_dirs():
5
+ return (str(Path(__file__).parent),)
@@ -0,0 +1,9 @@
1
+ import platform
2
+ from pathlib import Path
3
+
4
+ _suffix = {"Windows": ".dll", "Darwin": ".dylib"}.get(platform.system(), ".so")
5
+ _packages_root = Path(__file__).resolve().parent.parent.parent
6
+ _plugin = _packages_root / "vapoursynth" / "plugins" / f"vsanalog{_suffix}"
7
+
8
+ if _plugin.is_file():
9
+ binaries = [(str(_plugin), "vapoursynth/plugins")]
vsanalog/py.typed ADDED
File without changes
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: vsanalog
3
+ Version: 0.2.0
4
+ Summary: VapourSynth plugin for working with digitized analog video signals
5
+ License-Expression: GPL-3.0-or-later
6
+ Requires-Python: >=3.9
7
+ Requires-Dist: vapoursynth>=55
8
+ Requires-Dist: typing_extensions>=4.0; python_version < "3.10"
9
+
@@ -0,0 +1,10 @@
1
+ vsanalog-0.2.0.dist-info/METADATA,sha256=TD1xy2sYeXyn3tXFmwozNWAK8aZw5LU5zgDNpKnTi5o,283
2
+ vsanalog-0.2.0.dist-info/WHEEL,sha256=eGbHOVnVkNk5N_A188Q13-gtiwyWWQjeSFRh9oxazXU,84
3
+ vsanalog-0.2.0.dist-info/entry_points.txt,sha256=A3onFMxdGVjPaDwQchXDGS8dwPouScm1-LfTKc3f8yk,66
4
+ vapoursynth/plugins/vsanalog.dll,sha256=NH9ZwZhUU3VVdy2U2U2ub0hKtitrrZlyYgt5ZqtOlmg,357376
5
+ vapoursynth/plugins/vsanalog.lib,sha256=StzHA4cVUKAAwiZTcAUnQUCA5IisN6iGetJ5tDDfOPg,1784
6
+ vsanalog/__init__.py,sha256=W9khR0Rvcx0iCsPYHBLcxd_ksSXyh7eOpRQ0lI2tlHc,4256
7
+ vsanalog/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ vsanalog/__pyinstaller/__init__.py,sha256=xqxr9SRah90a5sdNCkoyLGh9veEnEp98qtDMT4RgaN4,94
9
+ vsanalog/__pyinstaller/hook-vsanalog.py,sha256=qZqW9B-3OkDsRAK3rvCFKjEhvo-uMcvyuiT_P5sNWuo,348
10
+ vsanalog-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: meson
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64
5
+
@@ -0,0 +1,3 @@
1
+ [pyinstaller40]
2
+ hook-dirs = vsanalog.__pyinstaller:get_hook_dirs
3
+