Skip to content

Releases: JustinTArthur/vapoursynth-analog

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 14 Sep 06:15

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 16 Aug 22:43

SECAM decoding, neural-network composite decoders, two new color filters, dropout reporting, and output geometry that follows the interface standards instead of the capture's own crop. That last one, the field-order tag on 525-line output, and a couple of removed options change what existing scripts produce — see Output geometry and tagging.

New decoding

  • SECAM decoding, emitting YUV440PS (4:4:0) tagged _ChromaLocation top-left, with an AnalogSecamFirstRowComponent frame property for downstream chroma alignment. Both chroma planes are woven by row parity like luma, so separating fields selects the same field on all three — an explicit SECAM crop must span a multiple of 4 lines.
  • resample_secam and fill_secam_by_delay turn that 4:4:0 output into a conventional raster. resample_secam realigns the line-sequential lattice and otherwise behaves like core.resize.<Filter>, forwarding format, matrix, range and the rest; fill_secam_by_delay instead copies each line's missing color difference from the previous line of the same field, as a receiver's delay line does, interpolating nothing. Both want woven frames, so run them before deinterlacing.
  • Neural-network composite decoders — nntransform3d, ldzeug2_color_cnn, ldzeug2_luma_sep and ldzeug2_luma_sep_frame — with bundled models, onnx_provider execution-provider selection and graceful CPU fallback. macOS runs them on native CoreML (the Neural Engine on Apple silicon) and the Windows wheel on any DirectX 12 GPU through DirectML. GPU wheels on the project's package index — one --extra-index-url channel per vendor runtime at https://py.justinarthur.com — add Nvidia CUDA/TensorRT (Linux, Windows) and AMD MIGraphX (Linux). See the installation docs.
  • Newer CVBS capture formats are read alongside ld-decode/vhs-decode .tbc: .cvbs, .cvbsy/.cvbsc for separated luma/chroma, plus the pre-1.5.0 .composite and .y/.c spellings, selected by file extension. RAW (unscaled-ADC) CVBS encodings are rejected.
  • color_family selects YUV444PS (default), RGBS or GRAYS float output.
  • model_precision, color_difference_precision and broadcast_scaling_precision options. The bundled nntransform3d v2 weights default to fp16: TensorRT builds a mixed-precision engine, and the CUDA and Windows wheels bundle an fp16 copy of those weights for an explicit onnx_provider="cuda" or "directml".
  • phase_compensation now defaults to enabled, making burst-locked chroma demodulation the default.

New filters

  • modernize_chromaticity (plugin and Python wrapper) converts analog-era colorimetry and photometry to modern targets (BT.709, sRGB, BT.2100 PQ/HLG, BT.2020 SDR, DCI/D65 P3, XYZ), with BT.1886 Annex 1/Appendix 1 display modelling, optional Bradford chromatic adaptation, and resize-style parameter names whose *_in values override frame properties. Color only: no geometry conversion and no dithering. Subsampled Y'CbCr input goes through an internal resize round trip (resample_filter_uv, bicubic by default) and keeps its subsampling on Y'CbCr output; 4:4:0 SECAM is instead routed through resample_secam / fill_secam_by_delay. Constant-luminance output covers both 2020cl (H.273 matrix 10) and chromacl (matrix 13, luma weights derived from the output primaries), each free to pair with any output transfer — H.273 Equations E-62 to E-65 define the color-difference normalizers as the transfer characteristic applied to expressions in KB/KR, so the curve is an independent axis rather than something the matrix fixes.
  • amplify_chroma (plugin and Python wrapper), a post-decode counterpart to chroma_gain: a saturation control in the analog video domain, scaling E'Cb/E'Cr rather than an HSV/HLS saturation axis. Frames that already carry those color differences — 32-bit float Y'CbCr tagged _Matrix=4, 5 or 6, as decode_4fsc_video emits — are scaled in place, and the same color differences in an integer format go through a float intermediate that names no matrix, so nothing is resampled and even 4:4:0 SECAM survives. Frames on other axes are converted through a _Matrix=6 intermediate of the same subsampling and back, per frame, so previously captured video from a source plugin works too; that conversion holds the analog luma constant the way a decoder's gain does, leaving the frame's own Y' to be re-derived, and 4:4:0 is refused rather than blended. Only analog-era _Primaries (4, 5, 6, 7, or none) are accepted, so it belongs upstream of modernize_chromaticity.
  • annotate_dropouts reports where each frame's dropouts are instead of concealing them, in an AnalogDropoutSpans frame property — a flat array of y, x_start, x_end, origin per region, in the decoded clip's own pixel coordinates. It is independent of dropout_correct, so damaged regions can be handed to another filter rather than replaced from neighbouring lines, and dropout_overcorrect widens what gets reported just as it widens what correction overwrites. On SECAM the regions also cover the FM click concealment the decoder performed itself, distinguished by origin.
  • core.analog.create_dropouts_mask (vsanalog.create_dropouts_mask) rasterises those regions into a mask clip for core.std.MaskedMerge and the other std mask functions, with origins to select which kinds of region to draw. The mask matches the clip's dimensions and precision, so subsampled output needs no special handling. vsanalog.dropout_spans reads the regions back as a list of named tuples.

Output geometry and tagging

  • Output geometry now follows the interface standards instead of the source's declared crop, so a video system always decodes to the same raster. NTSC and PAL-M give 768x486 (SMPTE ST 244's digital active line, ST 170's active picture); PAL and SECAM give 948x576 (EBU Tech 3280-E and ITU-R BT.1700). Previously .tbc sources inherited their sidecar's crop, giving 760x488 and 928x576 with the old default padding. The wider horizontal window includes the blanking transition on each side of the picture.
  • Removed padding_multiple. Output is now exactly the active window on every source. Under libchromadec the option added a black border rather than widening the crop, which std.AddBorders does downstream with control over the amount, sides and color; removing it also means pixel (0, 0) is always the first active sample of the first active line.
  • 525-line output is now tagged bottom-field-first. ST 170's 486-line window starts on a field 2 half-line, because field 2 begins at line 264 and so its first active line (283) sits half a line above field 1's (21). The previous top-field-first tag came from the black padding row that the old default padding_multiple=8 added above the picture. 625-line output begins on a field 1 line and remains top-field-first.
  • Added first_active_sample, last_active_sample, first_active_line and last_active_line to crop explicitly, in the numbering of the signal standards themselves rather than of the stored raster. Samples are numbered as SMPTE ST 244 and EBU Tech 3280-E do, from the start of the digital active line, with negative values reaching back into the line blanking ahead of it; lines are the field-sequential signal line numbers of SMPTE ST 170, ITU-R BT.470 / BT.1700 and EBU Tech 3280, first_active_line naming the window's topmost line. Both bounds are inclusive and independent; unset bounds keep the standard's value. To restore the previous crop, pass first_active_sample=9, last_active_sample=768 for NTSC or 8 / 929 for PAL.
  • The standard active window is now placed through each source's own horizontal alignment instead of a fixed offset, so subcarrier-locked captures — whose rows are cut at the first digital blanking sample rather than at 0H, as ld-chroma-encoder --sc-locked output is — land on the same picture as a 0H-cut .tbc without an explicit crop. This also fixes PAL-M, whose digital active line sits one sample further left than NTSC's.
  • Added AnalogFirstActiveSample / AnalogLastActiveSample / AnalogFirstActiveLine / AnalogLastActiveLine frame properties reporting the resolved window in those same standards coordinates.
  • Removed fpsnum and fpsden. They were meant to convert to a constant frame rate the way bs.VideoSource does, but only ever retagged the rate and rescaled the frame count — no frame was dropped or duplicated, so raising the rate advertised frames past the end of the capture and lowering it put the tail out of reach. A 4𝑓𝑠𝑐 capture is constant-rate by construction, leaving nothing to convert; retag with core.std.AssumeFPS, and retime after deinterlacing, where dropping a frame doesn't mean dropping two fields.

Metadata and diagnostics

  • A decode asking for dropout correction or annotation now warns when the capture's .tbc.db sidecar carries no dropout metadata while its .tbc.json does. The SQLite sidecar wins on existence alone, and releases up to 0.2.3 wrote one themselves during a decode without copying the dropouts across, so a capture decoded by an older version reports itself clean however damaged it is. Nothing writes those sidecars now; delete the .tbc.db to decode from the JSON.
  • JSON metadata is processed natively — no intermediate SQLite sidecar is created for it.
  • Decoder diagnostics now arrive as VapourSynth log messages instead of going straight to the process's stderr, so core.add_log_handler can capture, redirect or silence them. Added set_log_level to set the threshold (debug, info, warning, critical or off). Failures are unaffected — they still raise, and now carry the specific complaint from the layer that found it rather than a generic summary.

Build and packaging

  • The vendored ld-decode-tools submodule is replaced by [libchroma...
Read more

v0.2.3

Choose a tag to compare

@github-actions github-actions released this 30 Jun 01:42

Fixes for vhs-decode and tape-decode-rs:

  • Fix fractional IRE value input for blank/black/white in JSON to SQLite conversion. Older .db metadata sidecars will likely need to be regenerated if they were bugged from prior conversion.
  • Chroma metadata sidecar is now optional in Y/C input, will fallback to using luma TBC's metadata.

Commits: v0.2.2...v0.2.3

v0.3.0a3

v0.3.0a3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 May 03:58

Full Changelog: v0.3.0a2...v0.3.0a3

Full Changelog: v0.3.0a2...v0.3.0a3

Full Changelog: v0.3.0a2...v0.3.0a3

Full Changelog: v0.3.0a2...v0.3.0a3

v0.3.0a2

v0.3.0a2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 May 02:27

Full Changelog: v0.2.2...v0.3.0a2

v0.3.0a1

v0.3.0a1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 May 06:57

Full Changelog: v0.2.2...v0.3.0a1

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 17 Apr 03:30

Full Changelog: v0.2.1...v0.2.2

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 16 Apr 02:45

Revised Windows wheel should now contain the full dependency set. macOS and Linux wheels should be be unchanged from 0.2.0.

Full Changelog: v0.2.0...v0.2.1

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 13 Apr 06:36
  • Added a vsanalog Python wrapper package with type-hinted signatures and an auto-loading fallback for older VapourSynth versions that predate pip-installable plugins.
  • Retagged wheels as independent from the CPython ABI (none) so a single wheel can serve any compatible Python interpreter on a given platform.
  • More comprehensive documentation.

Commits: v0.1.1...v0.2.0

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 13 Mar 11:17

New build pipeline with reasonably-packaged plugin libs plus Python sdists and wheels that can support VapourSynth's upcoming pip-installable plugin flow (the old drop-in plugin libs will still work, don't worry).

No fixes or feature changes to the plugin itself.

Full Changelog: v0.1.0...v0.1.1