Skip to content

Using VapourSynth in mpv.net

stax76 edited this page May 25, 2022 · 2 revisions

Download StaxRip

Download StaxRip v2.13.0:

https://github.com/staxrip/staxrip/releases/download/v2.13.0/StaxRip-v2.13.0-x64.7z

StaxRip contains the following requirements:

  1. VapourSynth Portable R54.
  2. Python Portable 3.9.7.
  3. All required VapourSynth filters.

Extract StaxRip

Extract StaxRip to the following location:

C:\StaxRip\StaxRip.exe

Add the VapourSynth folder to the PATH environment variable

Add the VapourSynth folder to the top of the PATH environment variable.

Find the VapourSynth folder here:

C:\StaxRip\Apps\FrameServer\VapourSynth

This folder contains both VapourSynth and Python.

Tip: You can start the editor via command line:

rundll32.exe sysdm.cpl,EditEnvironmentVariables

Add a mpv profile

Add the following profile to your mpv.conf file:

[VapourSynth-Motion-Interpolation]
vf=vapoursynth="C:\StaxRip\mpv.vpy":buffered-frames=4:concurrent-frames=32
profile-restore = copy

If you want to open vpy files in mpv.net also add:

[extension.vpy]
demuxer-lavf-format = vapoursynth

Find mpv.conf here:

C:\Users\jd\AppData\Roaming\mpv.net\mpv.conf

Save the VapourSynth Script

Location:

C:\StaxRip\mpv.vpy

Content:

import os, sys
import vapoursynth

core = vapoursynth.core

sys.path.append(r"C:\StaxRip\Apps\Plugins\VS\Scripts")
import importlib.machinery
mvsfunc = importlib.machinery.SourceFileLoader('mvsfunc', r"C:\StaxRip\Apps\Plugins\VS\Scripts\mvsfunc.py").load_module()
adjust = importlib.machinery.SourceFileLoader('adjust', r"C:\StaxRip\Apps\Plugins\VS\Scripts\adjust.py").load_module()
havsfunc = importlib.machinery.SourceFileLoader('havsfunc', r"C:\StaxRip\Apps\Plugins\VS\Scripts\havsfunc.py").load_module()
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\AddGrain\AddGrain.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\AWarpSharp2\libawarpsharp2.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\CAS\CAS.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\CTMF\CTMF.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\Deblock\Deblock.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\EEDI2\EEDI2.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\EEDI3m\EEDI3m.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\Dual\flash3kyuu_deband\flash3kyuu_deband.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\FluxSmooth\libfluxsmooth.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\fmtconv\fmtconv.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\HQDN3D\libhqdn3d.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\Dual\KNLMeansCL\KNLMeansCL.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\mvtools\libmvtools.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\nnedi3\libnnedi3.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\nnedi3\NNEDI3CL.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\Sangnom\libsangnom.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\scenechange\scenechange.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\SVPFlow\svpflow1_vs64.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\SVPFlow\svpflow2_vs64.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\TTempSmooth\TTempSmooth.dll", altsearchpath=True)
core.std.LoadPlugin(r"C:\StaxRip\Apps\Plugins\VS\nnedi3\vsznedi3.dll", altsearchpath=True)

# ref: http://avisynth.org.ru/mvtools/mvtools2.html#functions
# default is 400, less means interpolation will only happen when it will work well
ignore_threshold=140
# if n% of blocks change more than threshold then don't interpolate at all (default is 51%)
scene_change_percentage=15

dst_fps = display_fps
# Interpolating to fps higher than 60 is too CPU-expensive, smoothmotion can handle the rest.
# while (dst_fps > 60):
#    dst_fps /= 2

if "video_in" in globals():
    # realtime
    clip = video_in
    # Needed because clip FPS is missing
    src_fps_num = int(container_fps * 1e8)
    src_fps_den = int(1e8)
    clip = core.std.AssumeFPS(clip, fpsnum = src_fps_num, fpsden = src_fps_den)
else:
    # run with vspipe
    clip = core.ffms2.Source(source=in_filename)
    dst_fps=float(dst_fps)

# resolution in megapixels. 1080p ≈ 2MP, 720p ≈ 1MP
mpix = clip.width * clip.height / 1000000

# Skip interpolation for >1080p or 60 Hz content due to performance
if not (mpix > 2.5 or clip.fps_num/clip.fps_den > 59):
    analParams = {
        'overlap': 0,
        'search': 3,
        'truemotion': True,
        #'chrome': True,
        #'blksize':16,
        #'searchparam':1
    }
    blockParams = {
        'thscd1': ignore_threshold,
        'thscd2': int(scene_change_percentage*255/100),
        'mode': 3,
    }

    if mpix > 1.5:
        # can't handle these on Full HD with Intel i5-2500k
        # see the description of these parameters in http://avisynth.org.ru/mvtools/mvtools2.html#functions
        analParams['search'] = 0
        blockParams['mode'] = 0
        quality = 'low'
    else:
        quality = 'high'


    dst_fps_num = int(dst_fps * 1e4)
    dst_fps_den = int(1e4)
    print("Reflowing from {} fps to {} fps (quality={})".format(clip.fps_num/clip.fps_den,dst_fps_num/dst_fps_den,quality))
    
    sup  = core.mv.Super(clip, pel=2)
    bvec = core.mv.Analyse(sup, isb=True, **analParams)
    fvec = core.mv.Analyse(sup, isb=False, **analParams)
    clip = core.mv.BlockFPS(clip, sup, bvec, fvec, 
            num=dst_fps_num, den=dst_fps_den, 
            **blockParams)

clip.set_output()

Activate the profile

Activate the profile in the profile section of the mpv.net context menu.

That's it.