Closed Nuihc88 closed 1 year ago
Hey, I've been lurking on this repo for a while, but haven't got the occasion to spend some time messing with trying to use these settings on VapourSynth (if that's even possible) to make use in my project, I've also made a post on doom9 explaining my objective on a larger scale if you're curious
I'm interested in learning C/C++ to make VapourSynth plugins but I really don't know where to start, the only thing I found is this
Importing the settings is certainly possible... If it helps, here's my half-finished VapourSynth Test Script with UltraLight Animated Preset's settings enabled:
import vapoursynth as vs
from vapoursynth import core
import math
core.num_threads=4 #8 #16
core.add_cache=True
core.max_cache_size=4000
last = VpsFilterSource #.resize.Point(format=vs.YUV420P8)
super_params="{pel:1,gpu:1,full:false}"
analyse_params="{block:{w:32,h:32,overlap:0},main:{\
search:{distance:-0 ,type:4,satd:false,sort:false,\
coarse:{distance:-21,type:2,satd:false,trymany:false,\
width:241,bad:{range:0}}},levels:3,penalty:{lambda:3.3,\
plevel:1.25,pnew:44,pglobal:104,pzero:240,pnbour:74,prev:-1}}}"
smoothfps_params="},mask:{cover:99},algo:2,cubic:1,linear:false,scene:{\
mode:0,blend:false,limits:{scene:2220,zero:4,blocks:42},luma:1}}"
Num="2"; Den="1"; Abs="false"
super = core.svp1.Super(last,super_params)
vectors = core.svp1.Analyse(super["clip"],super["data"],last,analyse_params)
smooth = core.svp2.SmoothFps(last,super["clip"],super["data"],vectors["clip"],vectors["data"],"{rate:{num:"+str(Num)+",den:"+str(Den)+",Abs:"+str(Abs)+smoothfps_params,src=last,fps=VpsFilterSource.fps)
#"{rate:{num:"+String(Num)+",den:"+String(Den)+",abs:"+String(abs)+smoothfps_params,src=last,fps=VpsFilterSource.fps)
smooth = core.std.AssumeFPS(smooth,fpsnum=smooth.fps_num,fpsden=smooth.fps_den)
smooth.set_output()
For some reason it's performing far worse than the AviSynth+ version, but at least it runs and has fairly readable formatting.
I think a function to convert multi-line string that removes spaces and new-lines into a single line string would be great to improve readability, so we can use JSON-like indentation/spacing and pass that thru a def
This isn't working code at all, just an idea of how it could work:
AnalyseParams = helpers.Wrap('''
{
block:{
w:32,
h:32,
overlap:0
},
main:{
search:{
distance:-0,
type:4,
satd:false,
sort:false,
coarse:{
distance:-21,
type:2,
satd:false,
trymany:false,
width:241,
bad:{
range:0
}
}
},
levels:3,
penalty:{
lambda:3.3,
plevel:1.25,
pnew:44,
pglobal:104,
pzero:240,
pnbour:74,
prev:-1
}
}
}
''')
SmoothFPSParams = helpers.Wrap('''
{
rate:{
num:"2",
den:"1",
Abs:"false"
},
mask:{
cover:99
},
algo:2,
cubic:1,
linear:false,
scene:{
mode:0,
blend:false,
limits:{
scene:2220,
zero:4,
blocks:42
},
luma:1
}
}
''')
or in a less verbose-y way:
AnalyseParams = helpers.Wrap('''
{
block:{w:32,h:32,overlap:0},
main:{
search:{
distance:-0,type:4,satd:false,sort:false,
coarse:{
distance:-21,type:2,satd:false,
trymany:false,width:241,
bad:{range:0}
}
},
levels:3,
penalty:{
lambda:3.3,plevel:1.25,pnew:44,
pglobal:104,pzero:240,pnbour:74,prev:-1
}
}
}
''')
SmoothFPSParams = helpers.Wrap('''
{
rate:{
num:"2",den:"1",Abs:"false"
},
mask:{cover:99},
algo:2,cubic:1,linear:false,
scene:{
mode:0,blend:false,
limits:{
scene:2220,zero:4,blocks:42
},
luma:1
}
}
''')
Personally i prefer keeping the configurations in just a few densely populated lines grouped into repeating patterns; that way it's quick and easy to review various versions and revisions in WinMerge's 3-way compare mode without needing to scroll around.
One of the reasons i'm rethinking readability in the first place has to do with my plans to make a simple GUI configuration tool later on. For example, i have following considerations for editing parameters:
sad
, lsad
& refine
, which are currently not used by my scripts, but could be added through the GUI.Currently i'm thinking of using something like this as a template:
super_params="{pel: 1, gpu: 1, full:false , scale:{ up: 2 , down: 4 } }"
analyse_params="{ block:{ w:32 , h:32 , overlap: 0 }, main:{ \
levels: 3 , search:{ distance: -0 , type: 4 , sort:false , satd:false , \
coarse:{ width: 241 , distance:-21 , type: 2 , trymany:false , satd:false , \
bad:{ range: 0 , sad: 1000 }}}, penalty:{ lsad: 8000 , lambda: 3.3 , \
prev: -1 , pnew: 44 , pzero: 240 , pnbour: 74 , pglobal: 104 , plevel: 1.25 }} \
,refine:[\
{thsad:65000, penalty:{pnew:44}, search:{ distance:-6 , type:2 , satd:false } },\
{thsad:65000, penalty:{pnew:44}, search:{ distance:-3 , type:4 , satd:false } }]\
}"
smoothfps_params="}, algo: 2 , linear:false , cubic: 1 , block:false , gpuid: 0,\
mask:{ cover: 88 , area: 0 , area_sharp:1.00 } , scene:{ mode: 0 , blend:false ,\
limits:{ m1:1800 , m2:3600 , scene:2220 , zero: 4 , blocks: 42 }, luma: 1.00 }}"
...that way i can find & replace almost anything using spaces (e.g. ' sort:false ' -> ' sort: true ') as separators and the remaining ones i could differentiate using Regular Expression wildcards and look-behind assertions (e.g. satd:.....(?<=.search:{ )
)
Moving Num
, Den
& Abs
outside the smoothfps_params
-string is another future proofing step required for more advanced motion interpolation scripts like the one in the first post, but i won't add those changes to my current scripts until i have something more usable.
What is your opinion on using mvtools with VapourSynth?
What is your opinion on using mvtools with VapourSynth?
I read somewhere that mvtools is slow and CPU only, which means it might not be suitable for realtime use or at least may require 16+ core CPU. However i don't really have enough experience with it to have an opinion one way or another.
I have more or less finished refining these scripts now, but am thinking of taking the project into new directions...
Here are some of my current ideas for possible future improvements:
AutoHotkey & Regular Expression based GUI with a systray-icon, menu and configuration window.
Making VapourSynth versions of my scripts. However due to lack of built in cache features and experience on my part, the progress has been practically non-existant; with my current test scripts only getting 8-14 fps, so not even worth sharing.
Creating a C-Plugin for AviSynth+ to get more granular motion interpolation using more or less the same logic as the script below; however i have no experience with writing AviSynth filters either...
Use ChangeFPS to create duplicate frames to later be replaced by DupeInterpolator ScriptClip.
global Stats=false Den=1 # 2 = Set FPS - Creates duplicate frames to reach all the way up to TargetFPS. global DupeThreshold=.618034 # 3 = Static - Uses Num / Den values from above to set framerate manually. if (FramerateTargetingMode==1) {Num=1 while(FrameRate()(Num+1)<TargetFPS){Num=Num+1} ChangeFPS(FrameRate()Num)} else if (FramerateTargetingMode==2) {ChangeFPS(TargetFPS)} else if (FramerateTargetingMode==3) {ChangeFPS(Num, Den)}
DupeInterpolator = """Difference=YDifferenceFromPrevious() FrameNumber=current_frame global DupeFactor=0 global DupeCounter=0 if(Framecount()>current_frame && DupeThreshold>=Difference) {current_frame=current_frame+1 DupeFactor=DupeFactor+1 DupeCounter=DupeCounter+1 while(Framecount()>current_frame && DupeThreshold>=YDifferenceFromPrevious() ) {current_frame=current_frame+1}
else{DupeFactor=0 Stats ? Subtitle("Dupe-Pass: Original") : last} Stats ? Subtitle("Threshold = "+string(DupeThreshold) +" Difference = "+string(Difference)+" DupeFactor = "+String(DupeFactor)+\ " Duplicates= "+String(DupeCounter)+ " Originals = "+string(FrameNumber-DupeCounter)+" Total = "+string(FrameNumber), align=8) : last""" ScriptClip(DupeInterpolator)