#
Comparison
Quality comparisons are frequently used within the enthusiast community to compare the video quality offered by different sources/releases. It serves as a great way to distinguish the differences between good and bad sources, and can help you identify video issues and determine which one to keep. This guide goes through the process of setting up and effectively utilizing VSPreview, a previewer utility for VapourSynth, to produce useful quality comparisons that will allow you to ascertain which video offers the best visual experience.
#
Installing
Python 3.14- Scroll down and select the installer for your platform (NOT install manager). During installation check Add python.exe to PATHVapourSynth R73- Download and installVapourSynth-x64-R73.exe. During installation, selectInstall for me only.ffms2fpngLibP2PLSMASHSourcevs-placeboresize2akarinvivtc- In your terminal, run the following:
vsrepo.py install ffms2 fpng libp2p lsmas placebo resize2 akarin vivtc
vs-jetpackvs-previewawsmfunc- In your terminal, run the following:
python -m pip install vsjetpack vspreview awsmfunc
#
Scripting
In order to create a comparison, you will need to create a VapourSynth script.
Create a file called comp.py. Launch it in your favorite text editor and add sections as desired:
The following comp.py script loads your sources into the previewer.
Make sure to comment (add ## to the beginning of the line) and uncomment lines as needed.
## Dependencies: Allows vspreview to run [required; do not remove]
from vstools import vs, core, depth, set_output, PropEnum, Matrix, Transfer, Primaries, ColorRange, FieldBased
from vssource import FFMS2, LSMAS
from vskernels import Point, EwaLanczosSharp, Hermite
from vsdeinterlace import vfm, vdecimate
from awsmfunc.types.placebo import PlaceboColorSpace as ColorSpace
from awsmfunc.types.placebo import PlaceboTonemapFunction as Tonemap
from awsmfunc.types.placebo import PlaceboGamutMapping as Gamut
from awsmfunc.types.placebo import PlaceboTonemapOpts
## File paths: Hold Shift and Right-click your file, select copy as path, and paste it here. For NF WEB-DLs change LSMAS to FFMS2
clip1 = LSMAS.source(r"C:\Paste\File\Path\Here.mkv")
clip2 = LSMAS.source(r"C:\Paste\File\Path\Here.mkv")
clip3 = LSMAS.source(r"C:\Paste\File\Path\Here.mkv")
## Source: Name of the source
source1 = "FirstSourceName"
source2 = "SecondSourceName"
source3 = "ThirdSourceName"
## <Additional comp settings>
## Place any additional settings you want to use in your comp here
## <End of additional comp settings>
## Output: Comment/uncomment as needed depending on how many clips you're comparing
set_output(clip1, name=source1)
set_output(clip2, name=source2)
set_output(clip3, name=source3)
Please note the order of the following filters. The filters under each (Required) section must be placed in that order in your script.
#
Inverse Telecine
Quick inverse telecine filter for converting telecined clips (usually 30 fps interlaced video) back to the original framerate (24 fps progressive).
clip1 = vdecimate(vfm(clip1))
#
FieldBased
Properly tags progressive content in interlaced container as progressive for correct chroma upscaling.
clip1 = FieldBased.PROGRESSIVE.apply(clip1)
#
Subsampling (Required)
Converts clips to 16-bit depth with 4:4:4 chroma subsampling.
clip1 = EwaLanczosSharp().scale(depth(clip1, 16), format=vs.YUV444P16, antiring=0.6)
This is currently broken on Nvidia with more than 2 sources unless you manually upgrade vs-placebo
#
Frame Rate
Sets the source frame rate (fps) based on fractional input (fpsnum/fpsden). For example, fpsnum=24000 and fpsden=1001 forces the clip frame rate to 23.976 fps. This should be used on sources that have different frame rates that don't automatically stay in sync. If they do stay in sync, note that the source has dropped or duplicate frames.
clip1 = core.std.AssumeFPS(clip1, fpsnum=24000, fpsden=1001)
#
Trimming
Removes the first n frames from the source. For example, [24:] will skip the first 24 frames and start the source at frame 25. This should be used on sources that are out of sync.
To get the frame difference, find a unique frame (e.g. scene changes) in the correct and incorrect source. Note the frame numbers each one begin at, then set the difference of the two for the incorrect source.
clip1 = clip1[24:]
For more advanced trimming such as chaining, splicing, and looping, see Vapoursynth's docs.
#
Cropping
Crops the source video by n pixels from the selected side. For example, left=20 will remove 20 horizontal pixels starting from the left side. This should be used on sources that use letterboxing or other form of borders. Make sure to check for variable aspect ratios throughout the file and only crop the smallest border.
clip1 = core.std.Crop(clip1, left=240, right=240, top=0, bottom=0)
#
Color Spaces
Sets the correct color information, should be used on sources with incorrect/missing metadata.
clip1 = PropEnum.ensure_presences(clip1, (Matrix.BT709, Transfer.BT709, Primaries.BT709, ColorRange.LIMITED))
HD BD/WEB
clip1 = PropEnum.ensure_presences(clip1, (Matrix.BT709, Transfer.BT709, Primaries.BT709, ColorRange.LIMITED))
NTSC DVD
clip1 = PropEnum.ensure_presences(clip1, (Matrix.ST170_M, Transfer.BT601, Primaries.ST170_M, ColorRange.LIMITED))
PAL DVD
clip1 = PropEnum.ensure_presences(clip1, (Matrix.BT470_BG, Transfer.BT601, Primaries.BT470_BG, ColorRange.LIMITED))
HDR
clip1 = PropEnum.ensure_presences(clip1, (Matrix.BT2020_NCL, Transfer.ST2084, Primaries.BT2020, ColorRange.LIMITED))
HD BD/WEB with incorrectly tagged matrix (Reds/green will look off)
clip1 = PropEnum.ensure_presences(clip1, (Matrix.ST170_M, Transfer.BT709, Primaries.BT709, ColorRange.LIMITED))
HD BD/WEB with incorrectly converted matrix (Inverse of the above, use this if that method makes colors look worse)
clip1 = core.resize.Point(clip1, _Matrix=vs.MATRIX_ST170_M)
clip1 = PropEnum.ensure_presences(clip1, (Matrix.ST170_M, ColorRange.LIMITED))
#
Double-Range Compression
Reverses Double-Range Compression to fix washed out colors.
clip1 = depth(clip1, range_in=ColorRange.LIMITED, range_out=ColorRange.FULL)
clip1 = ColorRange.LIMITED.apply(clip1)
Sets the range as full for incorrectly tagged sources to fix blown out highlights and crushed blacks.
clip1 = ColorRange.FULL.apply(clip1)
#
Clipping
Sometimes an HDR source will be mostly or even entirely within the SDR range, often seen with anime on Netflix. In these cases you can clip the source to get an exact match to SDR, unlike with traditional tonemapping.
Clipping should always be attempted first before resorting to tonemapping, even if some highlights get blown out. You may also need to apply a 0.92
Clip HDR source to SDR
clip1 = Point().resample(clip1, matrix=Matrix.BT709, transfer=Transfer.BT709, primaries=Primaries.BT709)
Clip DV (Profile 5) source to SDR
clip1args = PlaceboTonemapOpts(source_colorspace=ColorSpace.DOVI, target_colorspace=ColorSpace.HDR10, use_dovi=True)
clip1 = core.placebo.Tonemap(clip1, **clip1args.vsplacebo_dict())
clip1 = PropEnum.ensure_presences(clip1, (Matrix.BT2020_NCL, Transfer.ST2084, Primaries.BT2020))
clip1 = Point().resample(clip1, matrix=Matrix.BT709, transfer=Transfer.BT709, primaries=Primaries.BT709)
#
Tonemapping
Converts the dynamic range of the source (i.e. HDR/DV -> SDR).
- For converting HDR (washed out colors) -> SDR, set
ColorSpace.HDR10 - For converting DV (green/purple hue) -> SDR, set
ColorSpace.DOVI
clip1args = PlaceboTonemapOpts(source_colorspace=ColorSpace.HDR10, target_colorspace=ColorSpace.SDR, tone_map_function=Tonemap.Spline, gamut_mapping=Gamut.Perceptual, peak_detect=True, use_dovi=True, contrast_recovery=0.3 ,dst_max=100)
clip1 = core.placebo.Tonemap(clip1, **clip1args.vsplacebo_dict())
clip1 = core.std.SetFrameProps(clip1, _Matrix=vs.MATRIX_BT709, _Transfer=vs.TRANSFER_BT709, _Primaries=vs.PRIMARIES_BT709)
#
Depth (Required)
Converts the clip to 32 bit depth for accurate output
clip1 = depth(clip1, 32)
#
Gamma
Adjusts the gamma level of the video. Should be used to fix the QuickTime gamma bug (0.88) or similar where one source is brighter than others.
clip1 = core.std.Levels(clip1, gamma=0.88, planes=0)
#
Pixel format (Required)
Converts to RGBS which is required for debanding and scaling
clip1 = Point().resample(clip1, format=vs.RGBS)
#
Debanding
Otherwise competitive sources with obvious banding should be debanded to see how they'd fare with mpv's built-in deband filter. The debanded clip should never replace the original. Instead, it should be added as an additional node.
clip1 = core.placebo.Deband(clip1, planes=1|2|4, threshold=48 / 16.384, grain=32 / 8.192)
#
Scaling
Upscales lower resolution sources to match the highest resolution source. (Recommended)
clip1 = EwaLanczosSharp().scale(clip1, 1920, 1080, sigmoid=True, antiring=0.6)
Downscales higher resolution sources to match a lower resolution source. Only use this for demonstrative purposes
clip1 = Hermite().scale(clip1, 1920, 1080, linear=True)
#
Running
To run your comparison script, launch a terminal window in your working directory and run the following:
vspreview comp.py
Alternatively, you can create a comp.bat file, replacing C:\path\to\comp.py with the exact file path to your script:
vspreview "C:\path\to\comp.py"
#
First-time Setup
Drag the Plugins menu from the right-side of the VSPreview window and open the SlowPics Comps tab. Alternatively, you can access the Plugins menu using
Ctrl+PUnder Settings, set the following:
- Set Collection Name Template to
{tmdb_title} ({tmdb_year}) - S01E01 - {video_nodes} - Set Compression Type to
Slow - Enter your slow.pics username and password (optional)
- Tick the Public Flag
- Set Collection Name Template to
Click the Settings button on the bottom tab. Under Main, change Save Plugins Bar Position to
GlobalClick the Playback button on the bottom tab. Set the bottom-left value to an odd number (e.g
109)
Once complete, close and relaunch VSPreview to apply these changes.
#
Comparing
#
Basic Keybinds
For the purpose of making comparisons, you will only need the following binds:
If you wish to manually set your keybinds, you can find them under Settings -> Shortcuts.
#
Capturing
Open the Plugins window and select the SlowPics Comps tab
Set the TMDB type and ID from The Movie Database (e.g.
94605for Arcane)Before creating a comparison, skim through all your sources and ensure that they are displaying correctly. Most issues can be fixed using
filters in your comparison scriptSelect the frames to be uploaded. There are multiple methods to doing so:
- Manual: Scrub through the video and mark each frame using
Ctrl+Space - Automatic: Specify an amount of random frames in the Plugin menu. You may choose to use this feature alongside capturing frames manually
- Frames should ideally show a variety of scenarios (e.g. light/dark, static/high-motion, flat/grainy, etc.). Particularly, you may want to capture scenes with on-screen text and bright reds (if possible).
- Manual: Scrub through the video and mark each frame using
Hit the Start Upload button. VSPreview will automatically screenshot all selected frames and upload a comparison to slow.pics
We don't recommend using the dark/light frames feature, as it currently has many issues.
#
Choosing Sources (Anime)
The following will help make your comparison as effective as possible
- Include every available BD, you generally will need to check U2 (Private tracker)
- If 2 sources have identical video, only include 1 and label it as such (eg JPN/USA BD)
- We generally recommend picking episode 2 to ensure both the OP and ED are shown
- Include at least 1 web source when available
- Include all relevant encodes, see below
These sources should always be included
- Any BD/WEB fansub release
- Akatomba-Raws
- Beatrice-Raws
- H-Enc
- HQR
- Kagura
- Kawaiika-Raws
- km
- Kuroi-raws
- mottoj
- NanoAlchemist
- neko-raws
- Raws-Maji/KnK
- Salender-Raws
- SCY
- Seicher
- sergey_krs
- SOFCJ-Raws
- UQW
- Urotsuki
- VCB-Studio
- YURASUKA
- Yurasyk/Chyrka
- Yousei-raws
- Zagzad
=^_^=/frost
These sources should be included when the previous tier is not available, or when the only existing muxes use them
- Almighty
- ANK-Raws
- CBM
- DmonHiro
- IrizaRaws
- iAHD
- jsum
- Koten_Gars
- kuchikirukia
- Lowpower-Raws
- moscowgolem
- Moozzi2
- philosophy-raws
- ReinForce
- SEV
- Snow-Raws
- UCCUSS
These sources should never be included as they provide no value
- Any mini-encode
- Any re-encode
- 7³ACG
- AI-RAWS
- Centaurea-Raws
- DarkDream
- DBD-Raws
- Deadmau- RAWS
- FY-Raws
- GHOST
- Salieri
- Shiniori-Raws
Generally you will only need 1 web source in the comparison, which should be picked in the following order
- Crunchyroll (CR) - Should be the latest 8Mbps stream, if not publicly available check this list
- Disney+ (DSNP)
- Netflix (NF)
- Animation Digital Network (ADN)
- Amazon (AMZN)
- HIDIVE (HIDI)