View Full Version : Vapoursynth


Pages : 1 2 3 4 [5] 6

Selur
9th September 2020, 03:55
Using R52:


clip = core.resize.Bicubic(clip=clip, format=vs.RGB48, matrix_in_s="470bg", range_s="limited")
# color adjustment using TimeCube
clip = core.timecube.Cube(clip=clip, cube="I:/Hybrid/64bit/vsfilters/ColorFilter/TimeCube/PQ_to_BT709_slope.cube")
clip = core.resize.Bicubic(clip=clip, format=vs.YUV444P16, matrix_s="470bg", range_s="limited")
clip = core.std.Levels(clip=clip, min_in=16, max_in=235, min_out=16, max_out=235)

-> green screen

clip = core.resize.Bicubic(clip=clip, format=vs.RGB48, matrix_in_s="470bg", range_s="limited")
# color adjustment using TimeCube
clip = core.timecube.Cube(clip=clip, cube="I:/Hybrid/64bit/vsfilters/ColorFilter/TimeCube/PQ_to_BT709_slope.cube")
clip = core.resize.Bicubic(clip=clip, format=vs.YUV444P10, matrix_s="470bg", range_s="limited")
clip = core.std.Levels(clip=clip, min_in=16, max_in=235, min_out=16, max_out=235)

-> green screen
# adjusting color space from YUV420P10 to RGB48 for vscube
clip = core.resize.Bicubic(clip=clip, format=vs.RGB48, matrix_in_s="470bg", range_s="limited")
# color adjustment using TimeCube
clip = core.timecube.Cube(clip=clip, cube="I:/Hybrid/64bit/vsfilters/ColorFilter/TimeCube/PQ_to_BT709_slope.cube")
clip = core.resize.Bicubic(clip=clip, format=vs.YUV444P8, matrix_s="470bg", range_s="limited")
clip = core.std.Levels(clip=clip, min_in=16, max_in=235, min_out=16, max_out=235)
-> works

Same happens when using RGB30 in the scripts.


Levels documentation says:
clip

Clip to process. It must have integer sample type and bit depth between 8 and 16, or float sample type and bit depth of 32. If there are any frames with other formats, an error will be returned.

since there isn't an error I assume this is a bug in Vapoursynth or I'm doing something wrong when converting RGBX to YUV.

So:
a. can others reproduce this?
b. is this a bug in Vapoursynth or am I missing something?


Cu Selur

poisondeathray
9th September 2020, 04:00
@Selur , for the 10bit levels cases, it should not be 16 and 235. It should be 64 and 940. And 4096-60160 for 16bit

Also, you are adjusting all channels, not just Y - is that what you wanted ?

And for CbCr, in 8bit it would be 16-240 , 64-960 for 10bit, 4096-61440 for 16bit

Selur
9th September 2020, 15:00
@Poisongdeathray: Ah okay, I assumed Levels would to the scaling automatically.

Selur
13th September 2020, 05:08
Small question: is there a way to disable auto-loading of filters inside a script (on Linux and Mac) to be sure that only the filters which are explicitly loaded in the script are tried to load?

Myrsloik
13th September 2020, 10:49
Small question: is there a way to disable auto-loading of filters inside a script (on Linux and Mac) to be sure that only the filters which are explicitly loaded in the script are tried to load?

Implemented in the doodle1 branch but it's only accessible through the environment policy interface so it's very iffy. Unfortunately I can't give you an example either right now.

Selur
13th September 2020, 11:04
no problem, I'll wait till it hits the main branch, but happy there it's in the works. :)

shph
17th September 2020, 08:18
I am not an expert but this may be a bug in Vapoursynth (my original post here https://forum.selur.net/showthread.php?tid=1495&pid=9159#pid9159)
Gamma correction works normally if source transformed to RGB. But in YUV it produce green/purple (depends of gamma adjustment direction) color shift.

Examles:
planes: all Gamma adjusted in YUV. Green/Purle color shift problem (probably bug in Vapoursynth):
https://i.imgur.com/19167W1.jpg

planes: luma Gamma adjusted in YUV. No color shift problem, but "desaturation" effect that is essential for this sort of luma only adjustment.https://i.imgur.com/pU5xRll.jpg

planes: all Gamma adjusted in RGB. This is how any normal gamma adjustment usually look:
https://i.imgur.com/tx0WgKI.jpg

As a reference here is screengrab with gamma adjusted PhotoLine graphic editor. Some difference may be due video player screengrabs color management and range transformations, but overall look is near the same. It is dark but not desaturated:
https://i.imgur.com/CdztCXQ.jpg

VS_Fan
17th September 2020, 17:11
I am not an expert but this may be a bug in Vapoursynth (my original post here https://forum.selur.net/showthread.php?tid=1495&pid=9159#pid9159)
Gamma correction works normally if source transformed to RGB. But in YUV it produce green/purple (depends of gamma adjustment direction) color shift.It's not a bug. A brief suggestion: Don’t include the chroma planes if adjusting gamma with core.levels in vapoursynth

Recommended reading: Why gamma-correction is applied to RGB instead of YUV or similar? (https://stackoverflow.com/questions/38750069/why-gamma-correction-is-applied-to-rgb-instead-of-yuv-or-similar)

Also, here’s some info from Avisynth’s Levels (http://avisynth.nl/index.php/Levels)
When processing data in YUV mode, Levels only gamma-corrects the luma information, not the chroma. Gamma correction is really an RGB concept, and is only approximated here in YUV. If gamma=1.0 (unity), the filter should have the same effect in both RGB and YUV modes. For adjusting brightness or contrast in YUV mode, it may be better (depending on the effect you are looking for) to use Tweak or ColorYUV, because Levels changes the chroma of the clip

Selur
17th September 2020, 20:32
Vapoursynth documentation should also include some of this,.. ;)

shph
19th September 2020, 08:33
That makes sense. Y is Luma (tonality data only) and UV is saturation (color data only). Gamma is tonal curve only, so seems it is just useless and incorrect to apply it to UV color data or to YUV all together.

It is ok to apply Gamma only to Y in YUV model.
It is ok to apply Gamma to all RGB channels together or to separate R G B channels in RGB model.

And so we came to YRGB color correction concept used in DaVinci Resolve and some other color grading apps :)
https://i.imgur.com/Z6L91hz.jpg

Cary Knoop
19th September 2020, 17:30
It is ok to apply Gamma only to Y in YUV model.

It really is not ok!

shph
19th September 2020, 23:12
Cary Knoop, Can you explain further why?

As i noticed earlier Y gamma is not the same as RGB gamma. Y gamma is more like some special effect when you need adjust gamma without saturation.

shph
20th September 2020, 04:34
Here is another observation. Tweak is a part of VapourSynth? It was a discussed earlier that color correction results don't match exact to other image editors, but seems it is just due different math concepts of same adjustments in different apps https://forum.doom9.org/showthread.php?t=175093

But also i noticed that Tweak Contrast always shifts a lot to dark side of gradient. It feels like center Pivot point for that tool is way off. Could it be a bug? Maybe Tweak also require some special gamma transformation?
You can download Test Patterns generated in DaVinci Resolve here: https://www.dropbox.com/sh/bak63hnr7mnpgbj/AAAf-rMK0LvHYTAFjPuQaaxFa?dl=0
https://i.imgur.com/w2H580V.jpg

To compare, here is how normal contrast adjustment look s in Davinci Resolve or any other app:
https://i.imgur.com/IRduNq0.jpg

Cary Knoop
20th September 2020, 05:12
Cary Knoop, Can you explain further why?

As i noticed earlier Y gamma is not the same as RGB gamma. Y gamma is more like some special effect when you need adjust gamma without saturation.
You mess up your colors by modifying Y'.

If you want to do what I suspect you want to do you should use something like L*a*b*.
Unfortunately, Vapoursynth does not support this color model.

poisondeathray
20th September 2020, 05:56
Here is another observation. Tweak is a part of VapourSynth? It was a discussed earlier that color correction results don't match exact to other image editors, but seems it is just due different math concepts of same adjustments in different apps https://forum.doom9.org/showthread.php?t=175093

But also i noticed that Tweak Contrast always shifts a lot to dark side of gradient. It feels like center Pivot point for that tool is way off. Could it be a bug? Maybe Tweak also require some special gamma transformation?



tweak is just a port from avisynth tweak

If you want to increase contrast in a fashion similar to how Resolve and other NLE programs work, use havsfunc SigmoidDirect , for an increasing contrast "s-curve". The cont value units do not correlate directly with other programs

clip = haf.SigmoidDirect(clip, cont=blah, planes=[0])

gif demo, cont from 1 to 36
https://i.postimg.cc/mgf84bmJ/havsfunc-Sigmoid-Direct.gif (https://postimages.org/)

There is also VapourSynth-Curve, which can take photoshop acv files, and can work in YUV or RGB, and you can apply to each/all planes

shph
20th September 2020, 07:15
Yes, that sort of symmetrical S-curve variations usually expected when something named as "Contrast". Also center point position of that curve sometimes may be adjusted and that adjustment named "Pivot" in other apps. So it maybe a bug in Tweak, or Tweak may be just designed like this for some purpose.

feisty2
29th September 2020, 09:40
for some unknown reason, this seems to crash vspipe (like it's stuck in an infinite loop or something)

from vapoursynth import *
import os
clp = core.std.BlankClip(format=GRAYS)
clp.set_output(42)
os.system(f'vspipe -o 42 {__file__} tmp.bin -p')
clp = core.raws.Source('tmp.bin', 640, 480, src_fmt='GRAYS')
clp.set_output()

@Myrsloik what is happening here?

feisty2
29th September 2020, 14:13
I found a workaround to solve the problem

from vapoursynth import *
import os
clp = core.std.BlankClip(format=GRAYS)
clp.set_output(42)
if 'cache_flag' not in globals():
os.system(f'vspipe -o 42 -a "cache_flag=yes" {__file__} tmp.bin -p')
clp = core.raws.Source('tmp.bin', 640, 480, src_fmt='GRAYS')
clp.set_output()

it doesn't seem very pretty though...

feisty2
29th September 2020, 17:37
I wonder if there's a better (more accurate) way of doing this (https://github.com/IFeelBloated/VaporMagik/blob/master/VaporMagik.py#L70) with vs.core or the vs environment stuff:

def TraceFilePathOfTheRunningScript():
Frame = inspect.currentframe()
Callers = inspect.getouterframes(Frame)
del Frame
for x in Callers:
if x.filename.endswith('.vpy'):
return x.filename

it should work for most cases but it relies on the script being a .vpy file, which I guess might fail in some rare cases?

Jukus
4th October 2020, 19:01
I don't know if need to write about this, where and how correctly, but this file opens correctly with lsmas, but all the frames are mixed up when using ffms2.
https://1fichier.com/?w8vicd396ctnl4ds9e45

Selur
4th October 2020, 19:16
@Jukus: looks fine here using ffms2,...
Ah okay, I see it if I don't drop halve of the fields. :)
Seems like the field order gets mixed up.

vcmohan
5th October 2020, 12:53
Can I get link to source code of BlankClip function?

feisty2
5th October 2020, 13:04
Can I get link to source code of BlankClip function?

https://github.com/vapoursynth/vapoursynth/blob/master/src/core/simplefilters.c#L1184

stax76
5th October 2020, 13:09
On the github website there is a search field in the top left corner, enter BlankClip there or whatever you search.

Or download the code, open the code folder in Visual Studio Code and click on the search button in the side bar.

https://github.com/vapoursynth/vapoursynth/blob/master/src/core/simplefilters.c

vcmohan
7th October 2020, 07:29
https://github.com/vapoursynth/vapoursynth/blob/master/src/core/simplefilters.c#L1184 many thanks. I am trying to code a plugin where there will be no input clip but only outputs frames. I find in blankclip
VSNodeRef* node = vsapi->propGetNode(in, "clip", 0, &err);
if (!err) {
d.vi = *vsapi->getVideoInfo(node);
vsapi->freeNode(node);
hasvi = 1;
}
What should I do. I have no node as input, but have I to include a node and bind it to something? Or I should have no ref to node in my code?
in the arInitial part what is the purpose of the following?

if (d->vi.fpsNum > 0) {
VSMap* frameProps = vsapi->getFramePropsRW(frame);
vsapi->propSetInt(frameProps, "_DurationNum", d->vi.fpsDen, paReplace);
vsapi->propSetInt(frameProps, "_DurationDen", d->vi.fpsNum, paReplace);
}
Is there an instance where fps == 0?
What is keep?
May be I am testing your patience! Sorry for it.

feisty2
7th October 2020, 11:46
you could try using my c++ wrapper for the vs api, things are as simple, straightforward and obvious as it can get.
this is an example that has no input but has multiple outputs: https://github.com/IFeelBloated/vsFilterScript/blob/master/Examples/Palette.hxx

Selur
10th October 2020, 14:27
Small question about the whole Limiter&Levels filter:
Can someone clear this up?
Is it okay to use Limiter&Levels on YUV content, or should they only be used on RGB content and the planes-parameter is basically a bad idea?
Or is RGB only required for Levels when gamma is used?

Cu Selur

Selur
10th October 2020, 18:39
with:

# Loading F:\TestClips&Co\files\10bit Test.mkv using LWLibavSource
clip = core.lsmas.LWLibavSource(source="F:/TestClips&Co/files/10bit Test.mkv", format="YUV420P10", cache=0)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg",range_s="limited")
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip, fpsnum=25, fpsden=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# Color Adjustment
clip = core.std.Levels(clip=clip, min_in=160, max_in=1020, min_out=160, max_out=880)
# adjusting output color from: YUV420P10 to YUV420P8 for x264Model (i420@8-bit)
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, range_s="limited")

(this should be the same as using In 40/255 and Out 40/220 in 8bit right?)
I get a green image, where as when using:
clip = core.std.Levels(clip=clip, min_in=0, max_in=1020, min_out=160, max_out=880)
(this should be the same as using In 0/255 and Out 40/220 in 8bit right?)
everything looks fine.
-> to me this looks like there is some problem/bug with the min_in restriction with YUV420P10

Cu Selur
iirc scaling should be:
bit depth TV scale PC scale
8 bit 16-235 0-255
10 bit 64-940 0-1023
12 bit 256-3760 0-4095

poisondeathray
10th October 2020, 21:05
@Selur ,

In YUV, usually levels means Y levels

For levels, add

planes=[0]

shph
10th October 2020, 21:31
poisondeathray, Y levels looks more like special effect than something commonly used. See my post here
https://forum.doom9.org/showthread.php?p=1923597#post1923597

poisondeathray
10th October 2020, 21:58
poisondeathray, Y levels looks more like special effect than something commonly used. See my post here
https://forum.doom9.org/showthread.php?p=1923597#post1923597

Your post deals with "gamma" - gamma is an RGB concept

(Gamma can refer to Y plane; it acts as "power" function - and you can check with a Y waveform; but usually not applied to CbCr planes because they are color difference channels)

Levels in YUV , generally refers to Y plane only; applying it to the CbCr planes is the reason for the green discoloration Selur is observing

shph
10th October 2020, 22:19
Levels in-out min-max applied in YUV to Y only also look subjectively incorrect and very different to Levels applied in RGB to all planes.
Same as Gamma, Levels in-out min-max applied in YUV to Y only look more like some sort of special effect but not like something that people usually expect from levels correction.

poisondeathray
10th October 2020, 22:26
Levels in-out min-max applied in YUV to Y only also look subjectively incorrect and very different to Levels applied in RGB to all planes.
Same as Gamma, Levels in-out min-max applied in YUV to Y only look more like some sort of special effect but not like something that people usually expect from levels correction.

That's expected because gamma is a RGB concept.

Levels in/out min/max and gamma in Y looks correct for a Y levels correction. That's what a Y levels adjustment means.

RGB is additive color model . If you start with x value of R and double it, it gets more "red" . Same with Y' (in terms of it increases in brightness, it's not necessarily double) . But this does not happen with CbCr because they are color difference channels - the color completely changes

shph
10th October 2020, 23:38
This is all correct and was explained few posts earlier. I just try to explain that there two options to apply Levels/Gamma/Limiter that give different results:

- RGB channels together
- Y in YUV model

Why do you think that Y in YUV model looks correct but RGB is incorrect? If you compare result to image editors it appears that Y in YUV model looks "incorrect". My personal understanding of this filter is that both results look interesting and may be useful depending of artistic taste or some special requirement. Levels/Gamma/Limiter in RGB model behave like classic Levels tool in any image editing app.
Levels/Gamma/Limiter - Y in YUV model probably behave more like some sort of analogue video filter in equipment that operates in YUV.

shph
10th October 2020, 23:45
Examples:

Limiter in RGB model (forced RGB input was created by TimeCube filter with applied empty identity.cube LUT):
https://i.imgur.com/JntKXVd.jpg

Limiter - Y in YUV model:
https://i.imgur.com/cuOn1Pz.jpg

poisondeathray
11th October 2020, 00:41
Why do you think that Y in YUV model looks correct but RGB is incorrect?


I never said it was incorrect. It's correct for RGB .

I said it was correct for Y, and working correctly for Y channel



If you compare result to image editors it appears that Y in YUV model looks "incorrect".


An image editor works in RGB

Selur
11th October 2020, 05:58
I guess the confusion is that one intuitively assumes that YUV + planes=all would behave like RGB.
Okay, so:
a. either applying level limits only in Y or RGB (Levels and Limiter)
b. when using gamma always use RGB (Levels)
or expect the unexpected?

poisondeathray
11th October 2020, 06:56
a. either applying level limits only in Y or RGB (Levels and Limiter)


Levels limits by clipping can technically be applied to CbCr too, but the range is different than "legal" range Y (CbCr 16-240 in 8bit values, whereas Y is 16-235).

But if you use min/max in/out parameters, or gamma, range compression/expansion is applied or a power function (for gamma) - and that's when you can get unexpected results because of the way CbCr's works (color difference)

RGB range limiting is rare. There are 2 situations where the RGB range would be limited - for r103 compliance or studio range RGB. RGB is typically "full range" in 99.99999% of scenarios.



b. when using gamma always use RGB (Levels)
or expect the unexpected?


Not always; Adjusting "Gamma" - the parameter - can be used on Y channel as a power function . eg. you might want to roughly brighten shadows to a higher degree than highlights

The math for the Y curve is the same as , R, G, B curves (ie. the shape of the curve) when you adjust "gamma" for the latter. YUV obviously isn't RGB, so there is no reason to assume you'd get something visually similar

If you view a Y waveform, you can see what levels (any of the parameters, including gamma) in Y is actually doing to the image. People have used levels or smoothlevels in avisynth (since forever) . You know this, Selur

There are scenarios/ reason why one might prefer manipulations in YUV, but others in RGB

NLE's that work in YUV - their YUV levels "gamma" parameter works the same way, and their R,G,B "gamma" parameter for RGB levels works like an image editor

HuBandiT
12th October 2020, 15:15
I guess the confusion is that one intuitively assumes that YUV + planes=all would behave like RGB.
Okay, so:
a. either applying level limits only in Y or RGB (Levels and Limiter)
b. when using gamma always use RGB (Levels)
or expect the unexpected?

The answer depends on what you are trying to do.

What are you trying to do?

Jukus
12th October 2020, 15:45
Is there no way to use ffmpeg filters inside a script?

poisondeathray
12th October 2020, 16:00
Is there no way to use ffmpeg filters inside a script?


What filter(s) do you need that are not available natively ?

If you need to apply an exclusive ffmpeg filter, and there isn't something similar already available - ffmpeg output can be piped to a vs script (vsrawsource input), and that can be piped back into ffmpeg with vspipe or native ffmpeg vpy demuxer

Jukus
12th October 2020, 16:37
What filter(s) do you need that are not available natively ?
I searched for something autolevels and didn't find it.

I am trying to fix videos where good, normal scenes and very dark scenes are constantly alternating. I tried using "-vf pp=al", it just got a little better. Even if try to manually set the brightness and contrast values for a specific frame, then get disgusting grains, noise and others. I would be glad to have advice for this situation.

poisondeathray
12th October 2020, 17:38
I searched for something autolevels and didn't find it.

I am trying to fix videos where good, normal scenes and very dark scenes are constantly alternating. I tried using "-vf pp=al", it just got a little better. Even if try to manually set the brightness and contrast values for a specific frame, then get disgusting grains, noise and others. I would be glad to have advice for this situation.

I looked and couldn't find any either...

There are several "auto" leveling plugins in avisynth; if you're on windows you can use those in the vpy script. Avisynth+ is supposed to be crossplatform now, but I'm not sure if you can load avs plugins into vpy scripts on other platforms than Win

The ffmpeg/vpy piping back and forth workaround is not ideal; lots of overhead piping back and forth.

_Al_
12th October 2020, 19:49
Just as a curiosity sort of, you could pipe ffmpeg cmd line in vapoursynth directly in your script.
It is not ideal, it is one way only, no searching etc.
vs script is always python script so all python woo-doo is available in vs script as well. Not sure how many folks realize that.
import vapoursynth as vs
from vapoursynth import core
import subprocess
import ctypes

ffmpeg = r'C:\tools\ffmpeg.exe'
source_path=r'C:\videos\video.mp4'
clip = core.lsmas.LibavSMASHSource(source_path) #this clip is not not needed, just to get width and height
clip = core.std.BlankClip(clip)

w = clip.width
h = clip.height
Ysize = w * h
UVsize = w * h//4
frame_len = w * h * 3 // 2 #YUV420

command = [ ffmpeg, '-i', source_path,'-vcodec', 'rawvideo', '-pix_fmt', 'yuv420p', '-f', 'rawvideo', '-']
pipe = subprocess.Popen(command, stdout = subprocess.PIPE, bufsize=frame_len)

def load_frame(n,f):
try:
vs_frame = f.copy()
for i, size in enumerate([Ysize, UVsize, UVsize]):
ctypes.memmove(vs_frame.get_write_ptr(i), pipe.stdout.read(size), size)
pipe.stdout.flush()
except Exception as e:
raise ValueError(repr(e))
return vs_frame

try:
clip = core.std.ModifyFrame(clip, clip, load_frame)
except ValueError as e:
pipe.terminate()
print(e)

clip.set_output()

feisty2
12th October 2020, 19:57
VideoNode has a member function called output(), see: https://github.com/IFeelBloated/Oyster/blob/alpha/Alpha.py#L49

_Al_
12th October 2020, 20:36
yes, thats much better, using some filters on clip and then give it to ffmpeg:
import vapoursynth as vs
from vapoursynth import core
import subprocess

ffmpeg = r'C:\tools\ffmpeg.exe'
source_path=r'C:\videos\video.mp4'
clip = core.lsmas.LibavSMASHSource(source_path)

clip = clip.std.Expr(['x 20 -','','']) #just to demonstrate using some filters before ffmpeg

ffmpeg_cmd = [ffmpeg, '-f', 'yuv4mpegpipe', '-i', '-','-c:v', 'libx264', 'F:\OUT\output.mp4']
process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)
clip.output(process.stdin, y4m = True)
process.communicate()

_Al_
12th October 2020, 20:59
or how about this,
vs -> ffmpeg -> prores - > vs again -> vspipe -> whatever
is it too crazy?
import vapoursynth as vs
from vapoursynth import core
import subprocess

ffmpeg = r'C:\tools\ffmpeg.exe'
INTERMEDIATE = 'F:\OUT\prores.mov'
source_path=r'C:\videos\video.mp4'
clip = core.lsmas.LibavSMASHSource(source_path)
clip = clip.std.Expr(['x 20 -','','']) #just to demonstarte using some filter before ffmpeg

ffmpeg_cmd = [ffmpeg, '-f', 'yuv4mpegpipe', '-i', '-', '-c:v', 'prores', '-an', '-y', INTERMEDIATE]
process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)
clip.output(process.stdin, y4m = True)
process.communicate()

clip = core.lsmas.LibavSMASHSource(INTERMEDIATE)
clip = clip.std.Expr(['x 20 +','','']) #yet some more filters
clip.set_output()
technically , that ffmpeg could be piped into vs again like my example #1, not needing prores ...

feisty2
12th October 2020, 21:09
prores is lossy, ffv1 is probably better for your purpose

_Al_
13th October 2020, 01:34
VideoNode has a member function called output(), see: https://github.com/IFeelBloated/Oyst...a/Alpha.py#L49
What would be the purpose for that Materialize()? Function takes a clip, stores raw data on disk, then reads those data into same clip and that is returned. What is the Inject wrapper?

Oh, I guess it is used for more instances, only one time created.

feisty2
13th October 2020, 02:16
@Inject can dynamically inject any property into native types in python (stuff like list, or VideoNode), this is not normally allowed by python
Materialize() is used to speed up very slow scripts, it materializes intermediate results so they won’t be re-evaluated once things exceed max memory limit

Jukus
14th October 2020, 14:27
How can make a smooth transition between different filters? For example:
clip1 = core.std.Trim(clip, 6223, 8361)
clip1 = adjust.Tweak(clip1, hue=0.0, sat=1.3, bright=8.0, cont=1.1, coring=True)

clip2 = core.std.Trim(clip, 8362, 9887)
clip2 = adjust.Tweak(clip2, hue=0.0, sat=1.4, bright=15.0, cont=1.3, coring=True)
That is, it would not be an instant change, but a smooth transition within 100 frames.

poisondeathray
14th October 2020, 16:13
How can make a smooth transition between different filters? For example:
clip1 = core.std.Trim(clip, 6223, 8361)
clip1 = adjust.Tweak(clip1, hue=0.0, sat=1.3, bright=8.0, cont=1.1, coring=True)

clip2 = core.std.Trim(clip, 8362, 9887)
clip2 = adjust.Tweak(clip2, hue=0.0, sat=1.4, bright=15.0, cont=1.3, coring=True)
That is, it would not be an instant change, but a smooth transition within 100 frames.

You can use CrossFade from kagefunc

Jukus
14th October 2020, 18:40
You can use CrossFade from kagefunc
No, need a smooth transition from some adjust settings to others, not frame blending.

poisondeathray
14th October 2020, 18:44
No, need a smooth transition from some adjust settings to others, not frame blending.

That's what it does, a smooth transition, if the base clip is the same "clip"

Think of it like this:

You have 1 clip. But 2 filtered versions.

1st clip fades out, but 2nd clip fades in , so the filter transition is applied smoothly over period "x"



If that doesn't do what you want, another way would be to write an animation helper function in python, using std.FrameEval . I'm not strong in python , someone can help you with that

poisondeathray
14th October 2020, 22:13
Here is an example of an parameter animation helper function, using tweak's sat .

Interpolation is linear from startframe to endframe , from sat0 to sat1 . (In this example from frame 100 to frame 160, sat=1 to sat=3)

You can add other parameters, but linear interpolation and animation does not necessarily work with all parameters for all types of filters


import vapoursynth as vs
import adjust
import functools
core = vs.get_core()

c = core.colorbars.ColorBars(format=vs.YUV444P10)
c = core.std.SetFrameProp(c, prop="_FieldBased", intval=0) # progressive
c = core.resize.Point(c,format=vs.YUV444P8)
c = c * 300
c = core.std.AssumeFPS(c, fpsnum=30000, fpsden=1001)
c = core.text.FrameNum(c, 7)

def satanim(n, sat0, sat1, startframe, endframe):
if n < startframe:
return adjust.Tweak(c, sat=sat0)
elif n > endframe:
return adjust.Tweak(c, sat=sat1)
else:
return adjust.Tweak(c, sat=round(n-endframe)*(-1*sat0)/(endframe-startframe) + round(n-startframe)/(endframe-startframe) * sat1)


ani = core.std.FrameEval(c, functools.partial(satanim, sat0=1, sat1=3, startframe=100, endframe=160))

ani.set_output()

Jukus
14th October 2020, 22:43
@poisondeathray
Thanks, I'll try again later.
I tried CrossFade and it really works as I suggested, that is, it does blending, while it loads the CPU very much. It also changes the total number of frames.

StainlessS
14th October 2020, 22:56
Note, that Jukus problem as posed, only applies correction 6223, 8361, and 8362, 9887, [ie below 6223 and above 9887 not touched]
whereas PDR script satanim alters entire clip [I assume that CrossFade does too].
This would seem to be correct, pointing this out to Jukus, that will not adjust only frames 6223 -> 9887. [CPU very much comment]

Of course the blending thing would not be appropriate where tweening eg HUE [circular].

EDIT:
It also changes the total number of frames.
Typical with any kind of dissolve, eg CrossFade.

Try the PDR Satanim() thing, I think will preserve length.

EDIT: Ignore this
EDIT: Use trim to only process required range with satanim, then splice back into original clip.

poisondeathray
14th October 2020, 23:17
The helper function returns original clip, unless it's within startframe, endframe range. Length is unchanged . It's similar to animate() in avisynth, where parameters of a function are animated. It's a PITA IMO to setup. It's 100000x (or maybe more like 10000000x) easier to do any type of keyframe interpolation in a NLE or a GUI . And you can easily use other types of animation interpolation (not just linear), and some can GUIs have curves

Instead of using a dissolve function, the other way is to create an alpha channel control clip (white fade to black, or vice versa) where you use Overlay() with the alpha channel mask. This way the clip length is unchanged. This is essentially an animated blend between 2 or more layers.

StainlessS
14th October 2020, 23:21
The helper function returns original clip, unless it's within startframe, endframe range.
Oops, yes.

Jukus
14th October 2020, 23:30
I've already thought about some kind of graphic editor, but I still need filters that only Vapoursynth / Avisynth have.
Сan quickly encode the video in a graphics editor, and only then do it good in Vapoursynth, but that's bd 90 minutes video.

poisondeathray
14th October 2020, 23:36
I've already thought about some kind of graphic editor, but I still need filters that only Vapoursynth / Avisynth have.


Which filters ?

Your example used Tweak; - You have far more control over color manipulation, saturation, contrast, levels , hue etc.. in other programs. All keyframeable. Davinci Resolve, or almost any NLE's.

Jukus
14th October 2020, 23:45
Which filters ?
Ideally, I would like to use QTGMC with InputType = 1, but can only get by with a noise removal filter.

poisondeathray
14th October 2020, 23:54
Ideally, I would like to use QTGMC with InputType = 1, but can only get by with a noise removal filter.

That's OK , avs/vpy are great for some things, bad for others. Pros/Cons like anything

But color manipulation - especially animated parameters, or animated masks/roto - are not avisynth/vapoursynth strong points. If it's something simple , maybe you can stay in avisynth/vapoursynth. But many types of operations cannot be done (or would take years to do) in avs/vpy .

Nothing wrong with combining tools/workflows either - use what works for your needs

Writing a helper function, and defining each parameter is a PITA. And you can't even do realtime adjustments (you can't "see" what you're doing as you're changing), you have to refresh, change, refresh . It's too slow for serious work.

IMO, if staying withing avs/vpy, the overlay blend is the fastest / easiest way to control animation parameters (mix and matching filtered clip states, and the interpolation/transition is controlled by the animated luma mask)

_Al_
15th October 2020, 03:47
Using filters by frame number , that question was already here, it is a good idea to use it within FrameEval().
I would even push it even further, so it is more general, using some MAP table, split functions into separate function.

So it is visually very easy to fix, easy to add functions, and functions could be chained (more filters for the same frame):
#just demo, filters do not make sense, just to see how it works

import functools

def func1(clip):
return clip.std.Expr(['x 50 -','','']) #darken

def func2(clip):
return clip.std.Expr(['x 50 +','','']) #brighten

MAP = { #frame intervals, inclusive #filters
( 0, 256) : [func1],
(257, clip.num_frames-1) : [func1, func2]
#other intervals and functions could be added
}

def distribute_filters(n, clip):
for (lower, upper), funcs in MAP.items():
if lower <= n <= upper:
clip = functools.reduce(lambda r, f: f(r), funcs, clip) #this chains filters, example: clip=func2(func1(clip))
return clip

fixed = core.std.FrameEval(clip, functools.partial(distribute_filters, clip=clip))
fixed.set_output()

_Al_
15th October 2020, 03:52
To include crossfades it gets more tricky because filter needs frame number n and interval frame numbers, the whole script with that question about adjust.tweak():

import functools
import adjust

source_clip = ...... use your source filter

def tweak1(clip, *args):
return adjust.Tweak(clip, hue=0.0, sat=1.3, bright=8.0, cont=1.1, coring=True)

def tweak2(clip, *args):
return adjust.Tweak(clip, hue=0.0, sat=1.4, bright=15.0, cont=1.3, coring=True)

def crossfade1(clip, n, lower, upper):
return core.std.Merge(tweak1(clip[n]), tweak2(clip[n]), weight=(n-lower)/(upper-lower))

MAP = {
(6223, 8311) : [tweak1],
(8312, 8412) : [crossfade1],
(8413, 9887) : [tweak2]
}

def distribute_filters(n, clip):
for (lower, upper), funcs in MAP.items():
if lower <= n <= upper:
clip = functools.reduce(lambda r, f: f(r, n, lower, upper), funcs, clip)
return clip

out_clip = core.std.FrameEval(source_clip, functools.partial(distribute_filters, clip=source_clip))
out_clip.set_output()

crossfades is just using core.std.Merge() so down to basics, it could be called just like this,
and again, filters could be chained in that MAP dictionary, like [tweak1, my_filter, my_other filter] , so more filters could be used on the same frame

_Al_
16th October 2020, 00:05
It's 100000x (or maybe more like 10000000x) easier to do any type of keyframe interpolation in a NLE or a GUI . Lets make it better, something like 100x easier in NLE than in vs :-)

To animate all arguments in a filter (if possible) instead of crossfade could be done like this:
import vapoursynth as vs
from vapoursynth import core
import functools
import adjust
source_clip = .....

TWEAK1 = dict(hue=0.0, sat=1.3, bright=8.0, cont=1.1, coring=True)
TWEAK2 = dict(hue=0.0, sat=1.4, bright=15.0, cont=1.3, coring=True)
TWEAK_TYPES = dict(hue=None, sat= float, bright=float, cont=float, coring=None) #int, float or None to not animate argument

TWEAK_DIFF = dict()
for key, value in TWEAK1.items():
if TWEAK_TYPES[key] is not None:
TWEAK_DIFF[key] = round(TWEAK1[key]-TWEAK2[key]) if TWEAK_TYPES[key] == int else round(TWEAK1[key]-TWEAK2[key],2)

def tweak1(clip, *args):
return adjust.Tweak(clip, **TWEAK1)

def tweak2(clip, *args):
return adjust.Tweak(clip, **TWEAK2)

def crossfade1(clip, n, lower, upper):
tweak_out = dict()
for key, value in TWEAK2.items():
if TWEAK_TYPES[key] is not None:
tweak_out[key] = TWEAK1[key] - ((n-lower)/(upper-lower) * TWEAK_DIFF[key])
else:
tweak_out[key] = value
#print(tweak_out) #debug to see argument values for a frame
return adjust.Tweak(clip, **tweak_out)

MAP = {
(6223, 8311) : [tweak1],
(8312, 8412) : [crossfade1],
(8413, 9887) : [tweak2]
}

def distribute_filters(n, clip):
for (lower, upper), funcs in MAP.items():
if lower <= n <= upper:
clip = functools.reduce(lambda r, f: f(r, n, lower, upper), funcs, clip)
return clip

out_clip = core.std.FrameEval(source_clip, functools.partial(distribute_filters, clip=source_clip))
out_clip.set_output()
Not sure about performance, but it should behave as all in FrameEval() hopefully

_Al_
16th October 2020, 00:29
i did not took care if there is int type of value for that tweak_out[key] in crossfade1(), if it is 'int', it needs to be rounded up to integer, but anyway ...

Selur
17th October 2020, 08:05
Small question: How to handle 32bit Tiff with Levels properly?

I wanted to load a single 32bit TIFF with vsImageReader and apply levels on it.
Problem is I have no clue how to do it properly.
I assumed that the color space should be RGBS with 32bit precision and thus analog to limiting to 16-235 I used min_in = 16 << (32-8), max_in=235 << (32-8), min_out= 16 << (32-8), max_out = 235 << (32-8).
That gave me a black preview and I'm not sure whether this is due to a limitation of the preview, if I did something wrong or if it's a limitation somewhere else.
So any help is welcome.

# Imports
import vapoursynth as vs
core = vs.get_core()
# source: 'C:/Users/Selur/Desktop/images v2/TIFF 32-bit.tif'
# current color space: RGBS, bit depth: 32, resolution: 640x480, fps: 25, color matrix: 709, yuv luminance scale: full, scanorder: progressive
# Loading C:\Users\Selur\Desktop\images v2\TIFF 32-bit.tif using vsImageReader
clip = core.imwri.Read(["C:/Users/Selur/Desktop/images v2/TIFF 32-bit.tif"])
clip = core.std.Loop(clip=clip, times=100)
# Input color space is assumed to be RGBS
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip, fpsnum=25, fpsden=1)
# Setting color range to PC (full) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=0)
# Color Adjustment
clip = core.std.Levels(clip=clip, min_in=268435456, max_in=18446744073357230080, min_out=268435456, max_out=18446744073357230080)
# Output
clip.set_output()


Cu Selur

Ps.: I know that there's not many filters and output formats that support RGBS, but that's okay.

feisty2
17th October 2020, 12:21
is it settled that the new API will be placed in "VapourSynth4.h" and "VapourSynth.h" is always the old API?

poisondeathray
17th October 2020, 15:59
Small question: How to handle 32bit Tiff with Levels properly?

I assumed that the color space should be RGBS with 32bit precision


Depends on what you have, where it's from

Usually 32bpc float would be loaded with float_output=True

imwri.Read(....float_output=True)

RGBS would "normal" values be 0 to 1 , but values can be negative or >>1 .

eg. it's normal for a HDR sequence have values 10 or 20 with usable data

Myrsloik
17th October 2020, 17:38
is it settled that the new API will be placed in "VapourSynth4.h" and "VapourSynth.h" is always the old API?

Yes. Only minor changes are planned from now on.

Selur
17th October 2020, 18:22
@poisondeathray: thanks :) (not tackling HDR atm.)

neo_sapien
18th October 2020, 03:45
Can someone please check my script? I took an Avisynth script and turned it into a Vapoursynth version, and I want to make sure that they're comparable.

Avisynth script:

TFM()
TDecimate()
QTGMC2 = QTGMC(Preset="Very Slow", SourceMatch=3, TR2=4, InputType=2, Lossless=2, MatchEnhance=0.75, Sharpness=0.5, MatchPreset="Very Slow", MatchPreset2="Very Slow")
QTGMC3 = QTGMC(preset="Very Slow", inputType=3, TR2=4)
Repair(QTGMC2,QTGMC3, 9)


Vapoursynth script:

clip = core.std.SetFieldBased(clip, 2) # 1 = BFF, 2 = TFF
clip = core.vivtc.VFM(clip, 1)
clip = core.vivtc.VDecimate(clip)
QTGMC1 = havsfunc.QTGMC(clip, TFF = True, Preset="Very Slow", SourceMatch=3, TR2=4, InputType=2, Lossless=2, MatchEnhance=0.75, Sharpness=0.5, MatchPreset="Very Slow", MatchPreset2="Very Slow")
QTGMC2 = havsfunc.QTGMC(clip, TFF = True, Preset="Very Slow", InputType=3, TR2=4)
clip = core.rgvs.Repair(QTGMC1,QTGMC2, 9)


I'm also using this script to try and upscale my clip, doubling the height and width, after it's made progressive. This is just enlarging, right? It's not trying to re-deinterlace? Since I noticed the field bit.


clip = core.nnedi3cl.NNEDI3CL(clip, field = 1, pscrn=2, nsize=4, qual =2, nns =4, dh=True, dw=True)

HuBandiT
18th October 2020, 15:33
Small question: How to handle 32bit Tiff with Levels properly?

I assumed that the color space should be RGBS with 32bit precision and thus analog to limiting to 16-235 I used min_in = 16 << (32-8), max_in=235 << (32-8), min_out= 16 << (32-8), max_out = 235 << (32-8).
So any help is welcome.


PlaneStats is your friend: http://www.vapoursynth.com/doc/functions/planestats.html

And so is a histogram: https://github.com/dubhater/vapoursynth-histogram

Edit: no, actually PlaneStats is not good for this case - according to the docs at least it does some kind of normalization on the input.

feisty2
18th October 2020, 17:36
Do frame properties exist for audio frames as well? (I still don’t quite understand what a frame means for audio...)

Myrsloik
18th October 2020, 19:25
Do frame properties exist for audio frames as well? (I still don’t quite understand what a frame means for audio...)

Yes. They exist but I'm not sure what they're good for. One audio frame is up to 3000 samples. No idea what you'd actually want to flag that way though.

feisty2
20th October 2020, 09:35
Is it legal to instantly fetch a frame (via getFrameFilter) after requesting it (in the arInitial branch)?

Myrsloik
20th October 2020, 09:42
Is it legal to instantly fetch a frame (via getFrameFilter) after requesting it (in the arInitial branch)?

I think so. Any frame that isn't ready yet should simply return null.

But why would you do that?

feisty2
20th October 2020, 09:57
I guess to eliminate the need to call GetFrame() on video nodes. After a frame has been requested, it could be instantly fetched and stored in an associative container held by the video node, so the user may access the frame via Clip[n] instead of Clip.GetFrame(n, FrameContext).

_Al_
23rd October 2020, 05:27
Having this code:
clip = ... interlaced 25 fps clip
clip2 = havsfunc.QTGMC(clip, Preset="Fast", TFF=True)
print(clip2)
correctly shows:
Format: YUV420P8
Width: 1920
Height: 1080
Num Frames: 600
FPS: 50
Flags: NoCache
but
clip = ... interlaced 25 fps clip
def deint(n, clip):
return havsfunc.QTGMC(clip, Preset="Fast", TFF=True)
clip2 = clip.std.FrameEval(functools.partial(deint, clip=clip))
print(clip2)
shows wrong number of frames:
Format: YUV420P8
Width: 1920
Height: 1080
Num Frames: 300
FPS: 25
Flags: NoCache IsCache

if its within FrameEval() it passes originals clip fps for print function. clip2 is properly bobed, but evaluation prints original clips values.


Now looking at it, it actually is correct behavior, how to fix it though so it bobs all frames?

another EDIT:
assuming that first argument is just a placeholder so:
clip2 = core.std.FrameEval(clip.std.AssumeFPS(fpsnum=50, fpsden=1)*2, functools.partial(deint, clip=clip)) seams to give good result, hopefully nothing is broken

_Al_
24th October 2020, 01:07
It does not work. I guess frame number in must be total out, its how it works.
Or maybe is there a way how to manipulate that n using lambda somehow?
clip2 = clip.std.FrameEval(lambda n: deint(n, clip=clip))
To do something with that n to force FrameEval pass more frames out than in?

_Al_
26th October 2020, 04:13
Just tried it again, yes it works with that placeholder with doubled fps and doubled lenght,
not sure what went wrong yesterday, it seams to return clip correctly from FrameEval().
It works with both, partial and lambda function as well.

feisty2
26th October 2020, 13:27
are clips with varying format no longer supported in API v4?
I notice that "format" is no longer a pointer in the "info" struct.

Myrsloik
26th October 2020, 13:35
are clips with varying format no longer supported in API v4?
I notice that "format" is no longer a pointer in the "info" struct.

Nope, still supported. It's when the format is pfNone (0).

feisty2
27th October 2020, 18:48
is it possible for a filter to return multiple nodes, and some of them are vnodes while others are anodes?

feisty2
27th October 2020, 19:23
also, the documentation on calling python functions is a bit unclear, like it was not documented that the return value binds to the "val" key, if the function has multiple return values, will they all bind to "val"?

Myrsloik
27th October 2020, 22:49
is it possible for a filter to return multiple nodes, and some of them are vnodes while others are anodes?

Filters can't but functions can. A single VSMap key can only hold anodes or vnodes.

feisty2
28th October 2020, 11:05
Filters can't but functions can.

okay, then how do I retrieve the return values from such function in a C++ plugin? I know the first return value binds to "val", what about other return values?

feisty2
29th October 2020, 19:33
I played with some pretty ugly hacks


// C++ plugin
auto ret = VSFuncRef_stuff();
auto msg = ""s;
auto m = ret.map_pointer;

for (auto x : Range{ vsapi->propNumKeys(m) }) {
msg += vsapi->propGetKey(m, x);
msg += "\n";
}

throw msg;

# Python tests
def f():
return 'aaa', 'bbb'

def g():
return 'aaa', 123

core.???.Test(f) # okay, error message says "val"
core.???.Test(g) # error message says "not all values are of the same type in val"


and observed from the error log of vsedit that:
1) it is allowed to call a python function with multiple return values of the same type
2) all return values bind to the same key called "val"
3) it is not allowed to call a python function with multiple return values of different types because of 2)

@Myrsloik
technical details like this should really be documented rather than leave us wild guessing and poking around.

feisty2
31st October 2020, 09:45
is paTouch removed from api v4?

Myrsloik
31st October 2020, 12:31
is paTouch removed from api v4?

Yes, there's the mapSetEmpty() instead.

feisty2
5th November 2020, 21:08
is there an example for createFunc(), it seems like a way to call arbitrary C++ functions in py scripts?

Myrsloik
5th November 2020, 23:17
is there an example for createFunc(), it seems like a way to call arbitrary C++ functions in py scripts?

I think it's only used in python code (see vapoursynth.pyx for c-ish code) and then lut/lut2 for a callFunc() example.

Selur
8th November 2020, 12:39
Is there some known issue with fmtc and R52?
using:
# Imports
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
core.std.LoadPlugin(path="I:/workspace/Hybrid/debug/64bit/vsfilters/Support/fmtconv.dll")
core.std.LoadPlugin(path="I:/workspace/Hybrid/debug/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")
# source: 'F:\TestClips&Co\files\test.avi'
# current color space: YUV420P8, bit depth: 8, resolution: 640x352, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: progressive
# Loading source using FFMS2
clip = core.ffms2.Source(source="F:/TestClips&Co/files/test.avi",cachefile="E:/Temp/avi_078c37f69bb356e7b5fa040c71584c40_853323747.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg",range_s="limited")
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
original = clip
clip = core.fmtc.resample(clip=clip, kernel="gaussian", w=1280, h=704, interlaced=False, interlacedd=False)
original = core.fmtc.resample(clip=original, kernel="bicubic", w=1280, h=704, interlaced=False, interlacedd=False)
# adjusting output color from: YUV420P16 to YUV420P8 for FFvHuffModel (i420@8)
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, range_s="limited")
# adjusting for FilterView
if (original.format.id != clip.format.id):
if (original.format.color_family == vs.RGB and clip.format.color_family != vs.RGB):
original = core.resize.Bicubic(clip=original, format=clip.format.id, matrix_s="470bg", range_s="limited")
elif (original.format.color_family == clip.format.color_family):
original = core.resize.Bicubic(clip=original, format=clip.format.id, range_s="limited")
else:
original = core.resize.Bicubic(clip=original, format=clip.format.id, matrix_in_s="470bg", range_s="limited")
stacked = core.std.StackHorizontal([original,clip])
# set output frame rate to 25.000fps
stacked = core.std.AssumeFPS(clip=stacked, fpsnum=25, fpsden=1)
# Output
stacked.set_output()
both Vapoursynth Editor and vspipe both sometimes crash without an error, while other times vspipe crashes after a few hundred frames and then both run fine.

Cu Selur

feisty2
8th November 2020, 15:11
is copyFrameProps removed from API v4?

Myrsloik
8th November 2020, 16:41
Is there some known issue with fmtc and R52?
using:
...
both Vapoursynth Editor and vspipe both sometimes crash without an error, while other times vspipe crashes after a few hundred frames and then both run fine.

Cu Selur

Hard to tell what causes it without some kind of crash dump for debugging. I haven't seen any reported issues and nothing has changed in VS in frame/filter handling.

Myrsloik
8th November 2020, 16:42
is copyFrameProps removed from API v4?

I think I did. It was replaced with a map copy functions so you have to go the long way around and use that instead.

feisty2
8th November 2020, 21:20
there's no preset for audio formats?

feisty2
10th November 2020, 19:30
is it possible to change the API for releaseFrameEarly to void(const VSFrameRef*, VSFrameContext*) (release directly from a frame object rather than from a node object)?
the current API kind of breaks RAII for C++, a frame object always keeps the ownership of its underlying frame reference, if a frame reference is released from a node, there's no way to inform the frame object who's keeping the ownership of the reference that the reference has expired, and there will be a "double free" error after getFrame() returns.

feisty2
10th November 2020, 19:47
or maybe releaseFrameEarly() could set a frame to a "zombie" mode, the most memory consuming part (the image content of the frame) is instantly released after calling this function, but the frame header, particularly the part that's keeping the reference count is still alive in the memory, so there won't be a "double free" error when any frame object goes out of scope.

Myrsloik
10th November 2020, 20:10
there's no preset for audio formats?

No, trivial to query so I didn't see any real need. Also they can't be properly serialized into a single int.

Myrsloik
10th November 2020, 20:39
is it possible to change the API for releaseFrameEarly to void(const VSFrameRef*, VSFrameContext*) (release directly from a frame object rather than from a node object)?
the current API kind of breaks RAII for C++, a frame object always keeps the ownership of its underlying frame reference, if a frame reference is released from a node, there's no way to inform the frame object who's keeping the ownership of the reference that the reference has expired, and there will be a "double free" error after getFrame() returns.

No, releaseFrameEarly() is more or less deprecated and useless for 99.99% of filters. Write a wrapper that caters to the masses instead.

feisty2
16th November 2020, 20:06
how do I obtain the return value of the function that is passed to createFunc() in python?


// C++ code, inside getFrame()
auto f = [](auto in, auto out, auto, auto, auto) {
vsapi->propSetFloat(out, "val", 2.71, VSPropAppendMode::paReplace);
vsapi->logMessage(VSMessageType::mtWarning, "aaaaaaa");
};

auto fp = Function{ vsapi->createFunc(f, nullptr, [](auto) {}, core, vsapi) };
ProcessedFrame["test"] = fp;


#Python script
clip = core.test.Test(clip)
x = clip.get_frame(0).props['test']() # prints "aaaaaaa" as expected, however x is of type None rather than float

feisty2
16th November 2020, 22:32
it seems the problem is caused by Func.__call__() discarding its return value: https://github.com/vapoursynth/vapoursynth/blob/doodle1/src/cython/vapoursynth.pyx#L636
this "ret" thing, after receiving whatever stored in the out map, was never returned by __call__ and was simply discarded.
is this a bug?

feisty2
19th November 2020, 11:43
is the message handler attached to each core and no longer global in API v4?

Myrsloik
19th November 2020, 11:53
is the message handler attached to each core and no longer global in API v4?

Correct

feisty2
19th November 2020, 12:02
what's the use of removeMessageHandler()? it seems I can remove the current handler by simply passing a NULL handler to addMessageHandler()?
who owns the char pointer that the handler receives? is it the same pointer passed to logMessage() or a pointer to some internal deep copy of what's passed to logMessage()?

Myrsloik
19th November 2020, 12:34
what's the use of removeMessageHandler()? it seems I can remove the current handler by simply passing a NULL handler to addMessageHandler()?
who owns the char pointer that the handler receives? is it the same pointer passed to logMessage() or a pointer to some internal deep copy of what's passed to logMessage()?

addMessageHandler() simply adds one more handler, it never removes the current one
you then remove the handler by passing the handle from addMessageHandler() to removeMessageHandler()
Ownership is also optional since all handlers obviously will be removed automatically when a core is destroyed. Calling removeMessageHandler() with an invalid/already freed handle is safe and does nothing.

feisty2
19th November 2020, 12:46
interesting, I didn't realize there could be multiple message handlers. so logMessage() will send the message to all registered handlers?

Myrsloik
19th November 2020, 12:49
interesting, I didn't realize there could be multiple message handlers. so logMessage() will send the message to all registered handlers?

Yes

Filler here

feisty2
21st November 2020, 20:10
I can't decide which is the correct design for message handlers.
should I bind the lifetime of a message handler to its descriptor, like a file descriptor?

auto md = Core.AddMessageHandler([](auto...) {});
// md is a stateful object
// automatically calls removeMessageHandler() in md's destructor when it goes out of scope

or should I let the user manage the handler's lifetime manually?

auto md = Core.AddMessageHandler([](auto...) {});
// md is a stateless integer ID / pointer

Core.Eject(md);
// explicitly ejects the handler when no longer needed.

feisty2
22nd November 2020, 11:48
does getFrameAsync() have any special behavior (creating new threads, etc.)?
it seems the same asynchronous behavior could be achieved by simply calling getFrame() with std::async?

auto f = std::async(std::launch::async, [&] { return vsapi->getFrame(n, node, nullptr, 0); });

... // do something else while waiting for f

auto frame = f.get(); // block the current thread and retrieve the frame when needed


why should I use getFrameAsync() instead of something like the code above?

Selur
22nd November 2020, 20:49
I use a jpeg as source:
General
Complete name : c:\Users\Selur\Desktop\test.jpg
Format : JPEG
File size : 465 KiB

Image
Format : JPEG
Width : 1 280 pixels
Height : 534 pixels
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Compression mode : Lossy
Stream size : 465 KiB (100%)
which I open using:
clip = core.imwri.Read(["C:/Users/Selur/Desktop/test.jpg"])
clip = core.std.Loop(clip=clip, times=100)
what confuses me is that the file is reported as RGB24.
Does ImageMagick Writer-Reader (http://www.vapoursynth.com/doc/plugins/imwri.html) always return RGB or am I missing something?
In case it always returns RGB, it would be nice if this could be added to the documentation.

Cu Selur

Myrsloik
23rd November 2020, 10:36
I use a jpeg as source:
General
Complete name : c:\Users\Selur\Desktop\test.jpg
Format : JPEG
File size : 465 KiB

Image
Format : JPEG
Width : 1 280 pixels
Height : 534 pixels
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Compression mode : Lossy
Stream size : 465 KiB (100%)
which I open using:
clip = core.imwri.Read(["C:/Users/Selur/Desktop/test.jpg"])
clip = core.std.Loop(clip=clip, times=100)
what confuses me is that the file is reported as RGB24.
Does ImageMagick Writer-Reader (http://www.vapoursynth.com/doc/plugins/imwri.html) always return RGB or am I missing something?
In case it always returns RGB, it would be nice if this could be added to the documentation.

Cu Selur

It probably always returns RGB... maybe.

feisty2
23rd November 2020, 11:46
some elaboration on the issue mention at #4187 would be nice...
it's hard to determine the design of the async interface without knowing the technical details of the C API. also it's a lot harder to convert a callback kind of stuff to std::future which involves locks, condition variable and other unnecessary complexity.

Myrsloik
23rd November 2020, 12:44
some elaboration on the issue mention at #4187 would be nice...
it's hard to determine the design of the async interface without knowing the technical details of the C API. also it's a lot harder to convert a callback kind of stuff to std::future which involves locks, condition variable and other unnecessary complexity.

Internally getFrame() is implemented as a function that waits for getFrameAsync() to return. So I guess wrapping getFrame() in a future would be close at least. But with a lot of unnecessary locking and bookkeeping added.

feisty2
26th November 2020, 14:06
I think "id" should be a member of VSVideoFormat in API v4, otherwise it requires access to the core to determine if a clip has a constant format which is not very convenient

feisty2
26th November 2020, 14:11
or at least make the core parameter optional for queryVideoFormatID()

feisty2
26th November 2020, 22:11
it seems API v4 uses the colorfamily to determine if a format is constant, that's a bit weird...

Selur
28th November 2020, 18:53
Is there an "autowhite" filter which is more clever than the example over at http://www.vapoursynth.com/doc/functions/frameeval.html ?

feisty2
28th November 2020, 19:30
What do you mean by "more clever"? Like adding temporal consistency?

Selur
29th November 2020, 08:33
Yes, exactly. Temporal temporal consistency while taking scene changes into account. I was looking for some 'auto' filters like AutoAdjust, AutoContrast, Autolevels, HDRAGC and similar for Vapoursynth and the frameeval example of autowhite was the only thing I found. Seeing that it was a 'simple per frame auto white balance', I was wondering if there are mor complex/clever solutions out there. :)

feisty2
29th November 2020, 22:08
Yes, exactly. Temporal temporal consistency while taking scene changes into account. I was looking for some 'auto' filters like AutoAdjust, AutoContrast, Autolevels, HDRAGC and similar for Vapoursynth and the frameeval example of autowhite was the only thing I found. Seeing that it was a 'simple per frame auto white balance', I was wondering if there are mor complex/clever solutions out there. :)
here: https://github.com/IFeelBloated/AutoWB/blob/master/src.cxx, basically the same as that FrameEval stuff, but with temporal functionalities. writing vaporsynth filters is really easy, it's really no different from scripting in Python. you should consider writing a filter yourself next time you wanna add some basic extensions to an existing script/plugin.

Selur
2nd December 2020, 10:43
Nice. Thanks! :)

Myrsloik
9th December 2020, 16:59
I think "id" should be a member of VSVideoFormat in API v4, otherwise it requires access to the core to determine if a clip has a constant format which is not very convenient

Only id = 0 mean variable format. This is strictly enforced by all the api functions. The reason the api function need the core pointer is to maintain V3 api compatibility where the id isn't a simple serialization so a V4 filter won't choke if it's fed a V3 id.
If it truly bothers you look at the macro used to create ids and parse them on your own, the only advantage the api gives you is that invalid combinations will be rejected instead of possibly passed on.

feisty2
9th December 2020, 18:23
I've unified the memory layout of VideoFormat and VideoInfo in my wrapper (which currently still relies on API v3) to match that of API v4:
https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Node.vxx#L109
https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Metadata.vxx#L18
it should be fully compatible with API v4 at the source code level.

stax76
14th December 2020, 15:39
Guys, please up vote my request for direct VapourSynth support for x265:

https://github.com/msg7086/x265-Yuuki-Asuna/issues/11

lansing
18th December 2020, 09:42
I have started noticing this memory hungry behavior on Vapoursynth on preview editors like vseditor and virtualdub2. Whenever a script was loaded, Vapoursynth seems to allocate a big chunk of memory before any frame was even requested. For example, I have a script with 1080p video and QTGMC in vseditor, on script load the memory jumped straight to 4.5 GB of RAM, this is both unnecessary and unsustainable for multi tab editor, where it will be running out of memory for most people just by opening four or five similar scripts.

edcrfv94
18th December 2020, 13:05
Can filter once, multiple output to simultaneous x265 encoding? e.g. different filter stage or resolution 720p 1080p 2160p.

feisty2
18th December 2020, 13:27
yes, see: https://github.com/IFeelBloated/Oyster/blob/alpha/Alpha.py#L49

stax76
18th December 2020, 14:45
I'm not understanding why line 1+2 are needed here, isn't that exactly what altsearchpath=True in line 3 is supposed to do? Without line 1+2 it's not working.


import os.path
os.environ["PATH"] = r"C:\Anime4KCPP VapourSynth" + os.pathsep + os.environ["PATH"]
core.std.LoadPlugin(r"C:\Anime4KCPP VapourSynth\Anime4KCPP_VapourSynth.dll", altsearchpath=True)
clip = core.anime4kcpp.Anime4KCPP(clip, GPUMode = 1, ACNet = 1, zoomFactor = 2, HDN = 1, HDNLevel = 2)

Are_
18th December 2020, 16:09
Doesn't documentation say that's for dependencies?

stax76
18th December 2020, 17:02
I think I understand it now, what altsearchpath=True does is telling the LoadLibrary function to search dependencies in PATH.

_Al_
18th December 2020, 22:39
I have started noticing this memory hungry behavior on Vapoursynth on preview editors like vseditor and virtualdub2. Whenever a script was loaded, Vapoursynth seems to allocate a big chunk of memory before any frame was even requested. For example, I have a script with 1080p video and QTGMC in vseditor, on script load the memory jumped straight to 4.5 GB of RAM, this is both unnecessary and unsustainable for multi tab editor, where it will be running out of memory for most people just by opening four or five similar scripts.
Nowadays memory should not be an issue. Or you just limit it. For my Preview I use that below, first free memory is evaluated and if not enough, it is limited in vapoursynth. No more memory problems. Sure it might be not optimal, but on the other hand it never freezes, there is no other way if not enough memory, like using QTGMC for HD etc, and it is automatic, no more guessing or setting max cache size.


import vapoursynth as vs
from vapoursynth import core
try:
import psutil
except ImportError:
pass
import os

def freeRAM():
'''
getting free RAM
first it uses non standard library cross platform psutil
if modul is not installed, it falls back using Linux or Windows ways to get free RAM
so for Mac it needs psutil: to install psutil: pip3 install psutil
'''
available_RAM = None

#cross platform try if psutil is installed
try:
mem = psutil.virtual_memory()
available_RAM = int(mem.available/1024/1024)
if available_RAM and isinstance(available_RAM, int):
return available_RAM
except:
pass

#windows fallback
try:
proc = os.popen('wmic.exe OS get FreePhysicalMemory')
l = proc.readlines() #l should be a list
proc.close()
except:
pass
else:
for i, item in enumerate(l):
try:
available_RAM = int(l[i])
available_RAM = int(available_RAM/1024)
if available_RAM and isinstance(available_RAM, int):
return available_RAM
except:
pass

#linux fallback
try:
meminfo = dict((i.split()[0].rstrip(':'),int(i.split()[1])) for i in open('/proc/meminfo').readlines())
available_RAM = int(meminfo['MemAvailable']/1024)
if available_RAM and isinstance(available_RAM, int):
return available_RAM
except:
pass

#failed to get free RAM
return None

def limit_core_cache(core):
'''
Returns tuple (core, log).
Sets core.max_cache_size for less than available RAM,
log is string type ready for print.
'''

log = []
available = None
vs_cache = core.max_cache_size
log.append(f'vapoursynth cache is set to: {vs_cache}MB')
available_RAM = freeRAM()
if available_RAM is not None:
log.append(f'free RAM: {available_RAM}MB')
deduct = 0
if available_RAM < 200:
deduct = 50
log.append('almost no RAM, system likely to freeze')
elif 200 <= available_RAM < 400:
deduct = 120
log.append('not much RAM at all, freezing likely, lagish performance')
elif 400 <= available_RAM < 1024:
deduct = 220
log.append('more RAM would give better performance')
elif 1024 <= available_RAM < 1536:
deduct = 280
else:
deduct = 350
new_cache = max(50, available_RAM - deduct)
if new_cache < vs_cache:
log.append(f'setting Vapoursynth cache to: {new_cache}MB')
core.max_cache_size = new_cache
else:
log.append('\nWARNING, failed to get available free RAM,')
log.append(' Vapoursynth cache was not limited if needed,')
log.append(' RAM overrun or freeze possible\n')
return core, '\n'.join(log)
So it might be put as some extra module and just calling it:

import my_module
core, info = my_module.limit_core_cache(core)
if info: print(info) #or log or something

lansing
19th December 2020, 01:15
Nowadays memory should not be an issue. Or you just limit it. For my Preview I use that below, first free memory is evaluated and if not enough, it is limited in vapoursynth. No more memory problems. Sure it might be not optimal, but on the other hand it never freezes, there is no other way if not enough memory, like using QTGMC for HD etc, and it is automatic, no more guessing or setting max cache size.


I think for editor, the limiting of cache size should be frame based rather than memory based. The same QTGMC filter running in avspmod only takes 915 MB on playback because avs+(I think) only caches 3 frames.

_Al_
19th December 2020, 03:05
I'm no developer, grateful for I got available.
Some ideas, but sure they could be dead wrong, lacking proper developer background and experience:

-Saying 3 frames sounds like an arbitrary solution, because frame could be any size, SD, HD, 4k. Folks have 32GB nowadays. I have 20GB in "cheaper" laptop. 16GB extra for something like $30.

-Couple of lines above this, feisty2 is storing RAW video so script does not run for more things. We got 4k on the horizon that's the way I guess.

-I mentioned that before. Having more instances of script and switching between them. I think much better is to have clip instances and switch between them and so adjust workflows and habits to do so. Python literally wants you to. Tons of filters above some point, denoise, QTGMC is already rendered and some clips are forked at the bottom of the script, below, to have many filters absolutely the same. If nothing, then at least source plugin is the same. No need to calculate something 5x because having 5 scripts. To get rid of avisynth workflows might help. A red-neck-faulty-spaghetti-code preview I did, switching between clips, not scripts, is very fast comparing clips, instant during playback.

-Also Qt should remember frames, some decent number, depending on size, same as opencv so switching and comparing frames ones were rendered should be instant.

feisty2
30th December 2020, 08:47
if an installed logger is never manually removed by removeLogHandler(), will it be automatically removed when the core is freed?

Myrsloik
30th December 2020, 20:20
if an installed logger is never manually removed by removeLogHandler(), will it be automatically removed when the core is freed?

Yes yes yes!

poisondeathray
31st December 2020, 17:31
I think for editor, the limiting of cache size should be frame based rather than memory based. The same QTGMC filter running in avspmod only takes 915 MB on playback because avs+(I think) only caches 3 frames.

But _Al_ does have some good points...

It's often faster for me to preview in avspmod using VSImport() for me when using multiple tabs and navigating, even with the overhead. It's less sluggish and it seems more frames are held in memory

Soliloquy
11th January 2021, 20:25
I'm having troubles running portable python / vapoursynth on win10 x64, version 1909.
I got python 3.9.1 and placed it in a folder, then extracted vapoursynth r52 in the same folder. Lastly i exctracted vapoursynth editor and upon running, it simply prints "Failed to initialize VapourSynth environment!".
Not sure what to try next - googled the issue and didn't really find anything to try besides typing import sys; sys.executable and see what it outputs, which is 'E:\\Encoding\\vapoursynth\\python.exe'.
What do i try next?

ChaosKing
11th January 2021, 20:34
R52 needs Python 3.8 on windows.

Soliloquy
11th January 2021, 22:22
that did it, thanks man!

unix
15th January 2021, 17:54
Is there a direct VapourSynth support for x264?

DJATOM
15th January 2021, 21:19
If you can apply patch and compile, my patch is here (https://github.com/DJATOM/x264-aMod-patches/blob/master/06-vpy-input.diff).

unix
16th January 2021, 07:17
I think I will stuck with ffmpeg because I'm not familiar with compile x264 ^^"
anyways I found a topic and I think it could help me https://forum.doom9.org/showthread.php?t=148615

Thank you

feisty2
16th January 2021, 15:21
@Myrsloik
what are some of the other things I need to do to make my project the preferred C++ wrapper for VS over vsxx?

Myrsloik
17th January 2021, 13:30
@Myrsloik
what are some of the other things I need to do to make my project the preferred C++ wrapper for VS over vsxx?

Find 3 people who prefer it I guess? I don't use either so I have no opinion about which one is better...

videoh
17th January 2021, 16:21
We don't need no steenkin' wrappers. Imagine having a bug in your filter and having to go to feisty2 for support. :rolleyes:

stax76
17th January 2021, 17:03
But it's pythonic and C++20, don't you like it?

videoh
17th January 2021, 17:42
I'm sure it's wonderful and great for noobs.

StainlessS
17th January 2021, 18:59
I'm sure that its lovely Feisty, Myrsloik and VideoH are just being, well themselves really :)

feisty2
17th January 2021, 19:34
Imagine having a bug in your filter and having to go to feisty2 for support. :rolleyes:
that is simply not true. the source code is publicly available and extremely easy to understand. anyone reasonably familiar with the C++ language should be able to manipulate the wrapper (adding more functionality, fixing bugs, etc.) however he or she wants with zero difficulty.

videoh
17th January 2021, 19:53
Where is the documentation for the wrapper?

Visual Studio solution files for building the examples?

feisty2
17th January 2021, 20:15
I'm sure it's wonderful and great for noobs.

also not true. the wrapper covers all functions provided by the C API, so anything you can do with the low level API, you can do the same with the C++ wrapper, plus the much cleaner and more concise syntax while also being less error prone. there is no performance cost (as long as you choose not to enable some dynamic features like automatic padding which are meant for fast prototyping), everything is built upon zero cost abstraction. even experienced developers should enjoy some benefits like RAII and expect less memory errors.

someone must be a masochist to prefer

auto std = vsapi->getPluginByNs("std", core);
auto args = vsapi->createMap();
vsapi->propSetNode(args, "clip", node, paAppend);
vsapi->freeNode(node);
auto ret = vsapi->invoke(std, "Transpose", args);
vsapi->freeMap(args);
node = vsapi->propGetNode(ret, "clip", 0, nullptr);
vsapi->freeMap(ret);


over


auto TransposedClip = Core["std"]["Transpose"]("clip", InputClip);

feisty2
17th January 2021, 20:54
Where is the documentation for the wrapper?

Visual Studio solution files for building the examples?

I haven't started working on documentation and I'll get started once all interface design is finalized. I have covered all functions in the C API but the filter backbone is still subject to change.

for now, you can find various examples here: https://github.com/IFeelBloated/vsFilterScript/tree/master/Examples

GaussBlur - simple 3x3 convolutional filter

TemporalMedian - a temporal filter

Rec601ToRGB - an example showing how to write filters that manipulate frame properties, and output a video clip of a different format than its input

Crop - an example showing how to write filters that deal with various bitdepths, and output a video clip with a different image size

ModifyFrame - an example showing how to write filters that interact with Python scripts.

Palette - an example showing how to write filters with multiple outputs

SeparableConvolution - an example showing how to write filters that invoke external filters and itself

GaussBlurFast - an example showing how to write filters without automatic padding.

msvc is not currently supported, because it lacks many core language features of C++20 (mainly concepts). you need at least GCC 10.2 to compile the examples

videoh
17th January 2021, 21:47
It's undocumented and I can't build with it or debug it in my development environment. I'm such a masochist for not using it. :rolleyes:

sl1pkn07
20th January 2021, 00:21
@videoh. is a joke?

> I can't build with it or debug it in my development environment.

maybe is your problem(?)

videoh
20th January 2021, 03:05
Because Visual Studio on Windows has such a tiny usage. I'm the only one that would be stupid enough to have such an environment.

Hey, he called me a masochist for not using his stuff. How about you mind your own business? Or how about you ask him to create some documentation, for God's sake?

The only joke here is the never-DG guys continually twisting themselves into pretzels. Pitiful.

feisty2
20th January 2021, 07:48
it's nobody's problem, msvc is well known to be slow on supporting new C++ features (it's also not the worst tho, apple clang is far worse than msvc in terms of C++20 support (https://en.cppreference.com/w/cpp/compiler_support/20)). things will get there eventually. the main problem with msvc currently is that it does not provide complete support for concepts, a major C++20 feature that the wrapper relies on heavily.

and the masochist thing is not personal, using the low level API not only requires more work to do the same thing, it is also very error prone in certain cases, especially when dealing with reference counted objects. you won't believe how easy and how likely it is to forget calling that "free" function marked in red in the following code block

auto std = vsapi->getPluginByNs("std", core);
auto args = vsapi->createMap();
vsapi->propSetNode(args, "clip", node, paAppend);
vsapi->freeNode(node); // manually releasing resource acquired in a foreign scope, highly error prone.
auto ret = vsapi->invoke(std, "Transpose", args);
vsapi->freeMap(args);
node = vsapi->propGetNode(ret, "clip", 0, nullptr);
vsapi->freeMap(ret);

and bang! there you have a memory leak. and that's what I meant by "masochist", to rely on the not always so consciously stable human willpower to deal with all that when you have the option to let a language facility do it automatically for you.

videoh
20th January 2021, 12:45
when you have the option to let a language facility do it automatically for you I don't have that option, and I can't wait for eventually.

And do yourself a favor and write some documentation. Examples are not enough.

foxyshadis
22nd January 2021, 06:28
it's nobody's problem, msvc is well known to be slow on supporting new C++ features (it's also not the worst tho, apple clang is far worse than msvc in terms of C++20 support (https://en.cppreference.com/w/cpp/compiler_support/20)). things will get there eventually. the main problem with msvc currently is that it does not provide complete support for concepts, a major C++20 feature that the wrapper relies on heavily.

You have to be kidding me, right? This is a bleeding edge GCC 10 feature. You need an Ubuntu line less than six months old to be able to use that, no 20.04 or LTS for you. There's still no RHEL/CentOS that has gcc10. You literally have to reinstall your entire OS to be able to build this, or have a dev environment just for it.

You're intentionally cutting your userbase off in order to experiment with bleeding edge features, which is fine in the abstract, but marks the project as unsuitable for anyone else.

feisty2
22nd January 2021, 11:22
the latest version of all 3 mainstream compilers (GCC, Clang, MSVC) have supported many C++20 features, both GCC and Clang have implemented full support for concepts, and MSVC has partial support for it. I can imagine that MSVC should be able to catch up in the following months and my project should work with all mainstream compilers by the time I finish writing the documentation. CentOS is dead so not supporting it is no big deal, regardless of that, GCC is capable of bootstrapping, just download the source code of the latest version and build it with whatever version you already have, you certainly don't need to reinstall your OS to run the latest version of GCC. what's the point really to use Linux if you can't even compile GCC from scratch...

concepts is a must-have in order to design a flexible interface in C++, it is by far the only facility to express type-level equivariance in C++, take the following polymorphic function f() for example:

auto f(auto&& x) {
if constexpr (requires { { x.g() }->Iterable; })
if constexpr (requires { { *x.g().begin() }->SubtypeOf<VideoInfo>; })
return std::vector<VideoNode>{};
else if constexpr (requires { { *x.g().begin() }->SubtypeOf<AudioInfo>; })
return std::vector<AudioNode>{};
else
static_assert(AlwaysFalse<decltype(x)>, "Type Error!");
else if constexpr (requires { { x.g() }->SubtypeOf<VideoInfo>; })
return VideoNode{};
else if constexpr (requires { { x.g() }->SubtypeOf<AudioInfo>; })
return AudioNode{};
else
static_assert(AlwaysFalse<decltype(x)>, "Type Error!");
}

the "if constexpr (requires { ... })" construct defines an equivariant map from the return type of x.g() to the return type of f(), and therefore extends polymorphism to the type level for f(). As a result, the user defined function x.g() no longer needs to be constrained by an invariant interface. the user is allowed to define g() however he/she likes at the type level, whatever works the best for his/her particular use case, and the framework function f() always self-adapts to whatever the user wants.

you simply cannot write such f() without concepts. you can try mimicking it using SFINAE in older versions of C++ and I guarantee that your code will be an unreadable and unmaintainable mess in no time. therefore concepts is absolutely essential if you agree that the user's freewill matters.

edit: simple proof that shows f() is indeed equivariant at the type level for types that it can handle.
let F() denote f() at the type level, [] denote a type operator that transforms any type T to std::vector<T>.

we have that:
F([VideoInfo]) = [VideoNode]
[F(VideoInfo)] = [VideoNode]
F([AudioInfo]) = [AudioNode]
[F(AudioInfo)] = [AudioNode]

therefore F() satisfies F(G∙T) = G∙F(T), where G = [], T = VideoInfo, AudioInfo.

_Al_
22nd January 2021, 20:09
Not that is important, but tried to subclass videonode, if for example could use custom attributes like clip.rgb, clip.isError etc:
class My_videonode(vs.VideoNode):
def __init__(self, clip, *args, **kwargs):
super(My_videonode, self).__init__(*args,**kwargs)

my_videonode = My_videonode(clip1)
got error, vapoursynth.Error: Class cannot be instantiated directly,
from here:
https://github.com/vapoursynth/vapoursynth/blob/master/src/cython/vapoursynth.pyx#L954

is it possible, or is it stupid idea, it could be done differently sure, or forget it?

feisty2
22nd January 2021, 20:13
use VaporMagik (https://github.com/IFeelBloated/VaporMagik), it allows you to do dangerous things to native extensions, not just VideoNode, you can even modify the behavior of built-in types like list or int

_Al_
22nd January 2021, 21:41
thank you,
I think I saw it before, really advanced script for me, thinking what it would be good for :-) . I tried to butcher it a bit and came up with this, which works. So I might use it. Interesting. I realized also I could also use collections.namedtuple lib, not sure how I would implement it yet. But your VaporMagik seams to be fun:

import ctypes
import builtins

class PyObject(ctypes.Structure):
pass

PyObject._fields_ = [
('ob_refcnt', ctypes.c_ssize_t),
('ob_type', ctypes.POINTER(PyObject)),
]

class NativeMappingProxy(PyObject):
_fields_ = [('UnderlyingDictionary', ctypes.POINTER(PyObject))]

def Dereference(Pointer):
ObjectHolder = []
ctypes.pythonapi.PyList_Append(ctypes.py_object(ObjectHolder), Pointer)
return ObjectHolder[0]

def ExposeAttributeDictionary(Type):
AttributeMaps = Type.__dict__
TransparentAttributeMaps = NativeMappingProxy.from_address(id(AttributeMaps))
return Dereference(TransparentAttributeMaps.UnderlyingDictionary)

def SetTypeAttribute(Type, Name, Attribute):
AttributeDictionary = ExposeAttributeDictionary(Type)
AttributeDictionary[Name] = Attribute
ctypes.pythonapi.PyType_Modified(ctypes.py_object(Type))

@property
def rgb(self):
return self.resize.Bicubic(format=vs.RGB24)

SetTypeAttribute(vs.VideoNode, 'rgb', rgb)


clip = core.avisource.AVISource(file.avi)
print(clip)
print(clip.rgb)

_Al_
22nd January 2021, 22:15
is it possible using VaporMagik to do get things out of tuple to atribute:
@property
def rgb(self):
#action of converting
return rgb_clip, isError, log #returned is vs.VideoNode, bool and string

#something:
SetTypeAttribute(vs.VideoNode, 'rgb', rgb)

clip = core.avisource.AVISource(file.avi)
print(clip)
print(clip.rgb)
print(clip.isError)
print(clip.log)
#or maybe better
print(clip.rgb)
print(clip.rgb.isError)
print(clip.rgb.log)
#or
print(clip.rgb[0], clip.rgb[1], clip.rgb[2])

feisty2
23rd January 2021, 07:20
I don't see why you'd think that you cannot do that, although what you're trying to do doesn't seem elegant to me.

_Al_
23rd January 2021, 09:00
ok, I got that, thanks, but then I could not figure out how to have array/list of clips done by that, that code is too much for me, I settled with something like this at the end:
import vapoursynth as vs
from vapoursynth import core
import collections

class Clips(list):
def __init__(self, inputs):
list.__init__(self,[])

self.Clip_data = collections.namedtuple('Clip_data', ['clip','rgb','isError','log','output_index'])

if isinstance(inputs, type(vs.get_outputs())):
inputs = [ (clip, output_index) for output_index, clip in inputs.items()]

elif isinstance(inputs, list):
inputs = [ (clip, None) for clip in inputs]
else:
raise ValueError('wrong input')
for clip, output_index in inputs:
self.append(self.set(clip, output_index))

def set(self, clip, output_index=None):
rgb, isError, log = self.toRGB(clip)
#other work
return self.Clip_data(clip=clip, rgb=rgb, isError=isError, log=log, output_index=output_index)

def replace(self, index, clip, output_index=None):
self[index] = self.set(clip, output_index)

def appending(self, clip, output_index=None):
self.append(self.set(clip, output_index))

def toRGB(self, c):
#conversion to rgb, mocking a return for show
return core.resize.Bicubic(c, matrix_in_s='170m',format=vs.RGB24), False, 'this is a conversion log'

vs.clear_outputs()
clip = core.std.BlankClip(format=vs.YUV420P8)
clip.set_output(0)

bright = clip.std.Expr(['x 40 +','',''])
bright.set_output(1)

clips = Clips([clip, bright])
##clips = Clips(vs.get_outputs())

print(clips[0].clip)
print(clips[0].rgb)
print(clips[0].log)
print(clips[1].clip)
#...

#replacing clip on index 1
brightest = clip.std.Expr(['x 100 +','',''])
clips.replace(1, brightest)

#apending clip
clip = core.std.BlankClip(color=(255,0,0)).resize.Point(matrix_s='170m',format=vs.YUV420P8)
clips.appending(clip)

feisty2
23rd January 2021, 12:39
but then I could not figure out how to have array/list of clips done by that

obviously, you need to inject your custom attributes into the built-in list type. use the @Inject decorator provided by VaporMagik


@Inject
def f(self: list):
for x in self:
print(x)

[1, 2, 3, 4].f() # prints "1 2 3 4"

_Al_
25th January 2021, 23:20
ok thanks, I used dataclass at the end, same syntax as namedtuple, I understand it, and it can assign and change attributes directly (namedtuple has awkward syntax). Not saying that VaporMagik cannot do that, most likely yes.

feisty2
27th January 2021, 07:12
@Myrsloik
could you explain how getFrame() is invoked with different activation reasons, particularly the case involving arAllFramesReady && !*frameData? it seems getFrame() might be invoked twice with the same activation reason, what happens after getFrame() exits from the arAllFramesReady && !*frameData branch and before it gets invoked again? if several frames (either from the same node or from several nodes) are requested in the arAllFramesReady && !*frameData branch, is it guaranteed that all requested frames are ready before the next call to getFrame()?

there seems to be 4 types of filters with different getFrame() skeletons:

standard filters
arInitial -> RequestReferenceFrames()
arAllFramesReady -> DrawFrame()

source filters
arInitial -> DrawFrame()

special filters (e.g. std.FrameEval)
arInitial -> RequestReferenceFrames()
arAllFramesReady && !*frameData -> RequestSpecialResources()
arAllFramesReady -> DrawFrame()

special(or weird?) source filters
arInitial && !*frameData -> RequestSpecialResources()
arInitial -> DrawFrame()

any other possibilities? also is it possible to get a concrete error message if the arError branch is activated?

Myrsloik
27th January 2021, 11:09
@Myrsloik
could you explain how getFrame() is invoked with different activation reasons, particularly the case involving arAllFramesReady && !*frameData? it seems getFrame() might be invoked twice with the same activation reason, what happens after getFrame() exits from the arAllFramesReady && !*frameData branch and before it gets invoked again? if several frames (either from the same node or from several nodes) are requested in the arAllFramesReady && !*frameData branch, is it guaranteed that all requested frames are ready before the next call to getFrame()?

there seems to be 4 types of filters with different getFrame() skeletons:

standard filters
arInitial -> RequestReferenceFrames()
arAllFramesReady -> DrawFrame()

source filters
arInitial -> DrawFrame()

special filters (e.g. std.FrameEval)
arInitial -> RequestReferenceFrames()
arAllFramesReady && !*frameData -> RequestSpecialResources()
arAllFramesReady -> DrawFrame()

special(or weird?) source filters
arInitial && !*frameData -> RequestSpecialResources()
arInitial -> DrawFrame()

any other possibilities? also is it possible to get a concrete error message if the arError branch is activated?

That's more or less the existing cases. Rule is very simple (ignore arFrameReady since it's effectively deprecated):

At the end of each invocation either an output frame must be returned OR there must be outstanding frame requests (requestFrameFilter).

First call is always arInitial to make things clear.
Once all requested frames are available arAllFramesReady is called.
You're allowed to request additional frames in arAllFramesReady which will then result in getting called with arAllFramesReady again and you can repeat this as many times as you like.
Errors may be propagated from other filters at any time after the arInitial call and then it's not the filter's job to handle it, only to clean up any allocated resources and return nothing. The error message is always propagated to the original requester to display. (As in whoever called getFrame/getFrameAsync)

Your last weird example is obviously invalid since it'll have outstanding frame requests when returning an output frame.

feisty2
27th January 2021, 12:51
Your last weird example is obviously invalid since it'll have outstanding frame requests when returning an output frame.


that's good to know. then apparently the last weird case and the standard case could be unified by generalizing RequestReferenceFrames() to RequestResources()


if (activationReason == arInitial)
if constexpr (requires { { filter->RequestResources() }->AnyBut<void>; })
*frameData = new auto{ filter->RequestResources() };
else if constexpr (requires { filter->RequestResources(); }) // fails to satisfy AnyBut<void>, therefore returns void, equivalent to RequestReferenceFrames()
filter->RequestResources();
else if constexpr (requires { { filter->DrawFrame() }->SubtypeOf<FrameReference>; }) // source filter
return filter->DrawFrame().Leak();
else
static_assert(AlwaysFalse<decltype(filter)>, "missing attribute!");

feisty2
28th January 2021, 07:49
what happens if there's no frame requested or generated in the arInitial branch (empty branch)? it might happen in rare cases like the following

if (activationReason == arInitial)
for (auto& node : inputs) // inputs might be an empty container depending on the user input
node.RequestFrame(n, FrameContext);

will getFrame() still be invoked with arAllFramesReady later on?

Myrsloik
28th January 2021, 09:59
what happens if there's no frame requested or generated in the arInitial branch (empty branch)? it might happen in rare cases like the following

if (activationReason == arInitial)
for (auto& node : inputs) // inputs might be an empty container depending on the user input
node.RequestFrame(n, FrameContext);

will getFrame() still be invoked with arAllFramesReady later on?

That's a fatal error since you either must have outstanding requests or return a frame.

lansing
1st February 2021, 04:39
How does the api getCoreInfo2() function works? It asks for the core and VSCoreInfo as parameters. But the only way to get the VSCoreInfo from the document is by using api->getCoreInfo(), but it also said that this function was deprecated.

feisty2
1st February 2021, 06:15
How does the api getCoreInfo2() function works? It asks for the core and VSCoreInfo as parameters. But the only way to get the VSCoreInfo from the document is by using api->getCoreInfo(), but it also said that this function was deprecated.

https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Core.vxx#L9

lansing
1st February 2021, 06:43
https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Core.vxx#L9

Thanks I got it working. The naming is confusing, this is more like setCoreInfo rather than getCoreInfo

feisty2
1st February 2021, 08:09
it's a common practice in C to return something via side effects (by manipulating global variables or modifying something from a foreign scope via pointers)

lansing
2nd February 2021, 01:46
Can I retrieve the paths for the vs plugin folder and script folder through the api?

feisty2
2nd February 2021, 05:27
plugin path: https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Plugin.vxx#L59
script path: https://github.com/IFeelBloated/VaporMagik/blob/master/VaporMagik.py#L71

Myrsloik
2nd February 2021, 11:52
Can I retrieve the paths for the vs plugin folder and script folder through the api?

The script "folder" isn't a single folder but simply all the normal python import paths. You can see vsrepo.py to see how it's determined by default I guess.

The "vs plugin folder" is also harder to determine. Basically you have 3 locations:
1. The core plugins
2. The global plugins
3. User plugins

The location of 2 is written to the registry and 3 is always in the same appdata location. Why do you even need to find out where things are?

lansing
2nd February 2021, 12:09
The script "folder" isn't a single folder but simply all the normal python import paths. You can see vsrepo.py to see how it's determined by default I guess.

The "vs plugin folder" is also harder to determine. Basically you have 3 locations:
1. The core plugins
2. The global plugins
3. User plugins

The location of 2 is written to the registry and 3 is always in the same appdata location. Why do you even need to find out where things are?
I want to create links in vseditor to open them in one click. Right now I’m relying on vsrepogui, but when vsrepogui didn’t work, it’ll be a pain to look for them manually.

ChaosKing
2nd February 2021, 12:28
For plugins http://www.vapoursynth.com/doc/plugins.html#windows
vsrepogui just uses the paths provided by vsrepo.

But registry can be tricky if the user has installed 32bit vapoursynth or it is a "per user installation".

I need to check 4 locations in vsrepogui to cover all cases.

var regl32 = new VsRegistry().GetRegistry(localKey32, @"SOFTWARE\VapourSynth-32");
var regl64 = new VsRegistry().GetRegistry(localKey64, @"SOFTWARE\VapourSynth");

var regu32 = new VsRegistry().GetRegistry(userKey32, @"SOFTWARE\VapourSynth-32");
var regu64 = new VsRegistry().GetRegistry(userKey64, @"SOFTWARE\VapourSynth");

localKey* => RegistryHive.LocalMachine
userKey* => RegistryHive.CurrentUser


EDIT
vsrepo code for scripts

https://github.com/vapoursynth/vsrepo/blob/efda91e3a4a57a400d403ee878e3489540886880/vsrepo.py#L186
import site
site_package_dir = site.getusersitepackages()

Which returns C:\Users\USER\AppData\Roaming\Python\Python38\site-packages

lansing
2nd February 2021, 13:21
User plugin should be all I need. I think I’ll just call vsrepo to open them.

Jukus
3rd February 2021, 19:57
How should such a video be indexed?
Format : AVI
Format/Info : Audio Video Interleave
Commercial name : DV
Format profile : OpenDML
Overall bit rate mode : Constant
Overall bit rate : 30 Mb/s

Video
ID : 0
Format : DV
Codec ID : dvsd
Codec ID/Hint : Sony
Bit rate mode : Constant
Width : 720 pixels
Height : 480 pixels
Display aspect ratio : 16:9
Frame rate mode : Constant
Frame rate : 29.970 (30000/1001) FPS
Original frame rate : 29.970 (29970/1000) FPS
Standard : NTSC
Color space : YUV
Chroma subsampling : 4:1:1
Bit depth : 8 bits
Scan type : Interlaced
Scan order : Bottom Field First
Compression mode : Lossy

stax76
3rd February 2021, 20:04
You can open that with ffms2 or L-Smash-Source.

LigH
3rd February 2021, 21:39
Disadvantage: Because it is a "keyframe only" video format, the index will be huge and indexing will take a lot of time.

poisondeathray
3rd February 2021, 21:47
If you're on windows, you can open it up with core.avisource.AVISource without indexing. Disadvantage - requires system installed DV codec and none that I know of return the original NTSC 4:1:1 .

feisty2
4th February 2021, 13:40
does anyone actually need half precision (fp16) facilities and does any plugin actually provide support for it? I don't really wanna have it in my project and I have very good reasons:

1) there's no native support for fp16 in standard C/C++ and most CPUs provide very little or no support for it, meaning you will have to create your homegrown software-emulated fp16 type. it's not portable and it's very likely that it will be way slower than fp32 which comes with native hardware support.

2) unlike fp32 and fp64 which are universally well defined (literally every implementation out there adopts the representation defined by IEEE 754), the representation of fp16 varies on different platforms. there's the IEEE fp16, and BFloat16 (Google TPU), and who knows what else! applying arithmetic operations defined for one fp16 representation on another fp16 representation leads to garbage result. The user (or maybe even the developer) usually has absolutely no clue which fp16 representation is being used and all sorts of weird shit can happen. It might be better to avoid all this by simply not supporting fp16.

Myrsloik
4th February 2021, 13:44
does anyone actually need half precision (fp16) facilities and does any plugin actually provide support for it? I don't really wanna have it in my project and I have very good reasons:

1) there's no native support for fp16 in standard C/C++ and most CPUs provide very little or no support for it, meaning you will have to create your homegrown software-emulated fp16 type. it's not portable and it's very likely that it will be way slower than fp32 which comes with native hardware support.

2) unlike fp32 and fp64 which are universally well defined (literally every implementation out there adopts the representation defined by IEEE 754), the representation of fp16 varies on different platforms. there's the IEEE fp16, and BFloat16 (Google TPU), and who knows what else! applying arithmetic operations defined for one fp16 representation on another fp16 representation leads to garbage result. The user (or maybe even the developer) usually has absolutely no clue which fp16 representation is being used and all sorts of weird shit can happen. It might be better to avoid all this by simply not supporting fp16.

1. That's not how you do it. You use the unpack/pack instructions for fp16 for load and store and then feed that to the normal fp32 path. It's the only way to make it perform well.

2. Obviously it's whatever the cpu native fp16 format is, just like with other floats. So IEEE all the way on x86 (and just about all sane cpus).

Support is mostly pointless.

Jukus
4th February 2021, 17:46
Disadvantage: Because it is a "keyframe only" video format, the index will be huge and indexing will take a lot of time.
The file weighs over 30 gb
Duration over 02:30:00
The size of the ffms index is 50+ kb

lansing
5th February 2021, 11:16
What function do I use to retrieve warning message from the api? If I run a script with clip = core.get_core() in PyCharm it'll give me a nice deprecated warning, but in vseditor I couldn't find a function that can do that. the getError() only return on fatal error like frame failed to load.

feisty2
5th February 2021, 11:26
https://github.com/vapoursynth/vapoursynth/blob/doodle1/src/cython/vapoursynth.pyx#L2337
it has nothing to do with VS per se. you just have to find a way to utilize python's warnings module in your application.

LigH
5th February 2021, 23:12
@Jukus: OK, maybe it's worse with uncompressed audio. My memories may be not completely correct in this case.

lansing
6th February 2021, 01:36
https://github.com/vapoursynth/vapoursynth/blob/doodle1/src/cython/vapoursynth.pyx#L2337
it has nothing to do with VS per se. you just have to find a way to utilize python's warnings module in your application.

I don't really know what to do. Maybe like embedding Python into my vseditor project and then have it evaluate the script so I can catch the warning?

feisty2
6th February 2021, 08:20
you can use vaporsynth's FFI facilities to execute arbitrary python code in your C++ programs. you need to:
1) define a python function that does what you want, in this case, the function should collect all warning messages from warnings and return them as a list of strings.
2) pass the function to a special filter and execute it, in this case, you can instantly execute the acquired function in your filter's constructor, then call Core.Alert() to send all warning messages to console.

lansing
6th February 2021, 17:18
you can use vaporsynth's FFI facilities to execute arbitrary python code in your C++ programs. you need to:
1) define a python function that does what you want, in this case, the function should collect all warning messages from warnings and return them as a list of strings.
2) pass the function to a special filter and execute it, in this case, you can instantly execute the acquired function in your filter's constructor, then call Core.Alert() to send all warning messages to console.

What is vaporsynth's FFI facilities?

feisty2
6th February 2021, 17:40
What is vaporsynth's FFI facilities?

https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Function.vxx

and use it to run python code thru a special filter

struct PythonEval {
static constexpr auto Name = "PythonEval";
static constexpr auto Signature = "code:func;";

PythonEval(auto Arguments, auto Core) {
for (auto PythonCode = static_cast<Function>(Arguments["code"]); auto&& WarningMessage : PythonCode())
Core.Alert(static_cast<std::string>(WarningMessage));
}
};

lansing
7th February 2021, 07:51
This is what I found to catch the warnings:


import warnings

with warnings.catch_warnings(record=True) as warning_list:
core = vs.get_core()
clip = core.dgdecodenv.DGSource(r'hello.dgi')
clip.set_output()

for warning in warning_list:
print(warning.message)


But I need to wrap the whole script inside this warnings.catch_warnings in order to catch them.

feisty2
7th February 2021, 08:32
But I need to wrap the whole script inside this warnings.catch_warnings in order to catch them.

no need.


import logging

class MessageAbsorber(logging.Handler):
def __init__(self, MessageContainer):
logging.Handler.__init__(self)
self.MessageContainer = MessageContainer
def emit(self, MessageRecord):
self.MessageContainer += [MessageRecord.getMessage()]

WarningMessages = []
logging.captureWarnings(True)
logging.getLogger('py.warnings').addHandler(MessageAbsorber(WarningMessages))

def PassWarningMessagesToCxxPrograms():
return WarningMessages

# user script goes here

core.vsedit.PythonEval(PassWarningMessagesToCxxPrograms)

lansing
8th February 2021, 06:34
no need.


import logging

class MessageAbsorber(logging.Handler):
def __init__(self, MessageContainer):
logging.Handler.__init__(self)
self.MessageContainer = MessageContainer
def emit(self, MessageRecord):
self.MessageContainer += [MessageRecord.getMessage()]

WarningMessages = []
logging.captureWarnings(True)
logging.getLogger('py.warnings').addHandler(MessageAbsorber(WarningMessages))

def PassWarningMessagesToCxxPrograms():
return WarningMessages

# user script goes here

core.vsedit.PythonEval(PassWarningMessagesToCxxPrograms)

I came to understand the logging part after some reading, but I still don't get the last line, what is this PythonEval() and how does it talk to C++?

The script will be pass to vsscript_evaluateScript(), which doesn't return warning messages. Where do this PythonEval() play in the process?

feisty2
8th February 2021, 07:29
PythonEval() is a special C++ filter that takes a python function as its argument and returns nothing. it's somewhat similar to std.LoadPlugin() or std.SetMaxCPU() in terms of functionality (an infrastructure function rather than an actual filter that applies some processing to a video clip). its implementation should be something similar to #4274, basically it retrieves the warning messages by calling the foreign python function and sends all retrieved messages to stderr thru vsapi->logMessage()

lansing
8th February 2021, 09:49
PythonEval() is a special C++ filter that takes a python function as its argument and returns nothing. it's somewhat similar to std.LoadPlugin() or std.SetMaxCPU() in terms of functionality (an infrastructure function rather than an actual filter that applies some processing to a video clip). its implementation should be something similar to #4274, basically it retrieves the warning messages by calling the foreign python function and sends all retrieved messages to stderr thru vsapi->logMessage()

If I get this right, you're saying to create a dummy vs filter to sends the collected messages through stdder, and then in the C++ side, retrieve the messages through stdder and then output them with vsapi->logMessage()?

feisty2
8th February 2021, 10:02
no, it sends the collected messages TO stderr BY USING vsapi->logMessage(), read the documentation of vaporsynth's C API. any string passed to logMessage() already automatically appears in vsedit, you don't need any extra stuff.

lansing
8th February 2021, 10:18
no, it sends the collected messages TO stderr BY USING vsapi->logMessage(), read the documentation of vaporsynth's C API. any string passed to logMessage() already automatically appears in vsedit, you don't need any extra stuff.

So the chain would be like this?

collected messages -> dummy vs filter -> inside dummy vs filter -> logMessage()

feisty2
8th February 2021, 10:20
yes,,,

lansing
8th February 2021, 10:31
yes,,,

Thanks, I'll work on it.

feisty2
10th February 2021, 10:34
@Myrsloik
should I release *frameData instantly if an exception is thrown from the arAllFramesReady branch? or should I just leave it unhandled and expect it gets deleted when getFrame() is invoked again with arError?

basically, this

try {
if (auto& ResourceHandle = reinterpret_cast<ResourceType*&>(*frameData); activationReason == arInitial)
ResourceHandle = new auto{ FilterInstance->AcquireResources(...) };
else if (activationReason == arAllFramesReady) {
auto ManagedResourceHandle = std::unique_ptr<ResourceType>{ ResourceHandle };
auto GeneratedFrame = FilterInstance->DrawFrame(*ManagedResourceHandle, ...);
// if DrawFrame() throws an exception, *ResourceHandle is instantly released
// by the destructor of std::unique_ptr

return GeneratedFrame.ReleaseOwnership();
}
else if (activationReason == arError)
delete ResourceHandle;
// possible double-free here?

return nullptr;
}
catch (RuntimeError& ErrorMessage) {
FrameContext.RaiseError(ErrorMessage);
return nullptr;
}

or this

try {
if (auto& ResourceHandle = reinterpret_cast<ResourceType*&>(*frameData); activationReason == arInitial)
ResourceHandle = new auto{ FilterInstance->AcquireResources(...) };
else if (activationReason == arAllFramesReady) {
auto GeneratedFrame = FilterInstance->DrawFrame(*ResourceHandle, ...);
// no leak if DrawFrame() throws an exception
// *ResourceHandle will be released later from the arError branch

delete ResourceHandle;
return GeneratedFrame.ReleaseOwnership();
}
else if (activationReason == arError)
delete ResourceHandle;
return nullptr;
}
catch (RuntimeError& ErrorMessage) {
FrameContext.RaiseError(ErrorMessage);
return nullptr;
}

?

Myrsloik
10th February 2021, 10:39
@Myrsloik
should I release *frameData instantly if an exception is thrown from the arAllFramesReady branch? or should I just leave it unhandled and expect it gets deleted when getFrame() is invoked again with arError?

basically, this
...
?

You can't get an "exception" or error in arAllFramesReady. All frames are already successfully produced so I'm not sure what you're asking. And if there is an error arAllFramesReady won't be called, only arError, so obviously you should free the frameData there.

feisty2
10th February 2021, 10:49
the exception is thrown from the user defined function DrawFrame() when for instance, a required frame property is missing from the input (basically any situation that involves setFilterError() in a C plugin).

feisty2
10th February 2021, 11:02
oh I see, I think I kinda get it now, so arError indicates error getting an input frame, not error in an attempt to generate an output frame, is that right?

Myrsloik
10th February 2021, 11:22
oh I see, I think I kinda get it now, so arError indicates error getting an input frame, not error in an attempt to generate an output frame, is that right?

Exactly!

lansing
11th February 2021, 07:32
Thanks, I'll work on it.

I have created a dummy filter and passed in a list from the script to the filter, but I couldn't figure out the right syntax to retrieve it in C.

script
core.vsedit.Logger(["message 1", "message 2"])

dummy.c

static void VS_CC logger(VSMap* in, VSMap* out, void *userData, VSCore* core, const VSAPI* vsapi) {
char messages[] = vsapi->propGetData(in, "name", 0, NULL);

int i = 0;
while (messages[i]) {
vsapi->logMessage("WARNING", messages[i]);
i++;
}
}

VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc, VSRegisterFunction registerFunc, VSPlugin* plugin) {
configFunc("com.vsedit.logger", "vsedit", "VapourSynth Logger", VAPOURSYNTH_API_VERSION, 1, plugin);
registerFunc("Logger", "name:data[]", &logger, 0, plugin);
}


I couldn't get this to compile.

feisty2
11th February 2021, 09:06
auto logger(auto in, auto, auto, auto, auto vsapi) {
for (auto x : Range{ vsapi->propNumElements(in, "name") })
vsapi->logMessage(VSMessageType::mtWarning, vsapi->propGetData(in, "name", x, nullptr));
}

feisty2
11th February 2021, 09:28
char messages[] = vsapi->propGetData(in, "name", 0, NULL);


apparently you're not very familiar with C constructs, you cannot initialize a char array from a pointer (note that string literals are of type const char[N], not const char*, an array type can decay to a pointer type, but arrays and pointers are distinct entities). it's better if you just avoid C stuff all together.

lansing
11th February 2021, 09:44
apparently you're not very familiar with C constructs, you cannot initialize a char array from a pointer (note that string literals are of type const char[N], not const char*, an array type can decay to a pointer type, but arrays and pointers are distinct entities). it's better if you just avoid C stuff all together.

Yes C is confusing to me, it gave me a headache even trying to do simple thing like converting int to string.

lansing
11th February 2021, 17:07
I got the dummy filter printing messages now, but for some reason the logging module is not catching warnings on evaluation


import logging

class MessageAbsorber(logging.Handler):
def __init__(self, message_container):
logging.Handler.__init__(self)
self.messageContainer = message_container
def emit(self, message_record):
self.messageContainer += [message_record.getMessage()]

WarningMessages = []
logging.captureWarnings(True)
logging.getLogger('py.warnings').addHandler(MessageAbsorber(WarningMessages))

def get_warnings():
return WarningMessages

import vapoursynth as vs

core = vs.get_core()
core2 = vs.get_core()
core3 = vs.get_core()
clip = core.dgdecodenv.DGSource(r'video.dgi')
clip.set_output()

core.vsedit.Logger(get_warnings())

The same codes worked on PyCharm, but in vseditor, I'm getting error about the WarningMessages list still being empty. It will print if I passed in a list core.vsedit.Logger(["message1", "message2"])

Update: I think the reason for this is because vs disabled the warnings so they aren't even logged.

feisty2
12th February 2021, 13:20
@Myrsloik
Does the flags field of the VSVideoInfo object passed to setVideoInfo() partially determine the cache mode of the output node (along with the flags argument passed to createFilter()), or is it simply ignored?

Myrsloik
12th February 2021, 13:27
@Myrsloik
Does the flags field of the VSVideoInfo object passed to setVideoInfo() partially determine the cache mode of the output node (along with the flags argument passed to createFilter()), or is it simply ignored?

It's simply ignored and is filled out with the flags passed to createFilter()

lansing
18th February 2021, 03:02
What is the correct scenario for use of setting max cache size? I have a 1080i source with QTGMC(Preset='Medium'), setting max cache size to 4000 MB will give me a "script exceeded memory limit" warning, raising it to 12,000 MB will clear the warning, but there is no difference in speed on benchmark at 41 fps.

feisty2
23rd February 2021, 12:29
I got the dummy filter printing messages now, but for some reason the logging module is not catching warnings on evaluation

The same codes worked on PyCharm, but in vseditor, I'm getting error about the WarningMessages list still being empty. It will print if I passed in a list core.vsedit.Logger(["message1", "message2"])

Update: I think the reason for this is because vs disabled the warnings so they aren't even logged.

add these 2 lines

import logging
import warnings

class MessageAbsorber(logging.Handler):
def __init__(self, MessageContainer):
logging.Handler.__init__(self)
self.MessageContainer = MessageContainer
def emit(self, MessageRecord):
self.MessageContainer += [MessageRecord.getMessage()]

WarningMessages = []
warnings.simplefilter('always')
logging.captureWarnings(True)
logging.getLogger('py.warnings').addHandler(MessageAbsorber(WarningMessages))

# user script goes here

core.vsedit.PrintWarnings(WarningMessages)

feisty2
28th February 2021, 17:44
@Myrsloik
could you add

const char* getPluginName(VSPlugin*);
const char* getPluginNamespace(VSPlugin*);
const char* getPluginIdentifier(VSPlugin*);
const char* getPluginFunctionArguments(VSPlugin*, const char* functionName);

to APIv3? so the instantiation of a single plugin object or plugin func object can get rid of the super expensive getPlugins() or getFunctions()

Jukus
8th March 2021, 20:44
I got some strange BD with almost 100 m2ts files and they are not in chronological order.
Is there any way to parse such a disc for VS?

ChaosKing
8th March 2021, 21:47
Maybe this mpls reader can help https://github.com/HomeOfVapourSynthEvolution/VapourSynth-ReadMpls

videoh
8th March 2021, 22:10
I got some strange BD with almost 100 m2ts files and they are not in chronological order.
Is there any way to parse such a disc for VS? One option: DGDecNV.

BTW, that's not so strange. It's quite common. For example, MONSTERS_UNIVERSITY has 154 M2TS files.

feisty2
11th March 2021, 11:56
it seems that nfNoCache is now the only node flag in API v4, has nfMakeLinear been replaced by std.Cache(make_linear = True)?
are fmFrameState (API v4) and fmSerial (API v3) the same thing?

Myrsloik
11th March 2021, 12:47
it seems that nfNoCache is now the only node flag in API v4, has nfMakeLinear been replaced by std.Cache(make_linear = True)?
are fmFrameState (API v4) and fmSerial (API v3) the same thing?

Yes, you have to add a cache with std.Cache(make_linear = True) yourself. Preferably inside the filter constructor that needs it.

fmFrameState and fmSerial are still separate things.

feisty2
11th March 2021, 13:07
fmFrameState and fmSerial are still separate things.

so fmSerial has been removed in API v4, could you elaborate on how they are different?

Myrsloik
11th March 2021, 13:36
so fmSerial has been removed in API v4, could you elaborate on how they are different?

Never mind, fmFrameState = fmSerial. I renamed it so people won't think it makes frame accesses more linear which is a common confusion.

Selur
13th March 2021, 00:53
Got a question:
In case it use SelectEvery to split a clip into two clips:
clipA = core.std.SelectEvery(clip=clip, cycle=5, offsets=[0 3 4])
clipB = core.std.SelectEvery(clip=clip, cycle=5, offsets=[1 2])
(no frames get lost or are present in both clips)
and apply some additional filters to those clips, how can I weave those two clips properly together again?
Is there some sort of advanced Interleave which I could use with the offsets I used before.

Alternatively: How can I apply a filter only to specific frames which follow a pattern (given by cycle and offsets)?

Cu Selur

Ps.: may be using https://github.com/Irrational-Encoding-Wizardry/Vapoursynth-RemapFrames ?

poisondeathray
13th March 2021, 02:09
Got a question:
In case it use SelectEvery to split a clip into two clips:
clipA = core.std.SelectEvery(clip=clip, cycle=5, offsets=[0 3 4])
clipB = core.std.SelectEvery(clip=clip, cycle=5, offsets=[1 2])
(no frames get lost or are present in both clips)
and apply some additional filters to those clips, how can I weave those two clips properly together again?
Is there some sort of advanced Interleave which I could use with the offsets I used before.

Alternatively: How can I apply a filter only to specific frames which follow a pattern (given by cycle and offsets)?

Cu Selur

Ps.: may be using https://github.com/Irrational-Encoding-Wizardry/Vapoursynth-RemapFrames ?



Or ugly "old fashioned" way


clipA = core.std.SelectEvery(clip, cycle=5, offsets=[0, 3, 4])
clipB = core.std.SelectEvery(clip, cycle=5, offsets=[1, 2])

clipA0 = core.std.SelectEvery(clipA, cycle=3, offsets=[0])
clipA3 = core.std.SelectEvery(clipA, cycle=3, offsets=[1])
clipA4 = core.std.SelectEvery(clipA, cycle=3, offsets=[2])

clipB1 = core.std.SelectEvery(clipB, cycle=2, offsets=[0])
clipB2 = core.std.SelectEvery(clipB, cycle=2, offsets=[1])

int = core.std.Interleave(clips=[clipA0,clipB1,clipB2,clipA3,clipA4])

Selur
13th March 2021, 10:23
Or ugly "old fashioned" way
What's the other alternative? I don't see how I could use RemapFrames for this,...

Cu Selur

feisty2
13th March 2021, 17:08
for any m < n, is it guaranteed that VS will only call getFrame(n, arAllFramesReady) after getFrame(m, arAllFramesReady) has completed for fmParallelRequests, fmUnordered and fmSerial?

Myrsloik
13th March 2021, 23:53
for any m < n, is it guaranteed that VS will only call getFrame(n, arAllFramesReady) after getFrame(m, arAllFramesReady) has completed for fmParallelRequests, fmUnordered and fmSerial?

Nope. There's no api guarantee at all for order. There is however an internal tag that keeps track of the request number and takes it into consideration when scheduling things so most of the time things will be kinda in order.

_Al_
14th March 2021, 02:30
How can I apply a filter only to specific frames which follow a pattern (given by cycle and offsets)?
what comes to mind is to use Python, same as if you'd code something, as if coding in Python
import vapoursynth as vs
from vapoursynth import core
clip = core.std.BlankClip(format=vs.YUV420P8, color =(100,128,128))

def bright(clip):
return clip.std.Expr(["x 40 +","",""])

def dark(clip):
return clip.std.Expr(["x 40 -","",""])

DISTRIBUTE_FILTER = {
0: bright,
1: dark,
2: dark,
3: bright,
4: bright,
}

clip_out = clip.std.FrameEval(lambda n: DISTRIBUTE_FILTER[n % len(DISTRIBUTE_FILTER)](clip))
clip_out.set_output()
to use lambda could be overwhelming so to call a function from FrameEval():

import functools
def distribute_filter(n,clip=clip):
return DISTRIBUTE_FILTER[n % len(DISTRIBUTE_FILTER)](clip)
clip_out = core.std.FrameEval(clip, functools.partial(distribute_filter,clip=clip))

AOmundson
15th March 2021, 01:46
I'm attempting to decomb a video clip using TDeintMod (https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod), but it keeps outputting an error that I have no idea how to solve.

Script:
import vapoursynth as vs
core = vs.get_core()
core.max_cache_size = 32768

clip = r'D:\Video\1.mkv' #replace with your video file

def conditionalDeint(n, f, orig, deint):
if f.props['_Combed']:
return deint
else:
return orig

deint = core.tdm.TDeintMod(clip, order=1, edeint=core.nnedi3.nnedi3(clip, field=1))
combProps = core.tdm.IsCombed(clip)
clip = core.std.FrameEval(clip, functools.partial(conditionalDeint, orig=clip, deint=deint), combProps)

clip.set_output()

Error Message:

2021-03-14 19:43:13.737
Failed to evaluate the script:
Python exception: nnedi3: argument clip was passed an unsupported type (expected clip compatible type but got str)

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2244, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 2245, in vapoursynth.vpy_evaluateScript
File "E:\VapourSynthEditor\Decomb.vpy", line 13, in
deint = core.tdm.TDeintMod(clip, order=1, edeint=core.nnedi3.nnedi3(clip, field=1))
File "src\cython\vapoursynth.pyx", line 2056, in vapoursynth.Function.__call__
vapoursynth.Error: nnedi3: argument clip was passed an unsupported type (expected clip compatible type but got str)

poisondeathray
15th March 2021, 02:13
I'm attempting to decomb a video clip using TDeintMod (https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod), but it keeps outputting an error that I have no idea how to solve.

Script:
import vapoursynth as vs
core = vs.get_core()
core.max_cache_size = 32768

clip = r'D:\Video\1.mkv' #replace with your video file

def conditionalDeint(n, f, orig, deint):
if f.props['_Combed']:
return deint
else:
return orig

deint = core.tdm.TDeintMod(clip, order=1, edeint=core.nnedi3.nnedi3(clip, field=1))
combProps = core.tdm.IsCombed(clip)
clip = core.std.FrameEval(clip, functools.partial(conditionalDeint, orig=clip, deint=deint), combProps)

clip.set_output()

Error Message:

2021-03-14 19:43:13.737
Failed to evaluate the script:
Python exception: nnedi3: argument clip was passed an unsupported type (expected clip compatible type but got str)

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2244, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 2245, in vapoursynth.vpy_evaluateScript
File "E:\VapourSynthEditor\Decomb.vpy", line 13, in
deint = core.tdm.TDeintMod(clip, order=1, edeint=core.nnedi3.nnedi3(clip, field=1))
File "src\cython\vapoursynth.pyx", line 2056, in vapoursynth.Function.__call__
vapoursynth.Error: nnedi3: argument clip was passed an unsupported type (expected clip compatible type but got str)


Did you load the video with a source filter?


clip = r'D:\Video\1.mkv' #replace with your video file


should be something like this

clip = core.lsmas.LWLibavSource(r'D:\Video\1.mkv')

AOmundson
15th March 2021, 03:13
Did you load the video with a source filter?


clip = r'D:\Video\1.mkv' #replace with your video file


should be something like this

clip = core.lsmas.LWLibavSource(r'D:\Video\1.mkv')


Thanks, that fixed that error, but I'm currently suffering another one.


2021-03-14 21:12:32.715
Failed to evaluate the script:
Python exception: lsmas: failed to construct index.

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2244, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 2245, in vapoursynth.vpy_evaluateScript
File "E:\VapourSynthEditor\Decomb.vpy", line 6, in
clip = core.lsmas.LWLibavSource(clip)
File "src\cython\vapoursynth.pyx", line 2069, in vapoursynth.Function.__call__
vapoursynth.Error: lsmas: failed to construct index.


On that note, would you recommend FFmpeg or LSMASH for de-combing cartoons/anime without creating new combing lines?

poisondeathray
15th March 2021, 03:32
Thanks, that fixed that error, but I'm currently suffering another one.


2021-03-14 21:12:32.715
Failed to evaluate the script:
Python exception: lsmas: failed to construct index.

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2244, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 2245, in vapoursynth.vpy_evaluateScript
File "E:\VapourSynthEditor\Decomb.vpy", line 6, in
clip = core.lsmas.LWLibavSource(clip)
File "src\cython\vapoursynth.pyx", line 2069, in vapoursynth.Function.__call__
vapoursynth.Error: lsmas: failed to construct index.


On that note, would you recommend FFmpeg or LSMASH for de-combing cartoons/anime without creating new combing lines?


Did you get the path correct ?

Are you using recent LSmash version ?

Personally, I would use neither for a DVD source. DGSource if you have a Nvidia card and license, or DGDecode / d2v.Source are more reliable

AOmundson
15th March 2021, 03:46
Did you get the path correct ?

Are you using recent LSmash version ?

Personally, I would use neither for a DVD source. DGSource if you have a Nvidia card and license, or DGDecode / d2v.Source are more reliable

Thanks, I've got it working now. When you say to use DGSource/DGDecode instead of LSmash/FFmpeg, how would I go about implementing that? i.e. What DLLs would I need to download for the VS plugin folder, how should I write the code line in the editor itself, and what should I place in the Header, Executable, and Arguments boxes?

LessThanJake
19th March 2021, 10:21
I have installed VapourSynth via installer (VapourSynth64-R52.exe (https://github.com/vapoursynth/vapoursynth/releases)).

print(core.version()) for system wide python install says:
VapourSynth Video Processing Library
Copyright (c) 2012-2020 Fredrik Mellbin
Core R52
API R3.6
Options: -

If I create my own environment and add Vapoursynth via "pip install vapoursynth" says:
print(core.version())
VapourSynth Video Processing Library
Copyright (c) 2012-2020 Fredrik Mellbin
Core R51
API R3.6
Options: -

Documentation says:
https://i.imgur.com/CglX0nd.png

If installation via pip requires installation of VapourSynth beforehand I assume it referes to the global install (R52) but it says R51.
So what version do I actually have when using pip in my own env and does it matter that it only shows R51 and can s.o. update PyPi to R52 that it matches again?

Thanks :)

jinkazuya
23rd March 2021, 00:34
I am just wondering how to use the script here https://github.com/Selur/VapoursynthScriptsInHybrid/blob/master/G41Fun.py#L2885
if I use vapoursynth? I do not know what to do with it. Thanks and hope somebody could help. I would like to use the script or plugin of the detailsharpen.

vxzms
23rd March 2021, 01:19
I am just wondering how to use the script here https://github.com/Selur/VapoursynthScriptsInHybrid/blob/master/G41Fun.py#L2885
if I use vapoursynth? I do not know what to do with it. Thanks and hope somebody could help. I would like to use the script or plugin of the detailsharpen.



import vapoursynth as vs
from vapoursynth import core
import G41Fun

src = core.lsmas.LWLibavSource(clip)
dsharped = G41Fun.DetailSharpen(src, z=4, sstr=1.5, power=4, ldmp=1, mode=1, med=False)

dsharped.set_output()

jinkazuya
23rd March 2021, 03:11
import vapoursynth as vs
from vapoursynth import core
import G41Fun

src = core.lsmas.LWLibavSource(clip)
dsharped = G41Fun.DetailSharpen(src, z=4, sstr=1.5, power=4, ldmp=1, mode=1, med=False)

dsharped.set_output()



Thanks but how to use it with staxrip and what is the procedure of using it. Since it is the script of python, I do not know how to use it.

monohouse
23rd March 2021, 05:23
I have some problem with MakeDiff in versions 50,51,52 :x
Script evaluation failed:
Python exception: MakeDiff: both clips must have constant format and dimensions, and the same format and dimensions

Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 2244, in vapoursynth.vpy_evaluateScript
File "src/cython/vapoursynth.pyx", line 2245, in vapoursynth.vpy_evaluateScript
File "/mnt/dod/04.vpy", line 11, in <module>
clip = haf.QTGMC(clip, TFF=True, Preset="Placebo", ShowSettings=False, opencl=False, device=0, TR0=2, TR1=2, SourceMatch=0, TR2=0, Lossless=0, Sharpness=0 )
File "/usr/lib/python3.6/site-packages/havsfunc.py", line 1281, in QTGMC
noise = core.std.MakeDiff(clip, denoised, planes=CNplanes)
File "src/cython/vapoursynth.pyx", line 2069, in vapoursynth.Function.__call__
vapoursynth.Error: MakeDiff: both clips must have constant format and dimensions, and the same format and dimensions

linux, all compiled today, used LD_PRELOAD to test for plugin errors and there are none, without QTGMC the script works, latest mvsfunc and havsfunc

import vapoursynth as vs
import havsfunc as haf

core = vs.get_core()
core.set_max_cache_size(16000)

clip = core.ffms2.Source("//mnt//dod//movie.mkv")
clip = core.fmtc.bitdepth (clip, bits=16, fulls=False, fulld=True, dmode=1)
clip = haf.QTGMC(clip, TFF=True, Preset="Placebo", ShowSettings=False, opencl=False, device=0, TR0=2, TR1=2, SourceMatch=0, TR2=0, Lossless=0, Sharpness=0 )
clip = haf.MCTemporalDenoise(clip, radius=3, limit=2, twopass=False, limit2=2, refine=True, useTTmpSm=True, stabilize=False, maxr=3, TTstr=3, chroma=False, MVsharp=False, sigma=0, pfMode=-1,search=3, searchparam=4, pel=4, pelsearch=4, bwbh=512, owoh=256, blksize=4, overlap=2, deblock=False, post=0,bt=4,thSAD=2000, thSAD2=2000, thSCD1=1000, thSCD2=200)
clip = core.deblock.Deblock(clip, quant=20, aoffset=0, boffset=0)
clip = core.fmtc.bitdepth (clip, bits=10, fulls=True, fulld=True, dmode=1)
clip.set_output()

tested several older versions of havsfunc no change :x
I removed this code from src/core/mergefilters.c and it started working fine and the video looks correct
if (!isConstantFormat(d.vi) || !isSameFormat(d.vi, vsapi->getVideoInfo(d.node2))) {
vsapi->freeNode(d.node1);
vsapi->freeNode(d.node2);
RETERROR("MakeDiff: both clips must have constant format and dimensions, and the same format and dimensions");
}

strange problem

LigH
23rd March 2021, 15:02
Thanks but how to use it with staxrip and what is the procedure of using it. Since it is the script of python, I do not know how to use it.

First a question to stax76 ... does StaxRip support VapourSynth filters at all, as selectable filter? Probably not easily, because StaxRip builds AviSynth scripts. I don't think you can simply mix both worlds.

Or maybe I'm wrong. I noticed that StaxRip x64 ships both frameservers. But how to select either or mix both, may be better asked in his own thread about StaxRip (https://forum.doom9.org/showthread.php?t=172068).

stax76
23rd March 2021, 16:15
@LigH

I've expected a little more competence from somebody like you ... , right-click filters and choose:

Filter Setup > VapourSynth

After that:

File > Save Project As Template > Load template on startup

Vapoursynth is now your default frame server ready to use in staxrip, it currently has 60 vapoursynth plugins included, most of them with presets available in an easy-to-use menu.

https://github.com/staxrip/staxrip/wiki/Tools

jinkazuya
23rd March 2021, 17:46
@LigH

I've expected a little more competence from somebody like you ... , right-click filters and choose:

Filter Setup > VapourSynth

After that:

File > Save Project As Template > Load template on startup

Vapoursynth is now your default frame server ready to use in staxrip, it currently has 60 vapoursynth plugins included, most of them with presets available in an easy-to-use menu.

https://github.com/staxrip/staxrip/wiki/Tools

Hi stax76, would that be ok for you to include the plugin for Detailsharpen in the future release? I greatly appreciate. Staxrip is a pretty good application or program but I used to use MEGUI and now MEGUI and Avisynth+ become a bit complicated and none of the script that I used work and the encoding always throw exception when it is halfway done. But using scripts with staxrip is a little bit complicated to newbies or beginners. I hope staxrip could integrate a bit more plugins by default in the future esp I would like to use my beloved detailsharpen. Thanks a lot.

ChaosKing
23rd March 2021, 17:55
It seems it is aready included https://github.com/staxrip/staxrip/wiki/Tools#g41fun

stax76
23rd March 2021, 18:37
@jinkazuya

Yes, it appears it was included by an ex maintainer, but it might not be available in the menu, for that there is documentation here:

https://github.com/staxrip/staxrip/wiki/Usage#video-processing

https://github.com/staxrip/staxrip/wiki/How-to-register-DGDecNV%28DGSource-and-DGIndexNV%29-in-StaxRip

jinkazuya
23rd March 2021, 20:43
It seems it is aready included https://github.com/staxrip/staxrip/wiki/Tools#g41fun

@jinkazuya

Yes, it appears it was included by an ex maintainer, but it might not be available in the menu, for that there is documentation here:

https://github.com/staxrip/staxrip/wiki/Usage#video-processing

https://github.com/staxrip/staxrip/wiki/How-to-register-DGDecNV%28DGSource-and-DGIndexNV%29-in-StaxRip

The github page does not exist anymore for the plugin or script of detailsharpen, which is why if possible, if the plugin is included in the menu in the future release, that would be awesome.

stax76
23rd March 2021, 22:54
@jinkazuya

Please create a new thread (or use the staxrip thread) asking for code and default values and then add this code and values to the following wiki page:

Tool Update Requests (https://github.com/staxrip/staxrip/wiki/Tool-Update-Requests)

jackoneill
24th March 2021, 13:01
I have some problem with MakeDiff in versions 50,51,52 :x
Script evaluation failed:
Python exception: MakeDiff: both clips must have constant format and dimensions, and the same format and dimensions

Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 2244, in vapoursynth.vpy_evaluateScript
File "src/cython/vapoursynth.pyx", line 2245, in vapoursynth.vpy_evaluateScript
File "/mnt/dod/04.vpy", line 11, in <module>
clip = haf.QTGMC(clip, TFF=True, Preset="Placebo", ShowSettings=False, opencl=False, device=0, TR0=2, TR1=2, SourceMatch=0, TR2=0, Lossless=0, Sharpness=0 )
File "/usr/lib/python3.6/site-packages/havsfunc.py", line 1281, in QTGMC
noise = core.std.MakeDiff(clip, denoised, planes=CNplanes)
File "src/cython/vapoursynth.pyx", line 2069, in vapoursynth.Function.__call__
vapoursynth.Error: MakeDiff: both clips must have constant format and dimensions, and the same format and dimensions

linux, all compiled today, used LD_PRELOAD to test for plugin errors and there are none, without QTGMC the script works, latest mvsfunc and havsfunc

import vapoursynth as vs
import havsfunc as haf

core = vs.get_core()
core.set_max_cache_size(16000)

clip = core.ffms2.Source("//mnt//dod//movie.mkv")
clip = core.fmtc.bitdepth (clip, bits=16, fulls=False, fulld=True, dmode=1)
clip = haf.QTGMC(clip, TFF=True, Preset="Placebo", ShowSettings=False, opencl=False, device=0, TR0=2, TR1=2, SourceMatch=0, TR2=0, Lossless=0, Sharpness=0 )
clip = haf.MCTemporalDenoise(clip, radius=3, limit=2, twopass=False, limit2=2, refine=True, useTTmpSm=True, stabilize=False, maxr=3, TTstr=3, chroma=False, MVsharp=False, sigma=0, pfMode=-1,search=3, searchparam=4, pel=4, pelsearch=4, bwbh=512, owoh=256, blksize=4, overlap=2, deblock=False, post=0,bt=4,thSAD=2000, thSAD2=2000, thSCD1=1000, thSCD2=200)
clip = core.deblock.Deblock(clip, quant=20, aoffset=0, boffset=0)
clip = core.fmtc.bitdepth (clip, bits=10, fulls=True, fulld=True, dmode=1)
clip.set_output()

tested several older versions of havsfunc no change :x
I removed this code from src/core/mergefilters.c and it started working fine and the video looks correct
if (!isConstantFormat(d.vi) || !isSameFormat(d.vi, vsapi->getVideoInfo(d.node2))) {
vsapi->freeNode(d.node1);
vsapi->freeNode(d.node2);
RETERROR("MakeDiff: both clips must have constant format and dimensions, and the same format and dimensions");
}

strange problem

The error message gives you the line number in havsfunc.py (1281), so right before that line add

print(clip)
print(denoised)

to see what the difference is between those clips.

Patman
27th March 2021, 00:50
Hello everybody. I need your help with the following problem:

I have this code in my avs.c:

h->bit_depth = h->func.avs_bits_per_component(vi);
FAIL_IF_ERROR( h->bit_depth < 8 || h->bit_depth > 16, "unsupported bit depth `%d'\n", h->bit_depth );
if( h->bit_depth & 7 )
{
AVS_Value arg_arr[2];
arg_arr[0] = res;
arg_arr[1] = avs_new_value_int( 16 );
const char *arg_name[] = { NULL, "bits" };
AVS_Value res2 = h->func.avs_invoke( h->env, "ConvertBits", avs_new_value_array( arg_arr, 2 ), arg_name );
FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert to 16 bits: %s\n", avs_as_error( res2 ) );
res = update_clip( h, &vi, res2, res );
}

I would now like to store a code with an identical function in my vpy.c, but unfortunately it doesn't work that well. I have the following approach:

h->bit_depth = vi->format->bitsPerSample;
FAIL_IF_ERROR( h->bit_depth < 8 || h->bit_depth > 16, "unsupported bit depth `%d'\n", h->bit_depth );
FAIL_IF_ERROR( vi->format->sampleType == stFloat, "unsupported sample type `float'\n" );
if (h->bit_depth & 7)
{
VSMap* args = h->vsapi->createMap();
const char* error;
VSPlugin* fmtcPlugin = h->vsapi->getPluginById("fmtconv", core);

h->vsapi->propSetNode(args, "clip", h->node, paReplace);
h->vsapi->freeNode(h->node);
const VSFormat* new_format = h->vsapi->registerFormat(vi->format->colorFamily, vi->format->sampleType, 16, vi->format->subSamplingW, vi->format->subSamplingH, core);
h->vsapi->propSetInt(args, "csp", new_format->id, paReplace);
VSMap* ret = h->vsapi->invoke(fmtcPlugin, "bitdepth", args);
error = h->vsapi->getError(ret);
if (error)
{
FAIL_IF_ERROR(1, "failed to convert node to 16 bits: `%s'\n", error);
h->vsapi->freeMap(args);
h->vsapi->freeMap(ret);
return -1;
}
h->node = h->vsapi->propGetNode(ret, "clip", 0, NULL);
h->vsapi->freeMap(ret);
}

The aim is to consider certain plugins when processing. With avs it is 'ConvertBits' and with vpy 'fmtconv'. Does somebody has any idea?

feisty2
27th March 2021, 06:00
if you have a C++20 compiler (I guess GCC11 is currently the only option), you can play with my C++ wrapper for VS API (https://github.com/IFeelBloated/vsFilterScript) and coding a plugin is no more complicated than python scripting.

if you need to invoke an external filter as some sort of preprocessing, you can do it directly in the constructor of the filter

MyFilter(auto Arguments, auto Core) {
auto PreprocessedClip = Core["fmtc"]["bitdepth"]("clip", Arguments["clip"], "bits", 16);
}

alternatively, you can define InitiateCallGraph() (https://github.com/IFeelBloated/vsFilterScript/blob/master/Examples/SeparableConvolution.hxx#L51) if you need to run a more complex filter sequence, where you can invoke external filters for postprocessing, or recursively invoke the filter that is being defined.

feisty2
27th March 2021, 06:17
and no error checking of any sort is required (unless you need to change how your filter behaves based on if an evaluation fails), the error message (plugin not found, evaluation failed, or whatever) will automatically propagate to the console (vsedit, vspipe, etc.)

DJATOM
27th March 2021, 10:13
Since it's about x264, it uses C compiler, not C++.

feisty2
27th March 2021, 11:09
He/She didn't mention what it is that he/she's working on so I wouldn't have known. and since x264 already relies on GCC, it should be pretty handy for him/her to use the C++ wrapper (C99, the standard that x264 seems to be using, is mostly a subset of C++20 after all).

Patman
27th March 2021, 14:05
I'll give your wrapper a try.

As DJATOM already mentioned, the files are written in C (C compiler) and are used to directly support avs / vpy scripts in x264.

feisty2
28th March 2021, 09:53
@Myrsloik
is it safe to delete the user data passed to registerFunction() in Create() like the following?

auto RegisterFunction(auto&& Signature, auto&& Function) {
using FunctionType = std::decay_t<decltype(Function)>;
auto FunctionHandle = new auto{ std::forward<decltype(Function)>(Function) };
auto Create = [](auto in, auto out, auto FunctionHandle, auto core, auto...) {
auto& RegisteredFunction = *reinterpret_cast<FunctionType*>(FunctionHandle);
Console{ out }.Receive(RegisteredFunction(ArgumentList{ in }, CoreProxy{ core }));
delete &RegisteredFunction;
};
::vsapi->registerFunction(DeduceName(Signature), ExtractParamList(Signature), Create, FunctionHandle, ::PluginHandle);
}

RegisterFunction("f(x: int[])", [](auto args, auto Core) { for (auto y : args["x"]) Core.Print(static_cast<int>(y)); return 42; });

I guess what I am actually asking is that will Create() run on mutiple threads which then leads to the risk of use-after-free or double-free?

Myrsloik
28th March 2021, 11:50
@Myrsloik
is it safe to delete the user data passed to registerFunction() in Create() like the following?
[code]
...

No. Filter creation can be multithreaded too (mostly happens when you create and destroy filters in a getframe function).

feisty2
28th March 2021, 12:17
then who deletes the user data? I searched thru avisynth_compat.cpp (https://github.com/vapoursynth/vapoursynth/blob/master/src/avisynth/avisynth_compat.cpp) and didn't find where the WrappedFunction object (https://github.com/vapoursynth/vapoursynth/blob/master/src/avisynth/avisynth_compat.cpp#L724) gets deleted :confused:

jackoneill
28th March 2021, 12:29
Hello everybody. I need your help with the following problem:

I have this code in my avs.c:

h->bit_depth = h->func.avs_bits_per_component(vi);
FAIL_IF_ERROR( h->bit_depth < 8 || h->bit_depth > 16, "unsupported bit depth `%d'\n", h->bit_depth );
if( h->bit_depth & 7 )
{
AVS_Value arg_arr[2];
arg_arr[0] = res;
arg_arr[1] = avs_new_value_int( 16 );
const char *arg_name[] = { NULL, "bits" };
AVS_Value res2 = h->func.avs_invoke( h->env, "ConvertBits", avs_new_value_array( arg_arr, 2 ), arg_name );
FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert to 16 bits: %s\n", avs_as_error( res2 ) );
res = update_clip( h, &vi, res2, res );
}

I would now like to store a code with an identical function in my vpy.c, but unfortunately it doesn't work that well. I have the following approach:

h->bit_depth = vi->format->bitsPerSample;
FAIL_IF_ERROR( h->bit_depth < 8 || h->bit_depth > 16, "unsupported bit depth `%d'\n", h->bit_depth );
FAIL_IF_ERROR( vi->format->sampleType == stFloat, "unsupported sample type `float'\n" );
if (h->bit_depth & 7)
{
VSMap* args = h->vsapi->createMap();
const char* error;
VSPlugin* fmtcPlugin = h->vsapi->getPluginById("fmtconv", core);

h->vsapi->propSetNode(args, "clip", h->node, paReplace);
h->vsapi->freeNode(h->node);
const VSFormat* new_format = h->vsapi->registerFormat(vi->format->colorFamily, vi->format->sampleType, 16, vi->format->subSamplingW, vi->format->subSamplingH, core);
h->vsapi->propSetInt(args, "csp", new_format->id, paReplace);
VSMap* ret = h->vsapi->invoke(fmtcPlugin, "bitdepth", args);
error = h->vsapi->getError(ret);
if (error)
{
FAIL_IF_ERROR(1, "failed to convert node to 16 bits: `%s'\n", error);
h->vsapi->freeMap(args);
h->vsapi->freeMap(ret);
return -1;
}
h->node = h->vsapi->propGetNode(ret, "clip", 0, NULL);
h->vsapi->freeMap(ret);
}

The aim is to consider certain plugins when processing. With avs it is 'ConvertBits' and with vpy 'fmtconv'. Does somebody has any idea?

It looks like it should function. What problem did you encounter?

Things I noticed:
- You're leaking the args VSMap. You should free it after you call invoke.
- getPluginById can return NULL if the plugin you want is not loaded. fmtconv is not included with VapourSynth. You could use the built-in resizer (com.vapoursynth.resize (http://www.vapoursynth.com/doc/functions/resize.html)), then you don't really have to check what getPluginById returns.

Myrsloik
28th March 2021, 12:41
then who deletes the user data? I searched thru avisynth_compat.cpp (https://github.com/vapoursynth/vapoursynth/blob/master/src/avisynth/avisynth_compat.cpp) and didn't find where the WrappedFunction object (https://github.com/vapoursynth/vapoursynth/blob/master/src/avisynth/avisynth_compat.cpp#L724) gets deleted :confused:

Nobody deletes it. It's mostly a bad inherited avisynth-ism and should probably never be used.

Myrsloik
28th March 2021, 12:44
R53-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R53-RC1)
updated visual studio 2019 runtime version
updated to python 3.9 for windows
fixed length calculation in y4m header (djatom)
added long path support to vspipe (stax76)
fixed crash in text filter with small resolution clips (jackoneill)
fixed calling wrapped functions through python (IFeelBloated)

Finally doing a bit of development again. Note that the included vsrepo has some fixes too.

l00t
28th March 2021, 13:48
Thanks for the new release!

With the portable version combined with python 3.9.2 embedded I get Failed to initialize VapourSynth environment
(both with vspipe -v and also in vseditor)

Previously I had R52 with 3.8.8 working just fine (portable+embedded). I copied over the fresh files and I get this.

The installed version works fine with the installer version of python 3.9.2...

What did I do wrong? Any suggestions?

I'm on Win10 20H2 x64. Both python and vs are 64-bit variants.

l00t
28th March 2021, 13:55
Hmm, placing vapoursynth.cp39-win_amd64.pyd under Lib\site-packages seems to solve this issue...

Myrsloik
28th March 2021, 13:58
Thanks for the new release!

With the portable version combined with python 3.9.2 embedded I get Failed to initialize VapourSynth environment
(both with vspipe -v and also in vseditor)

Previously I had R52 with 3.8.8 working just fine (portable+embedded). I copied over the fresh files and I get this.

The installed version works fine with the installer version of python 3.9.2...

What did I do wrong? Any suggestions?

I'm on Win10 20H2 x64. Both python and vs are 64-bit variants.

Doh, typo in the portable build script so the actual module didn't get included. Redownload it.

l00t
28th March 2021, 14:02
Ah, now it works like a charm without messing with precompiled files. Thank you!

feisty2
28th March 2021, 15:28
Nobody deletes it. It's mostly a bad inherited avisynth-ism and should probably never be used.

I guess it might be somewhat useful for "bridge" plugins (bridging foreign plugins developed for other video processing software to VS, like core.avs.LoadPlugin), and it allows the user to register stateful lambdas as plugin functions.

I guess I could tie the lifetime of user data to a static variable like the following

struct GlobalRecyler {
using RecordType = std::tuple<auto(*)(void*)->void, void*>;
std::vector<RecordType> Records = {};

GlobalRecyler() = default;
GlobalRecyler(const GlobalRecyler&) = delete;
GlobalRecyler(GlobalRecyler&&) = delete;
auto& operator=(const GlobalRecyler&) = delete;
auto& operator=(GlobalRecyler&&) = delete;

auto Collect(auto Garbage) {
using GarbageType = std::decay_t<decltype(*Garbage)>;
Records.push_back({ [](auto PointerToGarbage) { delete reinterpret_cast<GarbageType*>(PointerToGarbage); }, Garbage });
}

~GlobalRecyler() {
for (auto [Recyler, Garbage] : Records)
Recyler(Garbage);
}
};

auto RegisterFunction(auto&& Signature, auto&& Function) {
using FunctionType = std::decay_t<decltype(Function)>;
static auto Evil = GlobalRecyler{};
auto FunctionHandle = new auto{ std::forward<decltype(Function)>(Function) };
auto Create = [](auto in, auto out, auto FunctionHandle, auto core, auto...) {
auto& RegisteredFunction = *reinterpret_cast<FunctionType*>(FunctionHandle);
Console{ out }.Receive(RegisteredFunction(ArgumentList{ in }, CoreProxy{ core }));
};
Evil.Collect(FunctionHandle);
::vsapi->registerFunction(DeduceName(Signature), ExtractParamList(Signature), Create, FunctionHandle, ::PluginHandle);
}


and the user data will be recycled along with the static variable when the plugin is unloaded, that should work, right?

Myrsloik
31st March 2021, 10:09
and the user data will be recycled along with the static variable when the plugin is unloaded, that should work, right?

Stop the madness!

You have to ask yourself if you're writing a wrapper to create new good plugins or if it's only a programming exercise to sexually please yourself using naughty code. The correct pattern is for the plugin itself to have an internal filter initialization counter or properly free everything on library unload. That pointer is useless if you have any idea what you're doing when writing code.

feisty2
31st March 2021, 14:57
well I'm not doing it just because I can, I'm doing it because I think there is indeed a valid use case. I've excluded quite a few rarely used or deprecated things or things that are not meant to be used by plugin developers from the C API (setMessageHandler, queryCompletedFrame, releaseFrameEarly, arFrameReady, nfIsCache, nfMakeLinear, cmCompat and all Compat formats, also all "map" stuff is invisible to the user). I would have excluded the use of this pointer too if I didn't already find a use case for it.

a while ago @lansing requested an example of a bridge plugin to load Vdubfilters (http://forum.doom9.net/showpost.php?p=1933851&postcount=76), while I never had the time to finish the example he/she asked for, I did take a quick glance over how it's done in avisynth (https://github.com/pinterf/AviSynthPlus/blob/master/plugins/VDubFilter/VDubFilter.cpp#L1544). there's this configuration object (fdl) representing the state of a virtualdub filter that you must pass to a filter instance, I suppose the skeleton of the bridge plugin would be something like

struct VirtualDubProxy {
VirtualDubProxy(auto Arguments, auto& Configurations, auto Core) {
auto& [ReferenceCounter, VirtualDubFunctionHandles, _] = Configurations;
...
}

static auto SpecifySignature(auto& Configurations) {
auto& [_, __, RawSignature] = Configurations;
...
return ... // converts RawSignature to VS signature format
}

....
};

for (auto& x : VirtualDubPlugin.ListFunctions())
PluginAPI::RegisterFilter<VirtualDubProxy>(x.ZipConfigurations());

apparently RegisterFilter() is just a wrapper for vsapi->registerFunction() and Create(), and the only place that allows me to pass that configuration object seems to be that userData pointer. so I don't know how this is possible without using that pointer. the configuration object will have a static lifetime so it can be accessed by all filter instances across threads, and itself may contain a reference counter and some resources may be released as soon as the reference count drops to 0, I don't understand how any of this is madness.

Myrsloik
10th April 2021, 14:50
R53-RC2 (https://github.com/vapoursynth/vapoursynth/releases/tag/R53-RC2)
r53:
updated visual studio 2019 runtime version
updated to python 3.9 for windows
added scale argument to text filters (AkarinVS)
fixed length calculation in y4m header (djatom)
added long path support to vspipe (stax76)
fixed crash in text filter with small resolution clips (jackoneill)
fixed calling wrapped functions through python (IFeelBloated)

Test it a bit. Probably the final RC so this thing gets released.

stax76
10th April 2021, 16:20
I tested portable with Python 3.9.4, it works fine.

Long path support might not be useful currently because original/vanilla x265 builds don't support long path, most builds are modded, mods from DJATOM, Patman and MeteorRain have a vs reader included, Lighs builds are based on synth readers from DJATOM and MeteorRain, links are here:

https://github.com/staxrip/staxrip/wiki/x265

unix
20th April 2021, 19:13
Guys I have an issue, I installed placebo plugin but vsp editor cant recognize it!

Note: I'm using portable Vapoursynth just for tests

Myrsloik
21st April 2021, 17:59
R53 is released (https://github.com/vapoursynth/vapoursynth/releases/tag/R53)!

updated visual studio 2019 runtime version
updated to python 3.9 for windows
added scale argument to text filters (AkarinVS)
fixed length calculation in y4m header (djatom)
added long path support to vspipe (stax76)
fixed crash in text filter with small resolution clips (jackoneill)
fixed calling wrapped functions through python (IFeelBloated)

Hopefully I'll have time to finish the mythic audio branch this summer.

Nico8583
22nd April 2021, 14:21
Thank you Myrsloik ! The Windows portable installation is the same than previous versions (except Python 3.9 instead of 3.8 - Decompress R53 into Python 3.9 embeddable folder) ? Thank you.

vcmohan
23rd April 2021, 08:05
It is a great convenience that vapousynth input script allows arrays. I am however curious whether an array of arrays for example filt:int[[],[],[],...]: opt; can be used in the code of plugin. If its possible how to get input number of arrays and number of elements in each array.

Myrsloik
23rd April 2021, 09:21
It is a great convenience that vapousynth input script allows arrays. I am however curious whether an array of arrays for example filt:int[[],[],[],...]: opt; can be used in the code of plugin. If its possible how to get input number of arrays and number of elements in each array.

No, only 1D arrays are allowed to keep the api simple. If you have a fixed number of dimensions simply add a second argument to specify the row size to get around it. Or implicitly figure out the array dimensions like the convolution filter.

Myrsloik
23rd April 2021, 09:43
Thank you Myrsloik ! The Windows portable installation is the same than previous versions (except Python 3.9 instead of 3.8 - Decompress R53 into Python 3.9 embeddable folder) ? Thank you.

Yes, same procedure as every year.

Selur
19th May 2021, 20:45
Is there anything similar to a 'vibrance' filter in photoshop and similar in Vapoursynth (some sort of restricted saturation filtering)?

Myrsloik
20th May 2021, 17:21
We looked a bit at the mess that is mask handling recently and now I have one simple question:

Is there any script out there that actually passes a YUV clip as the mask argument of MaskedMerge and doesn't set first_plane=1? (and doesn't simply discard the output UV planes later).
MaskedMerge(YUVclipA, YUVclipB, YUVmask)

I think the answer is no. Counterexamples welcome.

feisty2
1st June 2021, 18:52
any plan to replace this (https://github.com/vapoursynth/vapoursynth/blob/master/src/core/ter-116n.h) with a real font? It can't even display tabs...

Myrsloik
1st June 2021, 21:27
any plan to replace this (https://github.com/vapoursynth/vapoursynth/blob/master/src/core/ter-116n.h) with a real font? It can't even display tabs...

Nope, the whole point is that it adds no external dependencies at all for basic printing. If there's particular control shit or a like tabs simply create an issue for it and maybe someone will look at it.

Selur
13th June 2021, 16:23
Hi, I'm trying to get VSGAN running in a fresh portable Vapoursynth setup, see: https://github.com/rlaphoenix/VSGAN/issues/7
at the end I use this script:
# Imports
import os
import sys
import vapoursynth as vs
core = vs.get_core()

# Import scripts folder
scriptPath = 'I:/Hybrid/64bit/vsscripts'
sys.path.append(os.path.abspath(scriptPath))

# Loading Plugins
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")

# Import scripts
import mvsfunc

# source: 'G:\TestClips&Co\test.avi'
# current color space: YUV420P8, bit depth: 8, resolution: 640x352, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: progressive
# Loading source using FFMS2
clip = core.ffms2.Source(source="G:/TestClips&Co/test.avi",cachefile="E:/Temp/avi_9dec25d3f707eb4813d42334c7f1a8d6_853323747.ffindex",format=vs.YUV420P8,alpha=False)

# adjusting color space from YUV420P8 to RGB24 for vsVSGAN
clip = core.resize.Bicubic(clip=clip, format=vs.RGB24, matrix_in_s="470bg", range_s="limited")

# resizing using VSGAN
from vsgan import VSGAN
vsgan = VSGAN("cuda")
model = "I:/Hybrid/64bit/vsgan_models/4x_BSRGAN.pth"
vsgan.load_model(model)
clip = vsgan.run(clip=clip)

# Output
clip.set_output()
call it using:
i:\Vapoursynth\VSPipe.exe --info C:\Users\Selur\Desktop\testvsgan.vpy -
and end up with:
Script evaluation failed:
Python exception: cannot import name 'VSGAN' from 'vsgan' (i:\Vapoursynth\Lib\site-packages\vsgan\__init__.py)

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2242, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 2243, in vapoursynth.vpy_evaluateScript
File "C:\Users\Selur\Desktop\testvsgan.vpy", line 26, in <module>
from vsgan import VSGAN
ImportError: cannot import name 'VSGAN' from 'vsgan' (i:\Vapoursynth\Lib\site-packages\vsgan\__init__.py)
Problem is I have no clue where to look or what I might need to adjust.

When I use the FATPACK as basis instead of using the portable Python and Vapoursynth the was I did, it does work.
-> does anyone have an idea what I might have to adjust to make this work?

Cu Selur

Selur
13th June 2021, 17:06
Got it working by creating a fake I:\Vapoursynth\Lib\site-packages\VapourSynth-53.dist-info folder with some fake info and uninstalling and reinstalling VSGAN I got it working! :)
Side note: the portable version should contain a Lib\site-packages\VapourSynth-53.dist-info-folder with proper infos.

Cu Selur

EnC
25th June 2021, 04:45
Got it working by creating a fake I:\Vapoursynth\Lib\site-packages\VapourSynth-53.dist-info folder with some fake info and uninstalling and reinstalling VSGAN I got it working! :)
Side note: the portable version should contain a Lib\site-packages\VapourSynth-53.dist-info-folder with proper infos.

Cu Selur

This little trick did work for me too to install awsmfunc (https://git.concertos.live/AHD/awsmfunc) too. Strange it fails during 'requirements' without fake 'VapourSynth-53.dist-info' folder. :rolleyes:

Selur
26th June 2021, 09:13
Since my python skills aren't that high I'm not sure whether I made a mistake or this is a bug. :)
Using vs-placebo (https://github.com/Lypheo/vs-placebo) with shader="path to file" works fine for me, but using 'shader_s' does not.

Calling:

# Imports
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/libvs_placebo.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")
# source: 'G:\TestClips&Co\test.avi'
# current color space: YUV420P8, bit depth: 8, resolution: 640x352, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: progressive
# Loading source using FFMS2
clip = core.ffms2.Source(source="G:/TestClips&Co/test.avi",cachefile="E:/Temp/avi_9dec25d3f707eb4813d42334c7f1a8d6_853323747.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg",range_s="limited")
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# GLSL filter: adaptive-sharpen.glsl
# adjusting color space from YUV420P8 to YUV444P16 for VsGLSLFilter
clip = core.resize.Bicubic(clip=clip, format=vs.YUV444P16, range_s="limited")
with open("I:/Hybrid/64bit/vsfilters/GLSL/adaptive-sharpen.glsl") as glslf:
glsl = glslf.read()
glsl = glsl.replace('#define curve_height 1.0', '#define curve_height 2.0');
clip = core.placebo.Shader(clip=clip, shader_s=glsl, width=640, height=352)
# adjusting output color from: YUV444P16 to YUV420P10 for x265Model (i420@8)
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P10, range_s="limited")
# set output frame rate to 25.000fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()

I get:

Failed to evaluate the script:
Python exception: Shader: Function does not take argument(s) named shader_s

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2242, in vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 2243, in vapoursynth.vpy_evaluateScript
File "C:\Users\Selur\Desktop\test.vpy", line 23, in <module>
clip = core.placebo.Shader(clip=clip, shader_s=glsl, width=640, height=352)
File "src\cython\vapoursynth.pyx", line 2040, in vapoursynth.Function.__call__vapoursynth.Error: Shader: Function does not take argument(s) named shader_s

according to:
placebo.Shader(clip clip, [string shader, int width, int height, int chroma_loc = 1, int matrix = 2, int trc = 1, string filter = "ewa_lanczos", float radius, float clamp, float taper, float blur, float param1, float param2, float antiring = 0.0, int lut_entries = 64, float cutoff = 0.001, bool sigmoidize = 1, bool linearize = 1, float sigmoid_center = 0.75, float sigmoid_slope = 6.5, string shader_s])
this should work, shouldn't it?

Cu Selur

Ps.: I also posted this to the vs-placebo github issue tracker (https://github.com/Lypheo/vs-placebo/issues/12).

Selur
26th June 2021, 10:02
Okay, that got solved, only master contained the shader_s-path not the current (1.1.0) release,..
-> if someone got a build environment for this would be nice if he could build and share a current 64bit Windows build of VSGAN

feisty2
27th June 2021, 14:18
anyone wants a general remap filter?

clip = core.std.Remap(clip, lambda y, x: [clip.height - y - 1, x]) # equivalent to FlipVertical
clip = core.std.Remap(clip, lambda y, x: [y, clip.width - x - 1]) # equivalent to FlipHorizontal

clip = core.std.StackVertical([clip, clip])
clip = core.std.StackHorizontal([clip, clip])
clip = core.std.Remap(clip, lambda y, x: [y // 2, x // 2]) # equivalent to 2x upscale by point resize

Myrsloik
27th June 2021, 14:27
anyone wants a general remap filter?

clip = core.std.Remap(clip, lambda y, x: [clip.height - y - 1, x]) # equivalent to FlipVertical
clip = core.std.Remap(clip, lambda y, x: [y, clip.width - x - 1]) # equivalent to FlipHorizontal

clip = core.std.StackVertical([clip, clip])
clip = core.std.StackHorizontal([clip, clip])
clip = core.std.Remap(clip, lambda y, x: [y // 2, x // 2]) # equivalent to 2x upscale by point resize


That's a fun thing to have. I think you should have destination width/height arguments so the point resize-ish cases don't require the dummy steps.

Selur
10th July 2021, 18:28
hi, I'm trying to convert the Avisynth function:
function filldrops(clip c, float "thresh")
{
thresh = default(thresh, 0.1)

super=MSuper(c,pel=2)
vfe=MAnalyse(super,truemotion=true,isb=false,delta =1)
vbe=MAnalyse(super,truemotion=true,isb=true,delta= 1)
filldrops = MFlowInter(c,super,vbe,vfe,time=50)
fixed = ConditionalFilter(c, filldrops, c, "YDifferenceFromPrevious()", "lessthan", String(thresh))
return fixed
}
slightly modified, source: https://forum.doom9.org/showthread.php?p=17751849

to Vapoursynth, and got:

def filldrops(c, thresh=0.1)

def YDifferenceFromPrevious(n, f, clips):
if f.props['_SceneChangePrev']:
return clips[0]
else:
return clips[1]

super=core.mv.Super(clip=c,pel=2)
vfe=core.mv.Analyse(clip=super,truemotion=true,isb=false,delta =1)
vbe=core.mv.Analyse(clip=super,truemotion=true,isb=true,delta= 1)
filldrops = core.mv.FlowInter(clip=c,super,mvbw=vbe,mvfw=vfe,time=50)
#fixed = ConditionalFilter(c, filldrops, c, "YDifferenceFromPrevious()", "lessthan", String(thresh))
fixed = core.std.FrameEval(...)
return fixed

but I'm stuck at the ConditionalFilter-line. :/
-> can someone tell me how FrameEval(...) should look like to do what ConditionalFilter(...) does ?

Thanks!

Cu Selur

Myrsloik
11th July 2021, 15:45
def filldrops(c, thresh=0.1)
diffclip = core.std.PlaneStats(c, c[0] + c)
super=core.mv.Super(clip=c,pel=2)
vfe=core.mv.Analyse(clip=super,truemotion=true,isb=false,delta =1)
vbe=core.mv.Analyse(clip=super,truemotion=true,isb=true,delta= 1)
filldrops = core.mv.FlowInter(clip=c,super,mvbw=vbe,mvfw=vfe,time=50)
def selectFunc(n, f):
if f.props['PlaneStatsDiff'] < thresh:
return c
else:
return filldrops

fixed = core.std.FrameEval(c, selectFunc, prop_src=diffclip)
return fixed


Didn't test it but it should be 99% of the way there. Simple selection.

Selur
11th July 2021, 16:36
Thanks ! :)

JKyle
12th July 2021, 00:32
Thanks, @Selur and @Myrsloik.

I fixed some syntax errors and slightly modified the script to make it work in StaxRip.

Here (https://github.com/JJKylee/Filter-Scripts/blob/main/VapourSynth/filldrops.py)'s the source code.

Myrsloik
16th July 2021, 12:36
R54-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R54-RC1)

This release makes the handling of floating point masks consistent (now always 0-1 range, even for UV planes) and fixes some other minor bugs. Should be a very stable build overall.

r54:
updated visual studio 2019 runtime version
updated zimg to 3.0.2
cliptoprop now uses the length of the second clip instead of the first one
added sin and cos operator to the expr filter (AkarinVS)
made handling of floating point masks consistent (AkarinVS and more)
fixed memory leak on free in expr filter on linux (AkarinVS)

Selur
16th July 2021, 17:21
btw. is there a way to stop auto-loading so that only explicitly loaded filters are loaded nowadays?

@JKyle: Any plans to port Dejump to Vaporusynth?

Myrsloik
16th July 2021, 21:57
btw. is there a way to stop auto-loading so that only explicitly loaded filters are loaded nowadays?

@JKyle: Any plans to port Dejump to Vaporusynth?

An option to disable auto loading is probably coming soon. With more exciting things as well.

Selur
17th July 2021, 08:26
An option to disable auto loading is probably coming soon. With more exciting things as well.
Nice! Thanks for the info, looking forward to it. :)

Myrsloik
21st July 2021, 20:11
R54 released. Same list of changes as RC1 but it's been recompiled with a newer visual studio.

Dann0245
23rd July 2021, 10:15
On Ubuntu, how can I get vapoursynth plugins?

Or I have to compile all plugins one by one, compiling stuff is difficult for me.

quietvoid
23rd July 2021, 13:19
On Ubuntu, how can I get vapoursynth plugins?

Or I have to compile all plugins one by one, compiling stuff is difficult for me.

Maybe this could work? https://github.com/makedeb/makedeb
The AUR has a lot of plugin packages: https://aur.archlinux.org/packages/?O=0&K=vapoursynth-plugin

Selur
26th July 2021, 04:45
Using:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
core = vs.core
# Loading Plugins
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/vslsmashsource.dll")
# source: 'G:\TestClips&Co\files\ProRes\Test Patterns Resolve 4444 12-bit.mov'
# current color space: YUV444P16, bit depth: 12, resolution: 720x576, fps: 25, color matrix: 709, yuv luminance scale: limited, scanorder: progressive
# Loading G:\TestClips&Co\files\ProRes\Test Patterns Resolve 4444 12-bit.mov using LibavSMASHSource
clip = core.lsmas.LibavSMASHSource(source="G:/TestClips&Co/files/ProRes/Test Patterns Resolve 4444 12-bit.mov")
# making sure input color matrix is set as 709
clip = core.resize.Point(clip, matrix_in_s="709",range_s="limited")
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# adjusting color space from YUV444P16 to RGB48 for vsLevels
clip = core.resize.Bicubic(clip=clip, format=vs.RGB48, matrix_in_s="709", range_s="limited")
# Color Adjustment
clip = core.std.Levels(clip=clip, min_in=256, max_in=3760, min_out=256, max_out=3760)

# set output frame rate to 25.000fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()
I get a black output.
without the:
# Color Adjustment
clip = core.std.Levels(clip=clip, min_in=256, max_in=3760, min_out=256, max_out=3760)

Same when using:
# Color Adjustment
clip = core.std.Limiter(clip=clip, min=0, max=4080)

Is this a bug/limitation or am I missing something?


Shared the input in my GoogleDrive (https://drive.google.com/file/d/1CW5xA2_Y6y8IUlwCRrfJTkWC3L_x2IaO/view?usp=sharing).
Happens with both Vapoursynth R53 and R54.

Cu Selur

poisondeathray
26th July 2021, 04:58
# adjusting color space from YUV444P16 to RGB48 for vsLevels
clip = core.resize.Bicubic(clip=clip, format=vs.RGB48, matrix_in_s="709", range_s="limited")
# Color Adjustment
clip = core.std.Levels(clip=clip, min_in=256, max_in=3760, min_out=256, max_out=3760)


Is this a bug/limitation or am I missing something?




It's the expected result for RGB48 (16bit goes from 0 to 65535)

StainlessS
26th July 2021, 05:07
Selur, I think your numbers are for 12 bit.

shph
26th July 2021, 08:39
Few more interesting test results:

If i render with Hybrid to ProRes 444 MKV (instead of original MOV container) and put that rendered MKV file back to Hybrid - i got black screen preview when apply Levels even if UseRGB is unchecked.

If i use ProRes444 file, apply Levels with any settings and render to ProRes 444 - i got MOV file that is simply black.

Selur
26th July 2021, 10:06
It's the expected result for RGB48 (16bit goes from 0 to 65535)
+
Selur, I think your numbers are for 12 bit.
DOH,... since the input was 12bit I forgot to properly scale!

Thanks totally overlooked that.

Cu Selur

ChaosKing
1st August 2021, 11:03
In VS get_plugins() can show some basic information about plugins like name, functions, identifier etc. But it only works for loaded dlls.
Is it somehow possible to get the same (or almost same) information without (successfully) loading a plugin first?
I want to automate things for vsdb.top + more show some infos in vsrepogui.


Most important would be identifier + all function names

Myrsloik
1st August 2021, 11:20
In VS get_plugins() can show some basic information about plugins like name, functions, identifier etc. But it only works for loaded dlls.
Is it somehow possible to get the same (or almost same) information without (successfully) loading a plugin first?
I want to automate things for vsdb.top + more show some infos in vsrepogui.


Most important would be identifier + all function names

Sure, just look at the plugin loading code. See https://github.com/vapoursynth/vapoursynth/blob/master/src/core/vscore.cpp#L1517 (https://github.com/vapoursynth/vapoursynth/blob/master/src/core/vscore.cpp#L1517)for how it's done. You can more or less copy the code and simply supply your own configplugin and registerfunction callbacks.

ChaosKing
1st August 2021, 17:45
Thx. Will try to make a small cli app.

If I understand it correctly trying to read a plugin which uses cuda for example would still fail with LoadLibraryEx , wouldn't it? ( I don't have a cuda card in this case)

Myrsloik
1st August 2021, 17:53
Thx. Will try to make a small cli app.

If I understand it correctly trying to read a plugin which uses cuda for example would still fail with LoadLibraryEx , wouldn't it? ( I don't have a cuda card in this case)

Depends on how it was written. If the cuda libraries are either dynamically loaded (LoadLibrary) or delay loaded it'd work. If it's a static import it wouldn't. Note that in this case I think the check could mostly be considered to be whether or not the cuda libraries exist so you could borrow them from somewhere even if you, correctly, avoided nvidia.

poisondeathray
5th August 2021, 17:09
# GLSL filter: adaptive-sharpen.glsl
# clip = core.placebo.Shader

Okay, that got solved, only master contained the shader_s-path not the current (1.1.0) release,..



Selur, were you able to get adaptive-sharpen.glsl working with placebo.Shader ? Just specifying shader=r'PATH\adaptive-sharpen.glsl' ?

It returns image for me, but no difference in image

I'm using this version of adaptive-sharpen.glsl
https://gist.github.com/igv/8a77e4eb8276753b54bb94c1c50c317e

I tried linearizing input first, then linearize=True, no difference

(I'm trying to compare CPU version in avisynth port that Dogway put up - that version works)

BabaG
8th August 2021, 23:55
installation question. trying to install on kubuntu 20.04 and getting an error that:
No package 'python-3.8' found
yet, when i query for a python version, i get this:
Python 3.8.10

i know almost nothing about installing from source or github or any of it so i'm not surprized at the problems. got past a missing 'zimg' and managed to get that to be found during ./configure but don't know what to do about this now.

thanks for any help,
babag

Myrsloik
9th August 2021, 00:00
installation question. trying to install on kubuntu 20.04 and getting an error that:
No package 'python-3.8' found
yet, when i query for a python version, i get this:
Python 3.8.10

i know almost nothing about installing from source or github or any of it so i'm not surprized at the problems. got past a missing 'zimg' and managed to get that to be found during ./configure but don't know what to do about this now.

thanks for any help,
babag

Usually it means you need something like the python-3.8-dev package or similar.

BabaG
9th August 2021, 01:11
edit:
ok. got past that one. continuing to look for things it's not finding.
end edit

thanks! i'll look into that. just figured out i should probably post more info on the error so here it is:
checking for python platform... linux
checking for python script directory... ${prefix}/lib/python3.8/site-packages
checking for python extension module directory... ${exec_prefix}/lib/python3.8/site-packages
checking for PYTHON3... no
checking for PYTHON3... no
configure: error: Package requirements (python-3.8) were not met:

No package 'python-3.8' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables PYTHON3_CFLAGS
and PYTHON3_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

l33tmeatwad
9th August 2021, 01:17
This should do it: sudo apt install python3-dev python3-pip cython3

BabaG
9th August 2021, 02:29
i'm getting two errors as described here:
http://www.vapoursynth.com/doc/installation.html

first is:
vspipe: error while loading shared libraries: libvapoursynth-script.so.0: cannot open shared object file: No such file or directory

in response to the above error, i see this in the documentation but am not sure what to do with it (type it into my cli? put it in a config file someplace?LD_LIBRARY_PATH=/usr/local/lib vspipe --version

when i just put it in the cli, i get this:
Failed to initialize VapourSynth environment

i also see this in the docs but, again, don't know what to do with it:
PYTHONPATH=/usr/local/lib/python3.8/site-packages vspipe --version

again, when i put it into my cli, i get:
vspipe: error while loading shared libraries: libvapoursynth-script.so.0: cannot open shared object file: No such file or directory

i do feel like i'm getting close. this is just the kind of thing i never do.

thanks,
babag

l33tmeatwad
9th August 2021, 03:00
Debian based platforms have a few quirks that are easily avoided with a few tricks that can be found in this walkthrough (https://www.l33tmeatwad.com/vapoursynth101/software-setup).

BabaG
9th August 2021, 03:06
thanks! i'll look at that.

babag

Yomiko
9th August 2021, 06:54
I had the following issue when I was trying to build a plugin in Linux.

My plugin relied on an external library, libcolord, to search for a certain variable. Connection to libcolord was made by creating a reference to a singleton maintained by libcolord. In VS Editor where plugins are unloaded between preview attempts, the second time of creating the reference could always trigger an error "GLib-GObject-WARNING **: cannot register existing type ". I ended up moving the reference outside the plugin and built it as a standalone shared library, loaded with dlopen in my plugin without ever calling dlclose, and the problem seems to be solved.

May I know if it's a feature of VS? From what I understand, when the plugin is unloaded, nothing from the scope could survive.

BabaG
10th August 2021, 04:26
so, i followed the posted link by l33tmeatwad. thanks so much for that! i'd been looking for detailed instructions for quite some time and those were very thorough. very helpful!

there were quite a few warnings that came up when i was copy/pasting commands but i figured they were, hopefully, non-critical. other than that there were only a couple of issues.

first, this is the series of commands i followed for vapoursynth itself:
cd $HOME/.installs
git clone https://github.com/vapoursynth/vapoursynth.git
cd $HOME/.installs/vapoursynth
git checkout R54
./autogen.sh
./configure
make
make install
sudo make install
sudo ldconfig

in the above, i changed the site's reference to r50 to the current r54. hopefully that was cool. the site also says in this list of commands to issue a 'make install' command. that didn't work so i tried 'sudo make install' command and it went through.

the only other thing was this:
sudo cp hasvsfunc/havsfunc.py /usr/local/lib/python3.*/dist-packages/

there appears to be a typo in that. i changed it to:
sudo cp havsfunc/havsfunc.py /usr/local/lib/python3.*/dist-packages/
making that change allowed the cp to go through.

i am having one issue, i think. i haven't gotten far enough to know anything about what i'm doing but i get this error at the bottom of VSEdit:
Failed to initialize VapourSynth environment!

it sounds bad but i don't know if it really means anything. i'll be looking for a way to test a file to see if vs is actually there and capable of doing anything.

thanks again for that guide. it was really helpful!
babag

l33tmeatwad
10th August 2021, 04:35
Did you remove the site-packages folder before trying to make a symbolic link? Debian based Linux python installs use dist-packages and not site-packages, so if the directory was created before and not deleted stuff like VapourSynth will install there and thus not be loaded. If the actual directory exists simply copy all those files over and delete the site-packages folder then use the instructions to create a symbolic link to redirect anything trying to look or copy to that folder.

BabaG
10th August 2021, 05:09
thanks for the quick reply, l33tmeatwad! i confess, though, that i don't know what any of the response means. i'd need more detail to be able to follow. i can sort of get the gist but not enough to be able to act on it. fwiw, i followed the instructions in your link very literally.

thanks again,
babag

l33tmeatwad
10th August 2021, 13:29
So basically where you installed it before the VapourSynth install created /usr/local/lib/python3.*/site-packages, one of the errors you probably got was trying to create the symbolic link in step two because the folder exists already. A symbolic link is a kind of shortcut that points to something else. What you need to do is move everything inside of site-packages into dist-packages, delete the site-packages folder, then use these commands to point site-packages to dist-packages:
cd /usr/local/lib/python3.*
sudo ln -s dist-packages site-packages

BabaG
10th August 2021, 19:09
hey! that's awesome! thanks. the error is gone. now on to being confused by other things.

i copied something from someplace, possibly your site, and am getting a new error in vsedit. here's the code i have:from vapoursynth import core

video = core.lsmas.LWLibavSource(r'/home/babag/Documents/Projects/Buddies_97/2377.mov').text.ClipInfo()

video.set_output()

i found that i can check the script in vsedit with menu--->script--->check script. this is what it returns:
Failed to evaluate the script:
Python exception: No attribute with the name lsmas exists. Did you mistype a plugin namespace?

Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 2242, in vapoursynth.vpy_evaluateScript
File "src/cython/vapoursynth.pyx", line 2243, in vapoursynth.vpy_evaluateScript
File "/home/babag/Documents/Projects/Buddies_97/VS_Test-01.vpy", line 3, in
video = core.lsmas.LWLibavSource(r'/home/babag/Documents/Projects/Buddies_97/2377.mov').text.ClipInfo()
File "src/cython/vapoursynth.pyx", line 1891, in vapoursynth._CoreProxy.__getattr__
File "src/cython/vapoursynth.pyx", line 1754, in vapoursynth.Core.__getattr__
AttributeError: No attribute with the name lsmas exists. Did you mistype a plugin namespace?


thanks again, so much! (i promise to figure this out eventually.)
babag

l33tmeatwad
11th August 2021, 00:33
Assuming you compiled the plugin, did you move it to the /usr/local/lib folder to /usr/local/lib/vapoursynth? Almost all plugins will install to the regular lib directory. If any don't work after moving you can always move it back and create a symbolic link instead.

BabaG
11th August 2021, 04:48
i think this is the relevant set of commands that i followed:
cd $HOME/.installs

git clone https://github.com/l-smash/l-smash.git

cd l-smash

./configure --enable-shared

make lib

sudo make install-lib

i'm seeing these:
/usr/local/lib/liblsmash.a
/usr/local/lib/liblsmash.so
/usr/local/lib/liblsmash.so.2

nothing that looks like lsmash in the /usr/local/lib/vapoursynth directory.

thinking i should link the above three files into the /usr/local/lib/vapoursynth directory but will wait confirmation of that before i do something stoopid.

thanks,
babag

l33tmeatwad
11th August 2021, 05:28
No, that's just l-smash, the dependency for L-SMASH-Works (https://github.com/HolyWu/L-SMASH-Works) so it's in the correct directory.

kedautinh12
11th August 2021, 07:48
L-SMASH Works had new ver
https://github.com/AkarinVS/L-SMASH-Works

l33tmeatwad
11th August 2021, 15:08
L-SMASH Works had new ver
https://github.com/AkarinVS/L-SMASH-WorksThanks for the updated link, it's been forked so many times it's hard to keep up with, lol.

vcmohan
12th August 2021, 08:47
I am trying to install vapoursynth in my new hp laptop. R 51 download of .exe gives virus detected error. What should I do?

ChaosKing
12th August 2021, 08:51
Most likely a false positive. You can upload and check the file on virustotal.com
Btw R54 is the latest stable version.

vcmohan
12th August 2021, 12:25
r 54 64bit .exe also gives same problem

Myrsloik
12th August 2021, 12:36
r 54 64bit .exe also gives same problem

False positives all the way. All shitty antivirus software detects standard installers as viruses. Uninstall whatever shitty antivirus trial your new laptop came with and use the built in microsoft defender which doesn't make this kind of mistake.

l33tmeatwad
12th August 2021, 12:41
It appears there are some false positives on Virus Total, someone should probably follow-up with whatever's detecting it to have it removed. Weirdly, the second result only shows up for the 64-bit installer.

SecureAge APEX - Malicious
Qihoo-360 - Win32/Heur.Generic.HyoDv9kA

vcmohan
12th August 2021, 12:44
While in microsoft edge I did not have an option except to report it is safe, in Chrome it downloaded. On execution microsoft defender gave a no go banner but a path to bypass it was there. So I could execute it. I am having MCaffe anti virus also pre loaded. I think it may be superfluous.

Boulder
12th August 2021, 15:40
While in microsoft edge I did not have an option except to report it is safe, in Chrome it downloaded. On execution microsoft defender gave a no go banner but a path to bypass it was there. So I could execute it. I am having MCaffe anti virus also pre loaded. I think it may be superfluous.

You definitely don't want to have MS Defender and any other AV program in use simultaneously, it's just asking for trouble. MS Defender is good enough these days in my opinion.

BabaG
12th August 2021, 18:55
Assuming you compiled the plugin, did you move it to the /usr/local/lib folder to /usr/local/lib/vapoursynth? Almost all plugins will install to the regular lib directory. If any don't work after moving you can always move it back and create a symbolic link instead.
so, what is the filename for the file i should copy to vapoursynth directory? i didn't see a copy instruction in the guide.

thanks,
babag

l33tmeatwad
12th August 2021, 18:59
so, what is the filename for the file i should copy to vapoursynth directory? i didn't see a copy instruction in the guide.

thanks,
babag
In the guide I gave examples of how to compile and copy the plugin for each different method, refer to the instructions for the ffms2 plugin as an example.

BabaG
12th August 2021, 20:46
thanks again.

the example for ffms2 suggests using autogen.sh, which i did use in setting up ffms2. however, lsmash does not seem to have that. i do see that there is an example for ffms2 in which meson is used. i find a file, meson.build, in the L-SMASH-Works/VapourSynth directory so i cd'ed into that and tried following the steps in the guide under 'meson method.'

the first step there is:

meson build/

which returned this:
The Meson build system
Version: 0.53.2
Source dir: /home/babag/.installs/plugins/L-SMASH-Works/VapourSynth
Build dir: /home/babag/.installs/plugins/L-SMASH-Works/VapourSynth/build
Build type: native build
Project name: L-SMASH-Works
Project version: undefined
C compiler for the host machine: cc (gcc 9.3.0 "cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0")
C linker for the host machine: cc ld.bfd 2.34
Host machine cpu family: x86_64
Host machine cpu: x86_64
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Run-time dependency vapoursynth found: YES 54
Run-time dependency liblsmash found: YES 2.16.1 rev.1477
Dependency libavcodec found: NO found 58.54.100 but need: '>=58.91.0'
Did not find CMake 'cmake'
Found CMake: NO
Run-time dependency libavcodec found: NO

meson.build:41:0: ERROR: Invalid version of dependency, need 'libavcodec' ['>=58.91.0'] found '58.54.100'.

A full log can be found at /home/babag/.installs/plugins/L-SMASH-Works/VapourSynth/build/meson-logs/meson-log.txt

sounds like i have to figure out updating libavcodec? cmake?

thanks,
babag

l33tmeatwad
12th August 2021, 20:55
Seems like the latest LSMASHSource is looking for a newer version of LibAV than what your OS has in packages. You have two options, either compile FFmpeg yourself, or just use the version of LSMASHSource that I linked before instead of the updated one.

BabaG
12th August 2021, 21:06
You have two options, either compile FFmpeg yourself, or just use the version of LSMASHSource that I linked before instead of the updated one.

second option sounds more my speed. you mean the link from post #4334 to L-SMASH-Works?

edit:
just tried that and got the same error so i guess i'm unsure of what 'linked before' refers to.

thanks,
babag

l33tmeatwad
13th August 2021, 00:27
second option sounds more my speed. you mean the link from post #4334 to L-SMASH-Works?

edit:
just tried that and got the same error so i guess i'm unsure of what 'linked before' refers to.

thanks,
babagJust compile FFmpeg then, it's pretty simple.

BabaG
13th August 2021, 00:47
i really don't want to get into that. i have too much else that's dependent on it and all working fine. i really don't want to change it. getting the idea that vapoursynth is software better suited for rolling release distribution rather than lts one like i use. very disappointing. i really used to like avisynth and was hoping to get back into it in a modern context. i'm no admin or programmer, though. and haven't used windows for a few years either.

l33tmeatwad
13th August 2021, 00:54
You could just use ffms2.

BabaG
13th August 2021, 01:50
same error in vsedit:Failed to evaluate the script:
Python exception: No attribute with the name ffms2 exists. Did you mistype a plugin namespace?

plugin does seem to be in the right place:
file:///usr/local/lib/vapoursynth/libffms2.so

babag

Yomiko
13th August 2021, 05:14
In some systems /usr/local/lib is not a part of LD paths by default. Is it your case?

BabaG
13th August 2021, 06:32
sorry, LD?

LigH
13th August 2021, 08:58
Library directories for the compiler/linker workflow (see e.g. $LD_LIBRARY_PATH).

l33tmeatwad
13th August 2021, 14:28
Question, does Kubuntu use /usr/lib64? That could be the root of a lot of this confusion.

BabaG
13th August 2021, 18:37
there is a /usr/lib64 directory. nothing much in it. two shared libraries that don't seem vapoursynth related.
file:///usr/lib64/ld-linux-x86-64.so.2
file:///usr/lib64/libDaVinciPanelAPI.so


thanks,
babag

l33tmeatwad
14th August 2021, 15:52
You really need to just start troubleshooting things like trying to manually load plugins and such. VapourSynth either isn't looking in the /usr/local/lib/vapoursynth directory or ffms2 for some reason can't find it's dependencies.

Mystery Keeper
16th August 2021, 15:27
For all the people concerned with antivirus alerts.
Just upload the binaries here:
https://www.virustotal.com
Take Kaspersky as the most reliable.
Don't trust Avast or Norton. They're notorious for false positives.

ChaosKing
16th August 2021, 16:35
Norton just bought Avast for 8 billion!

lansing
19th August 2021, 21:43
I want to invoke a few filters in order programmatically, I want to reuse the VSMap that was returned from the invoke and the VSNodeRef.


VSMap * pResultMap = nullptr;

pResultMap = m_cpVSAPI->invoke(firstPlugin, filterName, pArgumentMap);
m_cpVSAPI->freeNode(pProcessingNode);
m_cpVSAPI->clearMap(pArgumentMap);

pProcessingNode = m_cpVSAPI->propGetNode(pResultMap, "clip", 0, nullptr);
m_cpVSAPI->freeMap(pResultMap);
pResultMap = nullptr;

// second filter
VSPlugin * secondPlugin = m_cpVSAPI->getPluginById(
"com.vapoursynth.std", m_pCore);
m_cpVSAPI->propSetNode(pArgumentMap, "clip", pProcessingNode, paReplace);


Will the `freeMap(pResultMap)` also killed my `pProcessingNode` so it won't get passed to the second filter?

Myrsloik
19th August 2021, 22:02
I want to invoke a few filters in order programmatically, I want to reuse the VSMap that was returned from the invoke and the VSNodeRef.


VSMap * pResultMap = nullptr;

pResultMap = m_cpVSAPI->invoke(firstPlugin, filterName, pArgumentMap);
m_cpVSAPI->freeNode(pProcessingNode);
m_cpVSAPI->clearMap(pArgumentMap);

pProcessingNode = m_cpVSAPI->propGetNode(pResultMap, "clip", 0, nullptr);
m_cpVSAPI->freeMap(pResultMap);
pResultMap = nullptr;

// second filter
VSPlugin * secondPlugin = m_cpVSAPI->getPluginById(
"com.vapoursynth.std", m_pCore);
m_cpVSAPI->propSetNode(pArgumentMap, "clip", pProcessingNode, paReplace);


Will the `freeMap(pResultMap)` also killed my `pProcessingNode` so it won't get passed to the second filter?

No, propGetNode() increases the reference count.

lansing
19th August 2021, 22:21
No, propGetNode() increases the reference count.

Thanks. Also do I even need the `pResultMap = nullptr;` after freeing it?

Myrsloik
19th August 2021, 22:29
Thanks. Also do I even need the `pResultMap = nullptr;` after freeing it?

No. That's obviously pointless.

Selur
21st August 2021, 18:28
Does anyone have a working RemoveDirtMC script for Vapoursynth ?
The one from https://forum.doom9.org/showpost.php?p=1711199&postcount=2 is using a variable called 'quad' which isn't defined anywhere.

Cu Selur

kedautinh12
22nd August 2021, 01:04
Here new RemoveDirtMC_SE.avsi
https://github.com/realfinder/AVS-Stuff/blob/Community/avs%202.5%20and%20up/RemoveDirtMC_SE.avsi

Selur
22nd August 2021, 08:06
@kedautinh12: Thanks, but you probably missed the 'for Vapoursynth' part,...

kedautinh12
22nd August 2021, 10:57
@kedautinh12: Thanks, but you probably missed the 'for Vapoursynth' part,...

I think you need port to Vapoursynth and i give you new ver for port

poisondeathray
22nd August 2021, 14:53
Does anyone have a working RemoveDirtMC script for Vapoursynth ?
The one from https://forum.doom9.org/showpost.php?p=1711199&postcount=2 is using a variable called 'quad' which isn't defined anywhere.

Cu Selur


Just replace "qpel" for "quad" . That version uses mv.compensate

There a couple other vapoursynth versions in this thread
https://forum.doom9.org/showthread.php?t=169771

Selur
22nd August 2021, 16:31
@poisondeathray: thanks :)

feisty2
23rd August 2021, 02:26
does the same frame/node/func always have the same VSFrameRef/VSNodeRef/VSFuncRef pointer?

lansing
23rd August 2021, 08:07
I'm a little confuse with the color matrix conversion

I want to convert from rec601 to rec709, if I specified both the input and output matrix, the clip info and frame info will give me matrix of rec709.

clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, matrix_in_s="470bg", matrix_s="709")

clip = core.text.ClipInfo(clip, alignment=7)
clip = core.text.FrameProps(clip, alignment=9)


But if I only specified the input matrix, both info will give me a matrix of Rec601?

clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, matrix_in_s="470bg")

Myrsloik
23rd August 2021, 09:27
does the same frame/node/func always have the same VSFrameRef/VSNodeRef/VSFuncRef pointer?

No, assume different pointers can point to the same thing.

Myrsloik
23rd August 2021, 09:31
I'm a little confuse with the color matrix conversion

I want to convert from rec601 to rec709, if I specified both the input and output matrix, the clip info and frame info will give me matrix of rec709.

clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, matrix_in_s="470bg", matrix_s="709")

clip = core.text.ClipInfo(clip, alignment=7)
clip = core.text.FrameProps(clip, alignment=9)


But if I only specified the input matrix, both info will give me a matrix of Rec601?

clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, matrix_in_s="470bg")


If no output matrix is specified it's assumed to be the same as the input. And as you probably know 470bg and 601 is the same thing.

Selur
24th August 2021, 20:15
Okay, I got RemoveGrainMC running and thought it would be nice wo have a version which can use SVP instead of MVTools. :)
Problem is I have no idea what I'm doing.
So here is my go at it:
import vapoursynth as vs
# dependencies:
# RemoveGrain (http://www.vapoursynth.com/doc/plugins/rgvs.html)
# MVTools (https://github.com/dubhater/vapoursynth-mvtools) or SVP libraries when gpu=True is used
# RemoveDirt (https://github.com/pinterf/removedirtvs)
# ChangeFPS (https://github.com/Selur/VapoursynthScriptsInHybrid/blob/master/ChangeFPS.py)


def RemoveDirt(input, repmode=16, remgrainmode=17, _grey=False, limit=10):
core = vs.get_core()
cleansed = core.rgvs.Clense(input)
sbegin = core.rgvs.ForwardClense(input)
send = core.rgvs.BackwardClense(input)
scenechange = core.rdvs.SCSelect(input, sbegin, send, cleansed)
alt = core.rgvs.Repair(scenechange, input, mode=[repmode,repmode,1])
restore = core.rgvs.Repair(cleansed, input, mode=[repmode,repmode,1])
corrected = core.rdvs.RestoreMotionBlocks(cleansed, restore, neighbour=input, alternative=alt, gmthreshold=70, dist=1, dmode=2, noise=limit, noisy=12, grey=_grey)
return core.rgvs.RemoveGrain(corrected, mode=[remgrainmode,remgrainmode,1])

def RemoveDirtMC(input, limit=6, _grey = False, block_size=8, block_over = 4, gpu=False):
core = vs.get_core()
quad = core.rgvs.RemoveGrain(input, mode=[12,0,1]) # blur the luma for searching motion vectors orig avs: mode=12, modeU=-1
if gpu:
# no clue what to do with _grey here, I assume it can be ignored
block_over = 0 if block_over == 0 else 1 if block_over == 2 else 2 if block_over == 4 else 3
Super = core.svp1.Super(quad, "{gpu:1,pel:2}")
bvec = core.svp1.Analyse(Super['clip'], Super['data'], input, "{ gpu:1, block:{w:"+str(block_size)+", h:"+str(block_size)+",overlap:"+str(block_over)+"} }")
fvec = core.svp1.Analyse(Super['clip'], Super['data'], input, "{ gpu:1, block:{w:"+str(block_size)+", h:"+str(block_size)+",overlap:"+str(block_over)+",special:{delta: 1}} }")
backw = core.svp2.SmoothFps(quad,Super['clip'], Super['data'],bvec['clip'],bvec['data'],"{}") # here the frame rate&count is doubled
forw = core.svp2.SmoothFps(quad,Super['clip'], Super['data'],fvec['clip'],fvec['data'],"{}") # here the frame rate&count is doubled
# since backw and forw now have twice the frame count I drop half the frames
backw = ChangeFPS.ChangeFPS(backw,input.fps_num,input.fps_den)
forw = ChangeFPS.ChangeFPS(forw,input.fps_num,input.fps_den)
else:
#block size of MAnalyze, blksize 8 is much better for 720x576 noisy source than blksize=16
#block overlapping of MAnalyze 0! 2 or 4 is not good for my noisy b&w 8mm film source
i = core.mv.Super(quad, pel=2)
bvec = core.mv.Analyse(super=i,isb=True, blksize=block_size,overlap=block_over, delta=1, truemotion=True, chroma= not _grey)
fvec = core.mv.Analyse(super=i,isb=False, blksize=block_size,overlap=block_over, delta=1, truemotion=True, chroma= not _grey)
backw = core.mv.Flow(clip=quad,super=i,vectors=[bvec])
forw = core.mv.Flow(clip=quad,super=i,vectors=[fvec])

clp = core.std.Interleave([backw,quad,forw])
clp = RemoveDirt(clp, remgrainmode=2, limit=limit,_grey=_grey)
clp = core.std.SelectEvery(clp,3,1)
return clp
A few things that seem kind of 'ugly' and are probably wrond:
a. I'm not using the _grey-parameter in the gpu case.
b. block_over in SVP only allows 0 - none, 1 - 1/8 of block size in each direction, 2 - 1/4 of block size, 3 - 1/2 of block size and I have no clue how I should handle this properly
b. when calculating backw and forw I end up with clips that have twice the number of frames which causes problems in the 'clp = core.std.Interleave([backw,quad,forw])', so I simply drop frames
-> would be nice if someone who actually understands what the cpu part of the script does could help 'fixing' this. :)


Cu Selur

Myrsloik
24th August 2021, 20:26
Okay, I got RemoveGrainMC running and thought it would be nice wo have a version which can use SVP instead of MVTools. :)
Problem is I have no idea what I'm doing.
So here is my go at it:
...
A few things that seem kind of 'ugly' and are probably wrond:
a. I'm not using the _grey-parameter in the gpu case.
b. block_over in SVP only allows 0 - none, 1 - 1/8 of block size in each direction, 2 - 1/4 of block size, 3 - 1/2 of block size and I have no clue how I should handle this properly
b. when calculating backw and forw I end up with clips that have twice the number of frames which causes problems in the 'clp = core.std.Interleave([backw,quad,forw])', so I simply drop frames
-> would be nice if someone who actually understands what the cpu part of the script does could help 'fixing' this. :)


Cu Selur

I think the grey argument is a leftover from the time when Avisynth didn't support greyscale clips and you passed YV12 instead. The correct solution is probably to remove it since if a user only want to process the Y plane only the Y plane will be passed to the function.

Also:
vs.get_core() => vs.core or just put vs.core everywhere instead of storing it in a variable.

And is this really correctly transcribed? I have no idea what it is in the original script but processing only Y and U plane looks iffy.
mode=[repmode,repmode,1]

TheSpectre
24th August 2021, 22:32
Hello. I'm having issues installing vapoursynth in Debian 11. It worked fine in Debian 10, but the update to Python 3.9 from 3.7 has caused me nothing but trouble. No matter where I install Vapoursynth to and what I set PYTHONPATH to, it always produces the following error: Failed to initialize VapourSynth environmentI've even followed l33tmeatwad's installation guide to a tee to no avail. Any ideas?

qyot27
25th August 2021, 02:10
Hello. I'm having issues installing vapoursynth in Debian 11. It worked fine in Debian 10, but the update to Python 3.9 from 3.7 has caused me nothing but trouble. No matter where I install Vapoursynth to and what I set PYTHONPATH to, it always produces the following error: I've even followed l33tmeatwad's installation guide to a tee to no avail. Any ideas?
VapourSynth:
sudo apt-get install checkinstall && \

git clone git://github.com/vapoursynth/vapoursynth.git && \
cd vapoursynth && \
autoreconf -fiv && \
CPPFLAGS="-march=native" LDFLAGS="-Wl,-Bsymbolic" ./configure --with-pic && \
make -j$(nproc) && \

sudo checkinstall --pkgname=vapoursynth --pkgversion="$(grep Version pc/vapoursynth.pc | \
sed 's/ /"/g' | cut -f2 -d "\"")"R-r"$(git rev-list --count HEAD)-g"$(git rev-parse --short HEAD)"" \
--backup=no --deldoc=yes --delspec=yes --deldesc=yes --strip=yes --stripso=yes \
--addso=yes --fstrans=no --default && \

sudo checkinstall --pkgname=vapoursynth-cython --pkgversion="$(grep Version pc/vapoursynth.pc | \
sed 's/ /"/g' | cut -f2 -d "\"")"R-r"$(git rev-list --count HEAD)-g"$(git rev-parse --short HEAD)"" \
--backup=no --deldoc=yes --delspec=yes --deldesc=yes --strip=yes --stripso=yes \
--addso=yes --fstrans=no --default --requires=vapoursynth python3 ./setup.py install

TheSpectre
25th August 2021, 03:17
VapourSynth:
sudo apt-get install checkinstall && \

git clone git://github.com/vapoursynth/vapoursynth.git && \
cd vapoursynth && \
autoreconf -fiv && \
CPPFLAGS="-march=native" LDFLAGS="-Wl,-Bsymbolic" ./configure --with-pic && \
make -j$(nproc) && \

sudo checkinstall --pkgname=vapoursynth --pkgversion="$(grep Version pc/vapoursynth.pc | \
sed 's/ /"/g' | cut -f2 -d "\"")"R-r"$(git rev-list --count HEAD)-g"$(git rev-parse --short HEAD)"" \
--backup=no --deldoc=yes --delspec=yes --deldesc=yes --strip=yes --stripso=yes \
--addso=yes --fstrans=no --default && \

sudo checkinstall --pkgname=vapoursynth-cython --pkgversion="$(grep Version pc/vapoursynth.pc | \
sed 's/ /"/g' | cut -f2 -d "\"")"R-r"$(git rev-list --count HEAD)-g"$(git rev-parse --short HEAD)"" \
--backup=no --deldoc=yes --delspec=yes --deldesc=yes --strip=yes --stripso=yes \
--addso=yes --fstrans=no --default --requires=vapoursynth python3 ./setup.py install

Same issue :(

TheSpectre
25th August 2021, 03:19
I've purged all installation remnants of Vapoursynth and I'll try the script again

TheSpectre
25th August 2021, 03:27
Manually importing Vapoursynth in a Python instance and checking the version works, but VSPipe doesn't. What the heck?

TheSpectre
25th August 2021, 03:45
I ran vspipe in a verbose Valgrind check and noticed these entries in particular right before Vapoursynth fails to initlise through vspipe. The full output can be found here https://controlc.com/8a255b52
--2369746-- Reading syms from /usr/local/lib/python3.9/dist-packages/VapourSynth-55-py3.9-linux-x86_64.egg/vapoursynth.cpython-39-x86_64-linux-gnu.so
--2369746-- object doesn't have a symbol table
--2369746-- Reading syms from /usr/local/lib/libvapoursynth.so
--2369746-- object doesn't have a symbol table
--2369746-- Reading syms from /usr/lib/x86_64-linux-gnu/libzimg.so.2.0.0
--2369746-- object doesn't have a symbol table
--2369746-- REDIR: 0x49380a0 (libstdc++.so.6:operator new(unsigned long)) redirected to 0x4838d80 (operator new(unsigned long))
--2369746-- Reading syms from /usr/lib/python3.9/lib-dynload/_ctypes.cpython-39-x86_64-linux-gnu.so
--2369746-- object doesn't have a symbol table
--2369746-- Reading syms from /usr/local/lib/libffi.so.7
--2369746-- object doesn't have a symbol table
Failed to initialize VapourSynth environment

qyot27
25th August 2021, 05:19
Did something happen to /etc/ld.so.conf that removed /usr/local/lib? As either running sudo ldconfig after installing or checkinstall as illustrated above (the addso=yes parameter specifically) should have made sure that step was completed.

You could also try and force it (assuming that libvapoursynth[-script].so is in /usr/local/lib):
LD_LIBRARY_PATH=/usr/local/lib vspipe --version

The thing that jumps out from the log though is this:
by 0x4E5586F: _PyEval_EvalFrameDefault (in /usr/local/lib/libpython3.9.so.1.0)
==2369746== by 0x4E09612: _PyFunction_Vectorcall (in /usr/local/lib/libpython3.9.so.1.0)
Why is it trying to look for libpython in /usr/local? The libpython3.9-dev package should have installed that stuff in /usr/lib/x86_64-linux-gnu (https://packages.debian.org/bullseye/amd64/libpython3.9-dev/filelist).

l33tmeatwad
25th August 2021, 15:43
Manually importing Vapoursynth in a Python instance and checking the version works, but VSPipe doesn't. What the heck?
Just tried it out on a fresh Debian 11 install and it worked fine, your install is an upgrade correct? It's possible that /usr/local/lib/python3.7 is still there, and if you copy/pasted the instructions with the * in it, it may have taken you there and you may not have setup site-packages to forward to dist-packages in the python3.9 folder.

TheSpectre
25th August 2021, 23:59
Just tried it out on a fresh Debian 11 install and it worked fine, your install is an upgrade correct? It's possible that /usr/local/lib/python3.7 is still there, and if you copy/pasted the instructions with the * in it, it may have taken you there and you may not have setup site-packages to forward to dist-packages in the python3.9 folder.

This is an upgraded installation, but I have purged all versions of Python other than 3.9

TheSpectre
26th August 2021, 00:07
The thing that jumps out from the log though is this:
by 0x4E5586F: _PyEval_EvalFrameDefault (in /usr/local/lib/libpython3.9.so.1.0)
==2369746== by 0x4E09612: _PyFunction_Vectorcall (in /usr/local/lib/libpython3.9.so.1.0)
Why is it trying to look for libpython in /usr/local? The libpython3.9-dev package should have installed that stuff in /usr/lib/x86_64-linux-gnu (https://packages.debian.org/bullseye/amd64/libpython3.9-dev/filelist).

It might have something to do with this https://wiki.debian.org/UsrMerge
Edit: Nevermind. This isn't related.

l33tmeatwad
26th August 2021, 00:15
I don't recall VapourSynth needing an egg, in fact I think I had a plugin once setup a vs egg and it conflicted with the main install. Try removing (or temporally relocating) /usr/local/lib/python3.9/dist-packages/VapourSynth-55-py3.9-linux-x86_64.egg, then if it's still failing remove and reinstall, but try R54 just for good measure.

TheSpectre
26th August 2021, 00:26
I don't recall VapourSynth needing an egg, in fact I think I had a plugin once setup a vs egg and it conflicted with the main install. Try removing (or temporally relocating) /usr/local/lib/python3.9/dist-packages/VapourSynth-55-py3.9-linux-x86_64.egg, then if it's still failing remove and reinstall, but try R54 just for good measure.

No luck. I've completely purged R55 and reinstalled R54 using qyot27's instructions, but still get the same bloody error :mad:

TheSpectre
26th August 2021, 00:31
At this rate, it may be better to either completely reinstall or do my encodes in a debootstrap chroot environment.

l33tmeatwad
26th August 2021, 00:32
Just to clarify, you did remove the VapourSynth egg and tried reinstalling again?

TheSpectre
26th August 2021, 00:34
Just to clarify, you did remove the VapourSynth egg and tried reinstalling again?

Correct :(

l33tmeatwad
26th August 2021, 00:38
Don't forget to sudo ldconfig after the install each time, Debian is funny like that. I would say do a complete purge of VapourSynth and make sure the egg is gone, then do a regular stock compile, no special extras, and then after the install do the ldconfig and try vspipe again. If that doesn't work a fresh install or alternative may be best *shrugs*

TheSpectre
26th August 2021, 00:47
Don't forget to sudo ldconfig after the install each time, Debian is funny like that. I would say do a complete purge of VapourSynth and make sure the egg is gone, then do a regular stock compile, no special extras, and then after the install do the ldconfig and try vspipe again. If that doesn't work a fresh install or alternative may be best *shrugs*

No luck. debootstrap it is :(
Thanks for trying to help me through Python Hell :thanks:

Selur
26th August 2021, 17:55
And is this really correctly transcribed? I have no idea what it is in the original script but processing only Y and U plane looks iffy.
mode=[repmode,repmode,1]
got it from https://forum.doom9.org/showthread.php?t=169771

Any opinion about the 'ChangeFPS' it's the main thing bothering me in the gpu part of the script where I'm totally unsure whether it makes sense. :)

Cu Selur

Ps.: uploaded the current RemoveDirt and a new SpotLess version to my Vapoursynth script collection (https://github.com/Selur/VapoursynthScriptsInHybrid/).

Quadratic
31st August 2021, 05:23
Since day one of using Vapoursynth, I have found the type hints included in the documentation to be rather confusing. Has there ever been any discussion on improving upon them?

Take Std.DeleteFrames() for instance https://vapoursynth.com/doc/functions/deleteframes.html
This is of very poor conveyance std.DeleteFrames(clip clip, int[] frames)
The hints from my environment are infinitely more useful: DeleteFrames: (clip: VideoNode, frames: int | Sequence[int]) -> VideoNode

Why is clip mentioned twice for all standard functions? Why are there commas after some square brackets? None if this is immediately clear and in my opinion only serves to confuse beginners. std.Crop(clip clip[,

Boulder
31st August 2021, 09:53
Since day one of using Vapoursynth, I have found the type hints included in the documentation to be rather confusing. Has there ever been any discussion on improving upon them?

Take Std.DeleteFrames() for instance https://vapoursynth.com/doc/functions/deleteframes.html
This is of very poor conveyance
The hints from my environment are infinitely more useful:

Why is clip mentioned twice for all standard functions? Why are there commas after some square brackets? None if this is immediately clear and in my opinion only serves to confuse beginners.

The format makes it easier for Avisynth users to adopt VapourSynth. I personally would not have understood the latter one, but the first one immediately tells me that the first argument is a clip to process and the next one needs some frame numbers.

ChaosKing
31st August 2021, 10:04
Why are there commas after some square brackets? None if this is immediately clear and in my opinion only serves to confuse beginners.

Looks like optional parameters to me.
The "simple" version is easier to read, especially when you have many parameters.

_Al_
31st August 2021, 20:03
Since day one of using Vapoursynth ...
The nature of python syntax, chaining attributes, functions where arguments could be optional or mandatory asks for an example to show nature of programing language - python. That web page should have examples with working script above it, including getting core and using correct syntax. Some functions have it (difficult ones). This would bring at least 50% more vapoursyth users. That was going thru my head , how many folks drop vapoursynth not succeding to make it work after one hour, or struggling with fcs syntax (like me)
import vapoursynth as vs
from vapoursynth import core
red = core.std.BlankClip(format=vs.RGB24, color=(255,0,0), length=1)
green = core.std.BlankClip(format=vs.RGB24, color=(0,255,0), length=1)
blue= core.std.BlankClip(format=vs.RGB24, color=(0,0,255), length=1)
clip = red + green + blue #clip with 3 frames, red,green and blue
no_green_frame = core.std.DeleteFrames(clip, 1)
no_green_frame.set_output(0)
just_green_frame = core.std.DeleteFrames(clip, [0,2])
just_green_frame.set_output(1)
Question is, who is going to do it, for example that web page, documentations. Myrsloik cannot be asked to do it. Or developers, same thing. It is up to some user that used to struggle with syntax to actually help and make it more clear for beginner to make a working script right away.

Myrsloik
31st August 2021, 20:44
The nature of python syntax, chaining attributes, functions where arguments could be optional or mandatory asks for an example to show nature of programing language - python. That web page should have examples with working script above it, including getting core and using correct syntax. Some functions have it (difficult ones). This would bring at least 50% more vapoursyth users. That was going thru my head , how many folks drop vapoursynth not succeding to make it work after one hour, or struggling with fcs syntax (like me)
import vapoursynth as vs
from vapoursynth import core
red = core.std.BlankClip(format=vs.RGB24, color=(255,0,0), length=1)
green = core.std.BlankClip(format=vs.RGB24, color=(0,255,0), length=1)
blue= core.std.BlankClip(format=vs.RGB24, color=(0,0,255), length=1)
clip = red + green + blue #clip with 3 frames, red,green and blue
no_green_frame = core.std.DeleteFrames(clip, 1)
no_green_frame.set_output(0)
just_green_frame = core.std.DeleteFrames(clip, [0,2])
just_green_frame.set_output(1)
Question is, who is going to do it, for example that web page, documentations. Myrsloik cannot be asked to do it. Or developers, same thing. It is up to some user that used to struggle with syntax to actually help and make it more clear for beginner to make a working script right away.

A bunch of getting started scripts as examples could be useful. Or general examples of how to use some of the most popular filters.

Speaking of documentation I'm kinda hoping for some nice person passing by to help with updating it for API4.

Myrsloik
2nd September 2021, 22:52
You should all go test the API4/audio builds now. Get it here: R55-API4-RC (https://github.com/vapoursynth/vapoursynth/releases)

Supports Python 3.8/win7 as well so no excuses.

It also performs better on most scripts and computers for those of you who don't care about audio. You'll most likely need to update some of your scripts to the latest version if you encounter errors.

A thread with more specific information is here (https://forum.doom9.org/showthread.php?t=183070). Some of it already outdated so start from the back.

This will probably be the main release branch in a week or two unless major problems appear.

Selur
3rd September 2021, 22:03
Do old plugins still work with the new version or do we need to have adjusted and recompiled plugins?

Myrsloik
3rd September 2021, 22:40
Do old plugins still work with the new version or do we need to have adjusted and recompiled plugins?

Should work properly with all old plugins.

Yomiko
4th September 2021, 01:49
Do you have a recommended size limit for frame property values?

Myrsloik
4th September 2021, 10:55
Do you have a recommended size limit for frame property values?

Not really. As long as you have the ram for it.

Yomiko
4th September 2021, 11:09
Nice. Would you like to attach ICC profiles of images as frame properties via imwri? Like here (https://github.com/YomikoR/VapourSynth-ICCConvert/blob/882e460b6896c4f3658ad6c7c4d17ee271aaf3fb/src/magick/magick.cc#L11-L15). The ->datum is unsigned char * so nothing will be fancy. Typically ICC profiles are from 1KB to 1MB. For preparation, it suffices to build ImageMagick with Little CMS (will add <500KB to the imwri dll) with MAGICKCORE_LCMS_DELEGATE macro checked when building imwri.

Myrsloik
4th September 2021, 11:30
Nice. Would you like to attach ICC profiles of images as frame properties via imwri? Like here (https://github.com/YomikoR/VapourSynth-ICCConvert/blob/882e460b6896c4f3658ad6c7c4d17ee271aaf3fb/src/magick/magick.cc#L11-L15). The ->datum is unsigned char * so nothing will be fancy. Typically ICC profiles are from 1KB to 1MB. For preparation, it suffices to build imwri with Little CMS (will add ~500KB to the plugin dll) with MAGICKCORE_LCMS_DELEGATE macro checked on build.

Sure, patches welcome I guess. As long as attaching it can be disabled and there's something interesting to do with the information.

l33tmeatwad
4th September 2021, 15:42
Was the ffms2 used with the tests a custom build or does the latest revisions on the main branch include VapourSynth audio support?

Myrsloik
4th September 2021, 16:11
Was the ffms2 used with the tests a custom build or does the latest revisions on the main branch include VapourSynth audio support?

No ffms2 builds have VS audio support. I'd actually recommend BestAudioSource instead unless it causes problems for you. If it does cause problems please do report them so I can try to improve it.

The ffms2 master branch has both API 3 and 4 support.

l33tmeatwad
4th September 2021, 16:18
I assume best audio source is included in VapourSynth?

DJATOM
4th September 2021, 16:29
No, considering the size.

Myrsloik
4th September 2021, 17:28
I assume best audio source is included in VapourSynth?

Binaries available here (https://github.com/vapoursynth/vapoursynth/releases/tag/R54-API4-test1).

l33tmeatwad
4th September 2021, 17:51
Was looking to compile for macOS, I assume the repository is up to date for BAS?

Myrsloik
4th September 2021, 18:23
Was looking to compile for macOS, I assume the repository is up to date for BAS?

Yes, should work. Haven't really tested it myself so feel free to submit fixes for annoying compile warning messages.

lansing
5th September 2021, 01:30
What is the difference between freeMap() and clearMap()? If I have a map that contains a video node and I want to delete it and reuse the map, do they both achieve the same thing?

Myrsloik
5th September 2021, 08:59
What is the difference between freeMap() and clearMap()? If I have a map that contains a video node and I want to delete it and reuse the map, do they both achieve the same thing?

clearMap only resets the map to its initial state (removes all values set in the map).

freeMap frees the actual map as well so then you'd have to allocate another one with createMap.

Myrsloik
5th September 2021, 15:28
Apparently vsrepo updates broke since my host now requires user agent headers to handle requests.
You can get a fixed vsrepo.py from here (https://github.com/vapoursynth/vsrepo/blob/master/vsrepo.py)

Selur
8th September 2021, 10:26
Downloaded "VapourSynth64-Portable-R55-API4-RC3.7z" from https://github.com/vapoursynth/vapoursynth/releases
looked inside the sdk/VapourSynth.h and it states:

#define VAPOURSYNTH_API_MAJOR 3
#define VAPOURSYNTH_API_MINOR 6

Did you forget to include the new headers with the portable version or am I missing something? Shouldn't it incude the API4?

Cu Selur

Myrsloik
8th September 2021, 10:36
Downloaded "VapourSynth64-Portable-R55-API4-RC3.7z" from https://github.com/vapoursynth/vapoursynth/releases
looked inside the sdk/VapourSynth.h and it states:

#define VAPOURSYNTH_API_MAJOR 3
#define VAPOURSYNTH_API_MINOR 6

Did you forget to include the new headers with the portable version or am I missing something? Shouldn't it incude the API4?

Cu Selur

Will be fixed

Selur
8th September 2021, 10:40
Okay, thanks!

Yomiko
10th September 2021, 07:14
Do you have a secret way to build a slim imwri.dll?

Selur
10th September 2021, 08:05
@Myrsloik: Do I see it right, that R55 will use API4 without any backward compatibility?

Boulder
10th September 2021, 08:28
I just found out that something happened between R53 and R54 which broke the function that calculates MDSI (found in muvsfunc.py). I used the exact same script and vsrepoed mvsfunc.py and muvsfunc.py to test. R53 works, R54 produces weird results.

More details here: https://forum.doom9.org/showthread.php?p=1951673#post1951673

Myrsloik
10th September 2021, 09:48
@Myrsloik: Do I see it right, that R55 will use API4 without any backward compatibility?

No. Get glasses.

Myrsloik
10th September 2021, 09:50
Do you have a secret way to build a slim imwri.dll?

By slim do you mean as a single dll? I think the one I distribute was cross compiled from linux by @jackoneill. No idea what trickery he used exactly but with visual studio it's probably near impossible to do.

Selur
10th September 2021, 10:51
No. Get glasses.
Okay, just read the 'Vaporusynth Editor 2' thread and it sounded like new R55 would require that viewers need to be updated. But good to know that is not the case and at least for R55 upgrading to the new API is optional.

Myrsloik
10th September 2021, 10:59
Okay, just read the 'Vaporusynth Editor 2' thread and it sounded like new R55 would require that viewers need to be updated. But good to know that is not the case and at least for R55 upgrading to the new API is optional.

The compatibility is more like this:
Plugins: 99% no change needed
Scripts: Minor changes needed if you used the deprecated get_core() function or YCOCG that's all removed. There are a few more smaller differences but a 2 minute change at most and many scripts are already adapted for it.
VSScript users: Most of them use the COMPAT* formats for output but they're removed. The rest is completely compatible.

Moral of the story: Planar formats FTW.

Selur
10th September 2021, 13:28
Okay, so at least most of the editor will need to be updated or they can't use R55.

Boulder
10th September 2021, 22:34
I just found out that something happened between R53 and R54 which broke the function that calculates MDSI (found in muvsfunc.py). I used the exact same script and vsrepoed mvsfunc.py and muvsfunc.py to test. R53 works, R54 produces weird results.

More details here: https://forum.doom9.org/showthread.php?p=1951673#post1951673

As this can be reproduced outside Zopti, I'll post here. Just use the test clip from the Zopti thread.

import vapoursynth as vs
import muvsfunc as muf
import mvsfunc as mvf

core = vs.core

orig = core.ffms2.Source(source=r"c:\zopti\strangerthings_s02e01.avi")

alternate = core.resize.Bicubic(orig, width=1280, height=640, filter_param_a=-0.7, filter_param_b=0.35)
alternate = core.resize.Bicubic(alternate, width=orig.width, height=orig.height, filter_param_a=0, filter_param_b=0.5)

orig = core.resize.Bicubic(orig, format=vs.RGB24, matrix_in_s='709')
alternate = core.resize.Bicubic(alternate, format=vs.RGB24, matrix_in_s='709')
clp = muf.MDSI(orig, alternate)
clp = core.text.FrameProps(clp)

clp.set_output()

Open the script in VapourSynth Editor and jump to frame 80.
R53 shows MDSI score 0.211945
R54 shows MDSI score 127114388.903713

There are several frames where this happens.

ChaosKing
10th September 2021, 22:53
Even simpler. I get also very high, almost random, numbers. Tested with R55.
clip=mvf.ToRGB(clip)
clip = muf.MDSI(clip, clip.text.Text("A"))
clip = core.text.FrameProps(clip)

Must be something related to Expr https://github.com/WolframRhodium/muvsfunc/blob/6abd811bfdab38fd75b90938522c17f6099b4695/muvsfunc.py#L4636

EDIT
It's OK with core.std.SetMaxCPU("none")

ChaosKing
10th September 2021, 23:08
If I replace the 3 expr lines https://github.com/WolframRhodium/muvsfunc/blob/6abd811bfdab38fd75b90938522c17f6099b4695/muvsfunc.py#L4713
core.std.Expr([ix_l1, iy_l1], ['x dup * y dup * + sqrt']) with something else (or the convolution line from above) , then the score shows the same value with/without cpu none.

Quadratic
16th September 2021, 16:18
Why does vspipe produce different errors based on the order of the script? This is a nightmare to debug...

Two scripts, the content is the same only the order is different. Both scripts "work", I can preview them in VSEdit, but vspipe errors.

import vapoursynth as vs
core = vs.core

clip = core.std.BlankClip(format=vs.RGBS)
clip2 = core.ffms2.Source('bunny_anim.gif')

rg = core.rgsf.RemoveGrain(clip, mode=1)

rg.set_output()

import vapoursynth as vs
core = vs.core

clip = core.std.BlankClip(format=vs.RGBS)

rg = core.rgsf.RemoveGrain(clip, mode=1)
clip2 = core.ffms2.Source('bunny_anim.gif')

rg.set_output()

AttributeError: No attribute with the name ffms2 exists. Did you mistype a plugin namespace?
AttributeError: No attribute with the name rgsf exists. Did you mistype a plugin namespace?

Myrsloik
16th September 2021, 16:19
Probably memory corruption somewhere in rgsf.

feisty2
16th September 2021, 21:38
remove grain mode 1 is the same as std.Convolution([1,2,1,2,4,2,1,2,1]), use that instead.
I haven't touched removegrain in years and I'm afraid I don't have time for this any time soon

Quadratic
17th September 2021, 07:40
Thank you for the prompt responses, but this does not give me an answer.

Running this script gives me an attribute error for ffms2
import vapoursynth as vs
core = vs.core

clip = core.std.BlankClip(format=vs.RGBS)
clip2 = core.ffms2.Source('bunny_anim.gif')

rg = core.fake.function(clip)

rg.set_output()
How can this be prevented? I can easily imagine this happening by mistake in a large script.

remove grain mode 1 is the same as std.Convolution([1,2,1,2,4,2,1,2,1]), use that instead.
I haven't touched removegrain in years and I'm afraid I don't have time for this any time soon

I understand and thanks, Convolutions have already been implemented where possible here: https://github.com/Irrational-Encoding-Wizardry/RgToolsVS

Unfortunately, there are some modules which contain functions that rely on rgsf.RemoveGrain/Repair such as https://lvsfunc.encode.moe/en/latest/

Maybe I can ask them to remove them but I don't know if there's any replacement filters which could be used in their stead.

poisondeathray
18th September 2021, 02:58
Why does vspipe produce different errors based on the order of the script? This is a nightmare to debug...

Two scripts, the content is the same only the order is different. Both scripts "work", I can preview them in VSEdit, but vspipe errors.

I don't get those vspipe error messages. It work ok for me on Windows

vspipe --info script.vpy gives no error message

Pipe into ffmpeg is also ok. eg. 1st script, no error message


import vapoursynth as vs
core = vs.core
core.std.LoadPlugin(r'PATH\RGSF_x64.dll')

clip = core.std.BlankClip(format=vs.RGBS)
clip2 = core.ffms2.Source(r'PATH\test.gif')

rg = core.rgsf.RemoveGrain(clip, mode=1)

rg.set_output()



vspipe script.vpy - | ffmpeg -f rawvideo -pix_fmt gbrpf32le -s 640x480 -r 24 -i - -an -f null NUL


Maybe your ffms2 version ? Or maybe different RGSF ? I am using old version r5, the most recent compiled binary on github

Quadratic
19th September 2021, 07:22
I noticed that all third-party plugins were now broken, I spent the entire night removing everything Vapoursynth related from my system (scorched earth) and reinstalling everything.

Things are working again, including core.rgsf.RemoveGrain. I still do not know the root cause.

Thanks and apologies for my behavior.

Myrsloik
21st September 2021, 09:42
New release. Now the API4 builds are the normal builds. Audio support and performance for everyone!
Also windows 7 support is back since you can use both python 3.8 and 3.9 now.

Full blog post with the changes here (http://www.vapoursynth.com/2021/09/r55-audio-support-and-improved-performance/).

For the more conservative of you there's R55-API3 which is the same as R54 with a few bug fixes.

Have fun reporting bugs.

Izuchi
22nd September 2021, 06:21
It doesn't seem like imwri is included in vsrepo, nor is it included with the R55 build so how can we get it exactly?

Edit: As a temporary solution, I copied the imwri binary from R54 API4 test1 build.

Myrsloik
22nd September 2021, 07:38
It doesn't seem like imwri is included in vsrepo, nor is it included with the R55 build so how can we get it exactly?

Edit: As a temporary solution, I copied the imwri binary from R54 API4 test1 build.

Basically producing single dll windows builds is hard. What would be really helpful is if someone contributed an imagemagick port to vcpkg so I can easily do the rest myself.
Alternatively someone could use mingw/cross compile a single dll and contribute that.

Simply grab it from the R55 api3 portable archive if you really need it for now.

Myrsloik
22nd September 2021, 13:14
What to do with https://github.com/vapoursynth/vs-imwri/blob/c961cd3adf9ca77eb580e2d2ee58d8c1fbbacd04/src/imwri.cpp#L40-L41 and https://github.com/vapoursynth/vs-imwri/blob/c961cd3adf9ca77eb580e2d2ee58d8c1fbbacd04/src/imwri.cpp#L45? Could you clean them first?

Probably cleaned up now.

ChaosKing
23rd September 2021, 09:06
@Myrsloik Could you check if the vsrepo addgrain commit is the "correct" way of upgrading a plugin to hybrid api4 / api3 releases?

Myrsloik
23rd September 2021, 09:10
@Myrsloik Could you check if the vsrepo addgrain commit is the "correct" way of upgrading a plugin to hybrid api4 / api3 releases?

It's not. See the correct place to specify api version here:
https://github.com/vapoursynth/vsrepo/commit/67ac70c35e82f593c7c7770879a1ea4af78360c4

ChaosKing
23rd September 2021, 09:18
Thx. Kinda missed the example package.

NullNix
23rd September 2021, 13:49
Hm. OK so after a bit of thrashing around creating new meson build systems for eedi3, miscfilters and removegrain, and diking out vs.YCOCG and vs.COMPAT from everywhere, I've tried current master out (commit ae11137cdf4605) with my own slightly-hacked-about copy of the wonderfully effective, unfortunately long-vanished-from-the-net G41Fun.RemoveGrain2. It seems to work!

But... I am sorry to report that rather than being 10% faster, with this workload v55 is consistently about 10% *slower* than v54 was, at 6.3fps rather than 6.9. I'll do some profiling and figure out where the speed is going :( perhaps a Broadwell-EX is not a "modern" CPU, but given that Intel are (still!) selling fairly-high-end servers with this CPU it's certainly not old. I was hoping for a speedup, dammit! *throws toys out of pram* (cost of pram: $0; obligations of pram manufacturer: nil, so I'll track this down rather than whining: or I'll try to: given how nondeterministic modern CPUs are, I'm not confident it'll be possible to identify a cause).

(This is using Python 3.9.7, Cython 0.29.24 and GCC off the 10 release branch as of May 21: not exactly a new GCC, but the rest is pretty up-to-date.)

Myrsloik
23rd September 2021, 13:51
Hm. OK so after a bit of thrashing around creating new meson build systems for eedi3, miscfilters and removegrain, and diking out vs.YCOCG and vs.COMPAT from everywhere, I've tried current master out (commit ae11137cdf4605) with my own slightly-hacked-about copy of the wonderfully effective, unfortunately long-vanished-from-the-net G41Fun.RemoveGrain2. It seems to work!

But... I am sorry to report that rather than being 10% faster, with this workload v55 is consistently about 10% *slower* than v54 was, at 6.3fps rather than 6.9. I'll do some profiling and figure out where the speed is going :( perhaps a Broadwell-EX is not a "modern" CPU, but given that Intel are (still!) selling fairly-high-end servers with this CPU it's certainly not old. I was hoping for a speedup, dammit! *throws toys out of pram* (cost of pram: $0; obligations of pram manufacturer: nil, so I'll track this down rather than whining: or I'll try to: given how nondeterministic modern CPUs are, I'm not confident it'll be possible to identify a cause).

(This is using Python 3.9.7, Cython 0.29.24 and GCC off the 10 release branch as of May 21: not exactly a new GCC, but the rest is pretty up-to-date.)

Performance problems have been located. R56 will be faster again.

NullNix
23rd September 2021, 14:47
Performance problems have been located. R56 will be faster again.

Aha great! If you need confirmation I'm happy to test. I'm just happy that a change of this magnitude broke so little! Nice backward compat, that.

In the meantime I have possible speedups in fftw -- ha ha like I can wring any more speed out of that, but some possibilities have occurred to me which I should investigate -- and maybe possibly in removegrain, which may be obsolete but is still costing me 4% of my CPU time doing a lot of insertion sorts :)

I might well be able to rope in some floating-point demigods whose shoes I am not fit to clean as well. Gosh it's convenient that my coworkers are spending time speeding up libm right now and are also interested in fftw. Why yes $MEGACORP it is a great use of your employees' time to speed up mathematical operations if it means that I can get a properly denoised blu-ray Red Dwarf set a day earlier than otherwise. YES IT IS.

(it will probably speed up a bunch of other simulation work too. And everyday use, apparently, though it escapes me how much everyday use needs FFTs and complex arithmetic. Denoisers in the sound domain, I suppose, though most of those are in hardware. And jpeg etc, I guess, though again those tend to implement their own stuff rather than using anything in libm, let alone fftw.)

NullNix
24th September 2021, 19:00
Hm. OK so after a bit of thrashing around creating new meson build systems for eedi3, miscfilters and removegrain, and diking out vs.YCOCG and vs.COMPAT from everywhere, I've tried current master out (commit ae11137cdf4605) with my own slightly-hacked-about copy of the wonderfully effective, unfortunately long-vanished-from-the-net G41Fun.RemoveGrain2. It seems to work!

I spoke too soon. --timecodes appears to be doing nothing. We get a timecodes file but it is always empty in my testing, as if outputError got set, but no error messages are displayed.

I'll look at it tomorrow (exhausted right now after LPC or I'd do it now), because I swear this worked in my first testing...

NullNix
24th September 2021, 20:00
I spoke too soon. --timecodes appears to be doing nothing. We get a timecodes file but it is always empty in my testing, as if outputError got set, but no error messages are displayed.

I'll look at it tomorrow (exhausted right now after LPC or I'd do it now), because I swear this worked in my first testing...

ok this is obvious, fixed :) PR submitted.

Selur
25th September 2021, 00:52
Does anyone have a Windows 64bit build of https://github.com/VFR-maniac/VapourSynth-ReduceFlicker ?

Yomiko
25th September 2021, 13:11
The link to isxdl.dll for building an installer is now redirected to "Inno Setup Dependency Installer". I ended up finding it from istool.

vxzms
26th September 2021, 00:14
Does anyone have a Windows 64bit build of https://github.com/VFR-maniac/VapourSynth-ReduceFlicker ?

You may be need https://github.com/chikuzen/ReduceFlicker

kedautinh12
26th September 2021, 01:55
You may be need https://github.com/chikuzen/ReduceFlicker

It's avisynth ver

poisondeathray
26th September 2021, 02:24
It's avisynth ver

it also has vapoursynth folder

https://github.com/chikuzen/ReduceFlicker/tree/master/vapoursynth

ChaosKing
26th September 2021, 09:53
The release dll is only for avisynth.

Myrsloik
26th September 2021, 14:54
The link to isxdl.dll for building an installer is now redirected to "Inno Setup Dependency Installer". I ended up finding it from istool.

Fixed. It's no longer needed.

Selur
27th September 2021, 04:26
On Windows 10 64bit with https://www.videohelp.com/software/HuffYUV 64bit installed.
Opening a "Authors.avi" (https://drive.google.com/file/d/1-25kJLVqpVsPjTigDQLD3eppGSSLUyQR/view?usp=sharing) using R54-API3 portable with AviSource I get "AVISource: couldn't locate a decompressor for fourcc ffds".
MediaInfo reports:
Video
Count : 377
Count of stream of this kind : 1
Kind of stream : Video
Kind of stream : Video
Stream identifier : 0
StreamOrder : 0
ID : 0
ID : 0
Format : HuffYUV
Format : HuffYUV
Commercial name : HuffYUV
Format version : Version 2
Codec ID : HFYU
Duration : 20000
Duration : 20 s 0 ms
Duration : 20 s 0 ms
Duration : 20 s 0 ms
Duration : 00:00:20.000
Duration : 00:00:20:00
Duration : 00:00:20.000 (00:00:20:00)
Bit rate : 27747450
Bit rate : 27.7 Mb/s
Width : 448
Width : 448 pixels
Height : 448
Height : 448 pixels
Pixel aspect ratio : 1.000
Display aspect ratio : 1.000
Display aspect ratio : 1.000
Frame rate : 25.000
Frame rate : 25.000 FPS
Frame count : 500
Color space : YUV
Chroma subsampling : 4:2:0
Chroma subsampling : 4:2:0
Bit depth : 8
Bit depth : 8 bits
Scan type : Progressive
Scan type : Progressive
Bits/(Pixel*Frame) : 5.530
Stream size : 69368624
Stream size : 66.2 MiB (100%)
Stream size : 66 MiB
Stream size : 66 MiB
Stream size : 66.2 MiB
Stream size : 66.16 MiB
Stream size : 66.2 MiB (100%)
Proportion of this stream : 0.99971
Opening the file in 64bit VirtualDub2 works fine.
Registry "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32" also lists "VIDC.HFYU".
Opening another file (https://drive.google.com/file/d/1GXGgyfiboPBrQrPWh9-ZlYArIgOcRoxQ/view?usp=sharing):
Video
Count : 377
Count of stream of this kind : 1
Kind of stream : Video
Kind of stream : Video
Stream identifier : 0
StreamOrder : 0
ID : 0
ID : 0
Format : HuffYUV
Format : HuffYUV
Commercial name : HuffYUV
Format version : Version 2
Codec ID : HFYU
Duration : 2503
Duration : 2 s 503 ms
Duration : 2 s 503 ms
Duration : 2 s 503 ms
Duration : 00:00:02.503
Duration : 00:00:02;15
Duration : 00:00:02.503 (00:00:02;15)
Bit rate : 56155667
Bit rate : 56.2 Mb/s
Width : 720
Width : 720 pixels
Height : 480
Height : 480 pixels
Pixel aspect ratio : 1.000
Display aspect ratio : 1.500
Display aspect ratio : 3:2
Frame rate : 29.970
Frame rate : 29.970 (30000/1001) FPS
FrameRate_Num : 30000
FrameRate_Den : 1001
Frame count : 75
Standard : NTSC
Color space : YUV
Chroma subsampling : 4:2:2
Chroma subsampling : 4:2:2
Bit depth : 8
Bit depth : 8 bits
Scan type : Interlaced
Scan type : Interlaced
Bits/(Pixel*Frame) : 5.422
Delay : 0
Delay : 00:00:00.000
Stream size : 17566212
Stream size : 16.8 MiB (97%)
Stream size : 17 MiB
Stream size : 17 MiB
Stream size : 16.8 MiB
Stream size : 16.75 MiB
Stream size : 16.8 MiB (97%)
Proportion of this stream : 0.97199
works fine.

-> Can someone explain this?

Cu Selur

qyot27
27th September 2021, 10:34
HuffYUV only supports YUY2 and RGB(24|32). YV12 - and any of the other pix_fmts - is only a part of ffvhuff.

The FourCC 'ffds' == ffdshow. That first file was probably encoded by (or to be compatible with) ffdshow's VFW codec.

Yomiko
27th September 2021, 10:37
vs-removegrain has SIMD codes the meson script didn't consider. Maybe I will send a PR in a week.

Selur
27th September 2021, 17:16
HuffYUV only supports YUY2 and RGB(24|32). YV12 - and any of the other pix_fmts - is only a part of ffvhuff.

The FourCC 'ffds' == ffdshow. That first file was probably encoded by (or to be compatible with) ffdshow's VFW codec.
I thought the "Codec ID" of MediaInfo would show the fourcc.

richardpl
27th September 2021, 17:42
Both files decodes just fine with recent mpv/ffmpeg.

Selur
27th September 2021, 18:35
yeah, but that does not help with AviSource at all,...

Myrsloik
29th September 2021, 12:31
R56 released. A pile of fixes. Should be safe for general use now.

Selur
29th September 2021, 14:13
Thanks?
Will there be a R56-API3 portable release?

Cu Selur

Myrsloik
29th September 2021, 14:33
Thanks?
Will there be a R56-API3 portable release?

Cu Selur

No, there are no relevant changes for API3. Maybe next time. Go find bugs.

poisondeathray
29th September 2021, 16:26
Does core.avisource.AVISource work in API4?

I get "AttributeError: No attribute with the name avisource exists. Did you mistype a plugin namespace?"

ChaosKing
29th September 2021, 16:41
Does core.avisource.AVISource work in API4?

I get "AttributeError: No attribute with the name avisource exists. Did you mistype a plugin namespace?"

vsrepo install avisource

It's an external plugin now.

_Al_
29th September 2021, 17:23
Is there a list what plugins were taken out using API4?
I guess what is missing from core directory,.
What plugins hide under MiscFilters.dll?

Myrsloik
29th September 2021, 17:26
Is there a list what plugins were taken out using API4?

All of them. If you can't name them all here's the api3 source:
https://github.com/vapoursynth/vapoursynth/tree/api3/src/filters

_Al_
29th September 2021, 17:27
ok, thanks

lansing
29th September 2021, 17:27
R56 fixed the slow format conversion issue in R55, now the speed is back to the same as R54. Benchmarked with vspipe on 8000 frames of a 4K video.

vspipe 4k-video.vpy .


R54 R55 R56
4K original 191 147 198
4K => RGB24 183 141 185
4K => RGB30 165 130 173
4K => RGB48 174 127 175
4K => RGBS 155 87 157

l33tmeatwad
29th September 2021, 19:56
I've been a bit too busy to really keep up and I haven't been able to find an answer through my searching. For the filters listed as obsolete (vinverse, morpho, etc), did something replace those?

NullNix
29th September 2021, 20:29
R56 released. A pile of fixes. Should be safe for general use now.

Hm. I'm sorry to report that for my 1080p usage we are still a bit slower than R54 :( down from 6.9fps to 6.4, though better than R55's 6.2. I'll do some profile comparisons and try to figure out why. (A bit irritating to do, what with all the plugins needing downgrading too, but them's the breaks etc. I don't expect anyone to be able to diagnose it from *this* pathetic excuse for a problem report. That's on me.)

DJATOM
29th September 2021, 20:51
I'd suggest to create portable r54 and r56 and compare them without re-installation. You know, windows likes to cache dlls so you have to reboot across re-installs or might measure the wrong results.

l33tmeatwad
29th September 2021, 21:14
Having a weird issue with imwri, it appears to not autoload, but if I manually load it it works fine.

Myrsloik
29th September 2021, 21:27
I've been a bit too busy to really keep up and I haven't been able to find an answer through my searching. For the filters listed as obsolete (vinverse, morpho, etc), did something replace those?

avisource: ffms2 more or less, it works perfectly for avi
vinverse: only supports 8 bit and is very rarely used, I think havsfun (or some other big script) has a version that supports higher bitdepths in script form
morpho: maximum/minimum unless you want a weird shape, if you want a weird shape you're probably better of writing a faster plugin for that
miscfilters: averageframes was moved to the core, scdetect can be written as ~5 lines of script so it's pointless and Hysteresis is in a weird limbo where I just don't know what to do with it. A few things use it but it's too specific. So now it's a zombie filter.
eedi3: eedi3m which is much faster

NullNix
29th September 2021, 23:28
I'd suggest to create portable r54 and r56 and compare them without re-installation. You know, windows likes to cache dlls so you have to reboot across re-installs or might measure the wrong results.

Oh god that sounds awful: presumably clearing the cache requires involuntary blood donations or something like that, too (yeah, looking around the net, it seems to: there are at least three different sorts of cache and everyone seems to be arguing over whether most of them need flushing or even exist at all).

But no, this is a Linux-from-scratch box with most software installed via the Nix package manager[1] :) not very Windows-like at all, nor honestly very much like a normal Linux system, and thankfully quite amenable to this sort of "oh dammit I wanted to go back to $oldthing" approach. Indeed the old vapoursynth is still there and so are all its plugins: it doesn't get deleted until a month or so after I replace it, and I can go back at any time.

So I'm really whining for no reason at all and I should stop.

(Only downside: I work on tracing and debugging and profiling tools, so profiling vapoursynth is entirely too much like work! upside: I might be able to use it as a testcase for the tools I work on, and then it actually is work! :) )

[1] no relation

Myrsloik
30th September 2021, 15:09
With R56 released things are now stable enough I think the long conversion to API4 for most plugins can start. But not all types of plugins really benefit at all so here's a short summary of where you'll see actual differences. The main advantage of API4 is the reduced cache bloat in some instances and somewhat cleaner plugin API in general.

Plugins that definitely benefit:

Pure spatial filters - memory usage reduction
Frame reordering plugins where frames aren't reused (trim, splice, deleteframes style) - memory usage reduction
Source filters - alpha handling was changed (should now simply be attached as _Alpha instead of multi clip output) and nfMakeLinear deprecated (but still respected)
Filters (sources excluded) that use nfMakeLinear - need to use the new API to make things more linear again


Plugins nobody will know notice if you change:

Source filters that don't return alpha
Temporal filters
Frame reordering filter that reuses frames (freezeframe, separatefields)

MythCreator
1st October 2021, 14:22
mvsfunc raised an exception"module vapoursynth has no attribute 'YCgCo'", is it deleted or replaced by something else?

Julek
1st October 2021, 16:17
mvsfunc raised an exception"module vapoursynth has no attribute 'YCgCo'", is it deleted or replaced by something else?

https://github.com/AmusementClub/mvsfunc

MythCreator
1st October 2021, 17:31
https://github.com/AmusementClub/mvsfunc

Thx:D

Selur
2nd October 2021, 22:40
What am I missing:
# Loading J:\test.avi using LWLibavSource
clip = core.lsmas.LWLibavSource(source="J:/test.avi", format="YUV420P8", cache=0, prefer_hw=0)
# making sure input color matrix is set as 2020cl
clip = core.resize.Bicubic(clip, matrix_in_s="2020cl",range_s="limited")
# making sure frame rate is set to 29.970
clip = core.std.AssumeFPS(clip=clip, fpsnum=30000, fpsden=1001)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# adjusting color space from YUV420P8 to RGBS
clip = core.resize.Bicubic(clip=clip, format=vs.RGBS, matrix_in_s="2020cl", range_s="limited")
clip.set_output()

fails with:
Resize error: Resize error 3074: invalid colorspace definition (10/2/2 => 0/2/2). May need to specify additional colorspace parameters.
if I use replace:
clip = core.resize.Bicubic(clip=clip, format=vs.RGBS, matrix_in_s="2020cl", range_s="limited")
with
clip = core.resize.Bicubic(clip=clip, format=vs.RGBS, matrix_in_s="2020ncl", range_s="limited")
decoding works. (Using R55 API3.6)

Cu Selur

Julek
3rd October 2021, 03:32
Try add a transfer_in_s

clip = core.resize.Bicubic(clip=clip, format=vs.RGBS, matrix_in_s="2020cl", transfer_in_s='2020_10', range_s="limited")

Selur
3rd October 2021, 10:04
@Julek: That worked. Thanks.
@devs: it would be reall helpfull if Vapoursynth could give a more specific error message.

Cu Selur

_Al_
4th October 2021, 03:04
Is there a way to run avisynth+ using vapoursynth portable, without installing avisynth? I have only 64bit AviSynth.dll and DevIL.dll they are both in same directory as Vapoursynth is.
I get:
Import: failed to get avisynth.dll
using still API3 not latest API4:
source_path = "avisynth_script.avs"
core.std.LoadPlugin('vsavsreader.dll')
clip = core.avsr.Import(source_path)
if isinstance(clip, tuple):
clip=clip[0]
Is there a way to use avisynth.dll, make avisynth+ work without putting it somewhere in windows directory or install it? To have it in a portable setup?

Myrsloik
6th October 2021, 19:07
R57-RC1 is out (https://github.com/vapoursynth/vapoursynth/releases/tag/R57-RC1)

r57:
fixed nodes never being marked as nfnocache/nfiscache in api3 which caused some older applications to enter an infinite cache insertion loop
fixed memory bloat in python due to circular references when dealing with frame objects
fixed vsrepo missing genstubs files
fixed vfw and avfs speed regression from r55

DJATOM
6th October 2021, 20:00
Is there a way to run avisynth+ using vapoursynth portable, without installing avisynth? I have only 64bit AviSynth.dll and DevIL.dll they are both in same directory as Vapoursynth is.
I get:
Import: failed to get avisynth.dll
using still API3 not latest API4:
source_path = "avisynth_script.avs"
core.std.LoadPlugin('vsavsreader.dll')
clip = core.avsr.Import(source_path)
if isinstance(clip, tuple):
clip=clip[0]
Is there a way to use avisynth.dll, make avisynth+ work without putting it somewhere in windows directory or install it? To have it in a portable setup?

You can try that
import ctypes

ctypes.CDLL('path/to/avs_plus/dll')

Myrsloik
6th October 2021, 20:31
Is there a way to run avisynth+ using vapoursynth portable, without installing avisynth? I have only 64bit AviSynth.dll and DevIL.dll they are both in same directory as Vapoursynth is.
I get:
Import: failed to get avisynth.dll
using still API3 not latest API4:
source_path = "avisynth_script.avs"
core.std.LoadPlugin('vsavsreader.dll')
clip = core.avsr.Import(source_path)
if isinstance(clip, tuple):
clip=clip[0]
Is there a way to use avisynth.dll, make avisynth+ work without putting it somewhere in windows directory or install it? To have it in a portable setup?

I suspect it'll work if you put avisynth.dll in the same dir as the script. Or just modify the PATH before running commands and add whatever location there.

_Al_
7th October 2021, 16:04
That really works, thank you!
import ctypes
ctypes.CDLL('./AviSynth.dll')
core.std.LoadPlugin('vsavsreader.dll')
clip = core.avsr.Import('source.avs')
if isinstance(clip, (tuple,list)):
clip = clip[0]
Avisynth plugins need to be loaded in Avisynth script

Can be avs script loaded to vapoursynth now, is it built in, I could not figure it out if it is, or still that Chikuzen vsavsreader.dll needs to be used?

Selur
9th October 2021, 15:13
downloaded "Windows embeddable package (64-bit)" from https://www.python.org/downloads/release/python-3100/
extracted it into a folder named 'Vapoursynth'
downloaded "VapourSynth64-Portable-R57-RC1" from https://github.com/vapoursynth/vapoursynth/releases
extracted it into the same folder, overwrote everything it wanted

called VSPipe and got "Failed to initialize VSScript" (same worked fine when using Python 3.9.6 from https://www.python.org/downloads/release/python-396/)
My guess is that this is just a limitation of the portable Vapoursynth (is it?) and a new 'vapoursynth.cp310-win_amd64.pyd' instead of the current 'vapoursynth.cp39-win_amd64.pyd' would be needed.
-> Any plans to switch to Pyhton 3.10 in the near future?

Cu Selur

Myrsloik
9th October 2021, 17:56
downloaded "Windows embeddable package (64-bit)" from https://www.python.org/downloads/release/python-3100/
extracted it into a folder named 'Vapoursynth'
downloaded "VapourSynth64-Portable-R57-RC1" from https://github.com/vapoursynth/vapoursynth/releases
extracted it into the same folder, overwrote everything it wanted

called VSPipe and got "Failed to initialize VSScript" (same worked fine when using Python 3.9.6 from https://www.python.org/downloads/release/python-396/)
My guess is that this is just a limitation of the portable Vapoursynth (is it?) and a new 'vapoursynth.cp310-win_amd64.pyd' instead of the current 'vapoursynth.cp39-win_amd64.pyd' would be needed.
-> Any plans to switch to Pyhton 3.10 in the near future?

Cu Selur

You need to recompile vsscript.dll as well to accomplish that, not just the python module.

Maybe I'll switch for R58. Or later.

Selur
9th October 2021, 18:46
Ah, okay good to know.
Thanks for the info.

Cu Selur

Selur
9th October 2021, 20:36
with API4:
"clip = FFDNet(clip=clip)" -> "'vapoursynth.VideoFrame' object has no attribute 'get_read_array'"
"clip = core.ttmpsm.TTempSmooth(clip=clip)" -> crashes without error
also can't find Win64 binaries for vinverse and morpho

Cu Selur

Myrsloik
9th October 2021, 22:06
with API4:
"clip = FFDNet(clip=clip)" -> "'vapoursynth.VideoFrame' object has no attribute 'get_read_array'"
"clip = core.ttmpsm.TTempSmooth(clip=clip)" -> crashes without error
also can't find Win64 binaries for vinverse and morpho

Cu Selur

get_read_array <= was deprecated, either use the new memory view or get_read_ptr
core.ttmpsm.TTempSmooth(clip=clip) <= Assumes miscfilters always is installed, crashes if not

Selur
9th October 2021, 22:43
core.ttmpsm.TTempSmooth(clip=clip) <= Assumes miscfilters always is installed, crashes if not
Thanks that helped.

get_read_array <= was deprecated, either use the new memory view or get_read_ptr
Not sure what to make of that, it it a bug in the viewer I use (https://github.com/YomikoR/VapourSynth-Editor) or in the filter?

Cu Selur

DJATOM
9th October 2021, 23:16
In the filter.

_Al_
9th October 2021, 23:36
that filter needs to change f.get_read_array(plane_number) to f[plane_number]
in API4, in python, there is an access to a plane view using slicing now

Selur
10th October 2021, 08:05
Ah okay, thanks for clearing that up. :)

Jukus
10th October 2021, 23:21
After the last updates VS is consuming 3-4 times less RAM than before!? That's awesome.

Selur
11th October 2021, 18:39
I had a few times where Only wanted to apply a specific filter to only a portion of a frame for only a few frames and I was wondering whether someone already worte a general function for this.
Something along the lines of:
function applyToRectangle(clip, functionPointer, funcitonarguments[], x, y, width, height)
or even better
function applyTotRectangleAndRange(clip, functionPointer, funcitonarguments[], x, y, width, height, start, end)
.

Cu Selur

ChaosKing
11th October 2021, 19:10
See https://github.com/Irrational-Encoding-Wizardry/Vapoursynth-RemapFrames
or
vsrepo install remap

lansing
11th October 2021, 19:12
I had a few times where Only wanted to apply a specific filter to only a portion of a frame for only a few frames and I was wondering whether someone already worte a general function for this.
Something along the lines of:
function applyToRectangle(clip, functionPointer, funcitonarguments[], x, y, width, height)
or even better
function applyTotRectangleAndRange(clip, functionPointer, funcitonarguments[], x, y, width, height, start, end)
.

Cu Selur

RemapFrames (https://github.com/Irrational-Encoding-Wizardry/Vapoursynth-RemapFrames)

Run your function on the filtered clip and then remap the frames you want to the original.

_Al_
11th October 2021, 23:20
I know, I know :-), here is solution in python, I added a selection for that filter remapping:
https://github.com/UniversalAl/animate

example:
import vapoursynth as vs
from vapoursynth import core
import animate

def blur(clip,*args):
return clip.std.BoxBlur()

MAP = [ #ranges can overlap
(60, 100), [animate.Crossfade(None, blur)], #fade in filter
(101,200), [blur],
(201,250), [animate.Crossfade(blur, None)], #fade out filter
]

clip = core.lsmas.LibavSMASHSource('source.mp4')
#if selection argument is passed: (width, height, left,top)
clip = animate.run(clip, MAP, selection=(300,200,50,90))
clip.set_output()

Selur
12th October 2021, 04:32
@lansing: I'm only want to apply the filtering on a part of the image, one of the poing of it is that filtering a part requires less processing power.
@_Al_: I don't get
a. why the blur function as args as argument that arent used.
b. what animate does and where it comes from :)

Cu Selur

_Al_
12th October 2021, 05:07
That's a standard feature in python, if a function needs to "eat up" arguments or if you do not know how many arguments that function is going to have. Actually better would be: def blur(*args,**kwargs): , but I did not use keyword arguments in animate.py, just positional arguments, so just *args is ok
We know that other functions will have arguments as a filters. And this function "blur" is processed with the same algorithm as other filters. Code would error saying that there are no arguments for that function or something.

That animate feature uses arguments in those functions when filters are chained, actually it is functools.reduce() which chain's filters.
I put together that code, actually it started here on the forum. I realized this could be used for other things, like quick fades in and out etc..

lansing
12th October 2021, 06:39
@lansing: I'm only want to apply the filtering on a part of the image, one of the poing of it is that filtering a part requires less processing power.


Something like this:


def applyToRectangle(n, f, clip):
# do stuff to the frame here

filtered_clip = core.std.FrameEval(base_clip, functools.partial(applyToRectangle, clip=base_clip))

final_clip = core.remap.Rfs(base_clip, filtered_clip , mappings="30 40 50")

Selur
12th October 2021, 17:18
@lansing:
The point was if anyone did have a function which would take:
a. a clip
b. rectangle coordinates+size
c. a filter + parameters
d. a frame range
which would:
only apply the filter on the rectangle and the frames.

So the function basically should only for the frames in the range.
1. take the source, crop out the recangle
2. filter the rectangle
3. replace the space of the rectangle with the filtered rectangle
The main point is not filter the whole clip and all the whole frame.

@_AI_: I somehow totally missed the link to the animate.py, that does help.
Thanks! I need to play around with this. :)

Cu Selur

Myrsloik
12th October 2021, 20:44
R57 (https://github.com/vapoursynth/vapoursynth/releases/tag/R57)!

r57:
added close method for frames in python (cid-chan)
arguments names will no longer have leading _ stripped in python, append _ to the end or argument names instead to avoid python keywords
fixed nodes never being marked as nfnocache/nfiscache in api3 which caused some older applications to enter an infinite cache insertion loop
fixed memory bloat in python due to circular references when dealing with frame objects
fixed vsrepo missing genstubs files
fixed vfw and avfs speed regression from r55
fixed mismatched format clips not working regression from r55

ChaosKing
12th October 2021, 22:36
Vapoursynth still has no official logo. How about something like this?

https://i.imgur.com/Kp7yTaB.png
https://i.imgur.com/VCyqIVE.png
https://i.imgur.com/UIZ4bpG.png
https://i.imgur.com/aLfzZ2L.png

LigH
13th October 2021, 09:11
Once upon a time I suggested something based on the Python snake icon and a film roll.

https://www.ligh.de/pics/VapourSynth_FilmClip.png

lansing
13th October 2021, 15:03
Last month was Vapoursynth 9th anniversary too

poisondeathray
13th October 2021, 17:57
I liked LigH's idea, because python is a central component to vapoursynth, and animated the filmstrip
https://forum.doom9.org/showthread.php?p=1847472#post1847472

Here is a revised version with text
https://i.postimg.cc/Vkv1q49J/vapoursynth-pythonfilm-v3-320x320.gif

l33tmeatwad
14th October 2021, 18:40
You can't just use the Python logo without permission as it's copyrighted.

LigH
15th October 2021, 09:00
Thank you for the reminder; still, one could ask for permission when it gets serious...

lansing
17th October 2021, 05:37
How do I load in an audio file in the script? I couldn't find it in the documentation

l33tmeatwad
17th October 2021, 05:48
Use best audio source, then you'll have to set two outputs, one for video and one for audio.

lansing
17th October 2021, 06:08
Use best audio source, then you'll have to set two outputs, one for video and one for audio.

I tried to load this in media player classic but it gives me the error "output index 0 is not video"


clip = core.dgdecodenv.DGSource(r"clip.dgi")
audio = core.bas.Source(r"audio_file.flac")
clip.set_output()
audio.set_output()

l33tmeatwad
17th October 2021, 06:10
You need to put 0 for video and 1 for audio in the parenthesis.

lansing
17th October 2021, 06:16
You need to put 0 for video and 1 for audio in the parenthesis.

Now the program crashed with "access violation"

"crashing modules: C:\Program Files\VapourSynth\core\vsvfw.dll"

Izuchi
18th October 2021, 13:18
How do I output 32-bit float video using vspipe? It seems to just give me green garbage.

Yomiko
18th October 2021, 14:42
How do I output 32-bit float video using vspipe? It seems to just give me green garbage.

That looks right if the output is interpreted as YUV in integer format

poisondeathray
18th October 2021, 15:25
How do I output 32-bit float video using vspipe? It seems to just give me green garbage.



YUV444PS or RGBS ? Not many programs will understand YUV444PS

What program are you piping into ?

For ffmpeg/libavcodec, you can vspipe rawvideo as RGBS and use -pix_fmt gbrpf32le in ffmpeg

Izuchi
18th October 2021, 20:26
Was hoping to output YUV420PS as an intermediary file after running BM3D CUDA and then inserting it back into the script. Is RGB my only option?

poisondeathray
18th October 2021, 21:50
Was hoping to output YUV420PS as an intermediary file after running BM3D CUDA and then inserting it back into the script. Is RGB my only option?


Even if you vspipe it to something , I do not know of any file format that you could read for YUV420PS. The raw reader in vapousynth does not support float, only up to 16bit int formats. All vapoursynth imwri reads are in RGB , even if source was YUV. (jpeg, YUV tiff)

For intermediate files, you could stay in vapoursynth by using imrwi to read/write a RGBS TIFF sequence, without vspipe or other programs . (The current imwri.write implementation only writes RGBH in EXR, but RGBS is ok in TIFF). If you use resize.Point it should be lossless from YUV420PS <=> RGBS . Make sure you use float_output=True for the imwri.Read step.


And how did you YUV420PS to work in vapoursynth ? I couldn't import it from core , and get "module 'vapoursynth' has no attribute 'YUV420PS'" error

Izuchi
18th October 2021, 22:57
Yeah YUV420PS didn't work for me either, it just returned garbage pixels ffms2 just reads it as YUV420P8 with only a single frame. Thanks for tip, I might try piping it to ffmpeg.

Izuchi
18th October 2021, 23:37
Would this be the correct command? vspipe script.vpy - | ffmpeg -f rawvideo -pix_fmt gbrpf32le -s 1920x1080 -r 24000/1001 -i - denoise.rgb

_Al_
19th October 2021, 00:51
no attribute 'YUV420PS'
former register_format(), now it is query_video_format(), I guess because of audio formats addition:
my_float_format = core.query_video_format(color_family=vs.YUV, sample_type=vs.FLOAT, bits_per_sample=32, subsampling_w=1, subsampling_h=1)
clip2 = clip.resize.Point(format=my_float_format)
print(clip2)
>>>
VideoNode
Format: YUV420PS32

poisondeathray
19th October 2021, 01:59
Would this be the correct command? vspipe script.vpy - | ffmpeg -f rawvideo -pix_fmt gbrpf32le -s 1920x1080 -r 24000/1001 -i - denoise.rgb


For raw RGB... but you can't read raw rgb float with vsrawsource. You would use denoise_%05d.exr for ffmpeg output, and imwri.Read with float_output=True for import back into vapoursynth. But there are issues with that workflow for some reason, it's not lossless if you check MakeDiff, I'm looking into it.

But if you use imwri.Write in vapoursynth it's lossless

output

clip = core.imwri.Write(clip, "TIFF", "imwri_Write_%05d.tiff",firstnum=0)


reimport

clipc = core.imwri.Read(r'imwri_Write_%05d.tiff', float_output=True)

poisondeathray
19th October 2021, 02:04
former register_format(), now it is query_video_format(), I guess because of audio formats addition:
my_float_format = core.query_video_format(color_family=vs.YUV, sample_type=vs.FLOAT, bits_per_sample=32, subsampling_w=1, subsampling_h=1)
clip2 = clip.resize.Point(format=my_float_format)
print(clip2)
>>>
VideoNode
Format: YUV420PS32

Thanks it works.

I remember asking about not included pixel formats and Holy Wu told me about register_format - I should have remembered

https://forum.doom9.org/showthread.php?p=1904930#post1904930

Myrsloik
19th October 2021, 10:44
Thanks it works.

I remember asking about not included pixel formats and Holy Wu told me about register_format - I should have remembered

https://forum.doom9.org/showthread.php?p=1904930#post1904930

How did you end up with YUV420PS in the first place? Subsampled float is a quite weird thing to have

poisondeathray
19th October 2021, 15:21
How did you end up with YUV420PS in the first place? Subsampled float is a quite weird thing to have

It was not for me, scroll up a few posts

Quadratic
20th October 2021, 12:21
How did you end up with YUV420PS in the first place? Subsampled float is a quite weird thing to have

Why is YUV420PS "weird"? It can be achieved with vsutil and fmtc. It is not uncommon.

Myrsloik
20th October 2021, 12:31
Why is YUV420PS "weird"? It can be achieved with vsutil and fmtc. It is not uncommon.

It's a very inefficient use of bits. You'd have an image that definitely looks better with full resolution chroma in YUV444P16 format and smaller size.

Julek
22nd October 2021, 15:17
Now I need some input on which frame statistics to implement. If you generalize all of the functions in avisynth you get these 6 left. I've seen that difference is used a lot but are there any of these I could skip? I can't remember seeing the min/max/median used ever.
You can also suggest new ones if they're not too complicated.

Average(clip)
Difference(clip1, clip2)
PlaneMax(clip, float threshold)
PlaneMin(clip, float threshold)
PlaneMedian(clip)
PlaneMinMaxDifference(clip, float threshold)

The full list here:
http://avisynth.org/mediawiki/ScriptClip
Any chance to implement threshold for Min/Max now?
Dogway's retinex uses this, I know there is a plugin for it, but the output is not the same and I wanted to do some tests, if possible.

Dogway
22nd October 2021, 15:53
Vapoursynth still has no official logo. How about something like this?

https://i.imgur.com/Kp7yTaB.png
https://i.imgur.com/VCyqIVE.png
https://i.imgur.com/UIZ4bpG.png
https://i.imgur.com/aLfzZ2L.png

Beautiful logos! I like 3rd and 4th the best. 4th looks more like consumer oriented, it's third or fourth in neutral tones.

groucho86
22nd October 2021, 16:46
Hi everyone,
I opened an issue on github (https://github.com/vapoursynth/vapoursynth/issues/823) but thought it may be worth posting here. I installed Vapoursynth R57 and imwri via homebrew and am trying to load a half-float EXR (https://github.com/vapoursynth/vapoursynth/files/7398013/halffloat.001.exr.zip).

clip = core.imwri.Read(filename='halffloat.%03d.exr', firstnum=1,
float_output=True)
print(clip.get_frame(0))

Returns:
Filter Read returned a frame that's not of the declared format
VapourSynth encountered a fatal error: Filter Read returned a frame that's not of the declared format
libc++abi.dylib: terminating

float_output set to False works.

Yomiko
23rd October 2021, 09:34
What's the reason for not allowing a GRAY plane extracted from an RGB clip resized to RGB because of its tagged matrix? It seems the matrix itself (if supported by VS) doesn't affect the output result.

vxzms
23rd October 2021, 14:00
Would you plan to let the vspipe’s filter-time also show namespace? I think it would be more intuitive.

Myrsloik
23rd October 2021, 14:12
Would you plan to let the vspipe’s filter-time also show namespace? I think it would be more intuitive.

Filter don't have a namespace but the functions that create them may or may not. So it's actually very hard to add what you'd expect as the namespace to your list.

If anything extending the graph output with time spent in various filters is probably the best way since then you can see which function is responsible.

GB452
24th October 2021, 22:11
Having a very strange issue: vsrepo can't detect VapourSynth. I had updated to VS 57, but had some issues (including this one) and uninstalled it and went back to what I was using previously, version 54, but I keep getting this error and I cannot find any suggestions on how to fix it online.

https://i.imgur.com/yFFP3lE.png

ChaosKing
24th October 2021, 22:14
Same happend to me after updating to R57.

Yomiko
25th October 2021, 00:37
What's the reason for not allowing a GRAY plane extracted from an RGB clip resized to RGB because of its tagged matrix? It seems the matrix itself (if supported by VS) doesn't affect the output result.

Meanwhile GRAY clip with unspec matrix can be resampled. A bug?

Myrsloik
25th October 2021, 10:41
Meanwhile GRAY clip with unspec matrix can be resampled. A bug?

No, gray clips are the Y in YUV so the same rules apply. You can resize unknown matrix YUV but you can't convert it to RGB.

Selur
25th October 2021, 14:11
I'm on Ubuntu 20.04, I compiled and installed Vapoursynth R57.
I also compiled a bunch of filters to "/home/selur/opt/vapoursynth/lib/python3.8/site-packages"

paths seem to be correct:

echo $LD_LIBRARY_PATH
/home/selur/opt/vapoursynth/lib
echo $PYTHONPATH
/home/selur/opt/vapoursynth/lib/python3.8/site-packages
echo $PATH
/home/selur/.local/bin:/home/selur/opt/vapoursynth/bin:/home/selur/.local/bin:/home/selur/opt/vapoursynth/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin



import vapoursynth as vs
core = vs.core
clip = core.std.BlankClip(format=vs.RGB24, color=[255, 255, 255])
clip = core.text.Text(clip, core.version())
clip.set_output()

works fine

explicit loading a library (libvslsmashsource.so):

import vapoursynth as vs
core = vs.core

core.std.LoadPlugin('/home/selur/opt/vapoursynth/lib/vapoursynth/libvslsmashsource.so')

clip = core.lsmas.LWLibavSource(source="test.mov", format="YUV422P10", cache=0, fpsnum=30000, fpsden=1001, prefer_hw=0)
clip = core.resize.Point(clip, matrix_in_s="470bg",range_s="limited")

clip.set_output()
works fine too,

but using:

import sys
import vapoursynth as vs
core = vs.core

sys.path.append('/home/selur/opt/vapoursynth/lib/vapoursynth')

clip = core.lsmas.LWLibavSource(source="test.mov", format="YUV422P10", cache=0, fpsnum=30000, fpsden=1001, prefer_hw=0)
clip = core.resize.Point(clip, matrix_in_s="470bg",range_s="limited")

clip.set_output()

doesn't.
It returns "Python exception: No attribute with the name lsmas exists. Did you mistype a plugin namespace?"

-> How can I tell Vapoursynth where to look for the libraries?
I though:
sys.path.append('/home/selur/opt/vapoursynth/lib/vapoursynth')
would do the trick, which it doesn't.

Cu Selur

Myrsloik
25th October 2021, 14:13
You're specifying the python search path, it's only used for import and similar python commands. You also shouldn't install filters in site-packages.

Selur
25th October 2021, 14:18
Sorry, my mistake. Didn't put the iflters in the site-packages. :)
site-packages only contains vapoursynth.la and vapoursynth.so
all compiled filters are in "/home/selur/opt/vapoursynth/lib/vapoursynth/"

Okay, so is there a way to somehow to use my folder as "/home/selur/opt/vapoursynth/lib/vapoursynth/" source for autoloading?

Selur
25th October 2021, 14:25
okay, forget it found it.
"$HOME/.config/vapoursynth/vapoursynth.conf "
with:
"SystemPluginDir=/home/selur/opt/vapoursynth/lib/vapoursynth"
works

Yomiko
25th October 2021, 14:39
Also this -> http://www.vapoursynth.com/doc/functions/general/loadallplugins.html

Selur
25th October 2021, 14:56
Uhhh,.. didn't know "LoadAllPlugins" :)

_Al_
25th October 2021, 16:21
oh, was LoadAllPlugins introduced with new API release or does it work with older releases too?

lansing
26th October 2021, 06:03
When creating filter, where do we put the xyvInit() initial function in API4 now? It was gone in the example filter. And in the createVideoFilter(), there are this two lines in the example script:


VSFilterDependency deps[] = {{d.node, rpStrictSpatial}};
vsapi->createVideoFilter(out, "Invert", vi, invertGetFrame, invertFree, fmParallel, deps, 1, data, core);


What is the VSFilterDependency and numDeps do? The documentation is lacking.

Myrsloik
26th October 2021, 10:27
When creating filter, where do we put the xyvInit() initial function in API4 now? It was gone in the example filter. And in the createVideoFilter(), there are this two lines in the example script:


VSFilterDependency deps[] = {{d.node, rpStrictSpatial}};
vsapi->createVideoFilter(out, "Invert", vi, invertGetFrame, invertFree, fmParallel, deps, 1, data, core);


What is the VSFilterDependency and numDeps do? The documentation is lacking.

1. You have a function that calls createVideoFilter(), put it there instead. Most filters are already written that way.

2. It's an array where you list all the nodes and in which order you will request frames from them to generate the output. StrictSpatial is obviously for spatial only filters, NoFrameReuse is for reordering filters of certain types (basically if you request all output frames once none of the input frames will be requested twice, trim, splice and similar fit into this category). General is for everything else.

NumDeps is simply how items are in the deps array.

lansing
26th October 2021, 23:46
Okay got it. Also can you add some example filter written in c++? Because when I got stuck with the c syntax, I couldn't find any other example because everybody was writing in c++. For example, I want to use the isConstantVideoFormat() from the VSHelper4.h, I included the header file in my c file #include "VSHelper4.h", but visual studio still couldn't recognize the function.

DJATOM
27th October 2021, 00:08
Use vsh::yourCalledFunction.

lansing
27th October 2021, 01:33
Use vsh::yourCalledFunction.

using namespace is a c++ thing

WolframRhodium
27th October 2021, 04:26
vsh_yourCalledFunction

lansing
27th October 2021, 06:16
Thanks, worked.

Now I ran into another problem trying to build the filter. The build succeeded, but the function didn't get register. Here is the xxxCreate function.


void VS_CC levelsCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi) {
LevelsData d;
LevelsData *data;
int err;

d.node = vsapi->mapGetNode(in, "clip", 0, 0);
d.vi = *vsapi->getVideoInfo(d.node);

d.factor = vsapi->mapGetFloat(in, "factor", 0, &err);
if (err) {
d.factor = 100.0;
}

// Comparing them directly?
if (d.factor < 0.0 || d.factor > 100.0) {
vsapi->mapSetError(out, "Levels: factor must be between 0 and 100 (inclusive)");
vsapi->freeNode(d.node);
return;
}

if (!vsh_isConstantVideoFormat(&d.vi) || d.vi.format.sampleType != stInteger || d.vi.format.bitsPerSample != 8) {
vsapi->mapSetError(out, "Levels: only constant format 8bit integer input supported");
vsapi->freeNode(d.node);
return;
}

if (d.vi.width)
d.vi.width += 256;
if (d.vi.height)
d.vi.height = MAX(256, d.vi.height);

data = (LevelsData *)malloc(sizeof(d));
*data = d;

VSFilterDependency deps[] = { {d.node, rpStrictSpatial} };
vsapi->createVideoFilter(out, "Levels", &d.vi, levelsGetFrame, levelsFree, fmParallel, deps, 1, data, core);
}

########################################

void VS_CC levelsCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi);

VS_EXTERNAL_API(void) VapourSynthPluginInit2(VSPlugin* plugin, const VSPLUGINAPI* vspapi) {
vspapi->configPlugin("com.nodame.histogram", "hist", "VapourSynth Histogram Plugin", VS_MAKE_VERSION(1, 0), VAPOURSYNTH_API_VERSION, 1, plugin);
vspapi->registerFunction("Levels", "clip:clip;factor:float:opt;", "clip:vnode;", levelsCreate, NULL, plugin);
}


vsedit2 was able to read the plugin "hist", but not the function "Levels". What am I doing wrong?

Yomiko
27th October 2021, 07:05
Maybe clip:vnode in the signature.
But if the filter is only for vsedit2, I think having createVideoFilter(2) called in the filter chain should be sufficient.

lansing
27th October 2021, 07:44
Maybe clip:vnode in the signature.


Thank you, that is the problem. I was looking at the codes for hours and couldn't figure it out.

Myrsloik
27th October 2021, 11:37
Protip: if you misuse the api you'll get warnings for things like invalid argument strings if you run things from the commandline

lansing
28th October 2021, 08:31
Protip: if you misuse the api you'll get warnings for things like invalid argument strings if you run things from the commandline

What about debugging crashes. My test filter tested okay on vspipe --info but crashes on preview, what do I do?

Myrsloik
28th October 2021, 12:23
What about debugging crashes. My test filter tested okay on vspipe --info but crashes on preview, what do I do?

Attach a debugger, duh. If there's no error message then your own code crashed inside the getframe function.

lansing
28th October 2021, 17:26
I want to rotate the frame inside the filter, can I call like std.Transpose and std.FlipHorizontal in the filter?

Myrsloik
28th October 2021, 17:49
I want to rotate the frame inside the filter, can I call like std.Transpose and std.FlipHorizontal in the filter?

Yes, use invoke. You can look at the code of SCDetect on how to do it here:
https://github.com/vapoursynth/vs-miscfilters-obsolete/blob/master/src/miscfilters.cpp#L132

lansing
28th October 2021, 21:58
Yes, use invoke. You can look at the code of SCDetect on how to do it here:
https://github.com/vapoursynth/vs-miscfilters-obsolete/blob/master/src/miscfilters.cpp#L132

What if I want to do rotate right -> process the frame -> rotate left? It feels like doing the last rotate in the xxxFree function is too late in the process?

Myrsloik
28th October 2021, 22:54
What if I want to do rotate right -> process the frame -> rotate left? It feels like doing the last rotate in the xxxFree function is too late in the process?

Use createVideoFilter2() and then simply call invoke on the node returned from there. Same idea.

Not the best example but few places do this in the VS code (see unpackRGB32Create):
https://github.com/vapoursynth/vapoursynth/blob/master/src/avisynth/avisynth_compat.cpp#L897

lansing
29th October 2021, 00:07
Use createVideoFilter2() and then simply call invoke on the node returned from there. Same idea.

Not the best example but few places do this in the VS code (see unpackRGB32Create):
https://github.com/vapoursynth/vapoursynth/blob/master/src/avisynth/avisynth_compat.cpp#L897

So the structure would be like this?


static const VSFrame *VS_CC firstGetFrame() {}

static const VSFrame *VS_CC finalGetFrame() {
return frame;
}

void VS_CC filterCreate() {

d.node = vsapi->mapGetNode(in, "clip", 0, 0);
// call invoke on node

VSNode * node2 = vsapi->createVideoFilter2(firstGetFrame, freeFunc1, data);

// call invoke on node2

d.node = node2;

vsapi->createVideoFilter(finalGetFrame, freeFunc2, data);
}

Yomiko
29th October 2021, 00:20
from boxblur
https://github.com/vapoursynth/vapoursynth/blob/master/src/core/boxblurfilter.cpp#L294-L307

lansing
29th October 2021, 04:44
I'm seeing two patterns from the examples above about chaining invoke, it got me confused:

#1:
invmap2 = vsapi->invoke(stdplugin, "Trim", invmap);
...
vsapi->mapConsumeNode(invmap, "clipb", vsapi->mapGetNode(invmap2, "clip", 0, nullptr), maAppend);
...
invmap2 = vsapi->invoke(stdplugin, "PlaneStats", invmap);


#2
vsapi->createVideoFilter(vtmp2, "BoxBlur", xxx);
vtmp1 = vsapi->invoke(stdplugin, "Transpose", vtmp2);

In the first example, after the first invoke, the resulting node has to be consumed into a new map before pluging it into another invoke.

But in the second example, the resulting map just go straight to an invoke without the node consume?

Myrsloik
29th October 2021, 09:41
Sometimes thebmap returned from invoke has the right contents and then it can be passed to invoke immediately. If it doesn't you have have to do more map manipulation.

lansing
30th October 2021, 05:17
ShufflePlanes should automatically strip the "_Matrix" property if the target color family is vs.GRAY. otherwise an error message pops up bitchin' about "no _Matrix stuff allowed for GRAY" or whatever and you have to manually remove the "_Matrix" thingy before ShufflePlanes which is very annoying.

I just encountered this annoyance, is there a better solution now?

lansing
30th October 2021, 06:40
Format conversion from a Shuffleplanes causes a shift in chroma?


clip = yuv_clip
clip = core.std.ShufflePlanes(clip, 0, colorfamily=vs.YUV)
#clip = core.resize.Point(clip, format=vs.YUV444P8) // no shift
clip = core.resize.Point(clip, format=vs.YUV420P8) // chroma shift

Yomiko
30th October 2021, 14:51
Point (nearest neighbor) is supposed to be like that. It never blends neighboring pixels.

lansing
30th October 2021, 15:32
Point (nearest neighbor) is supposed to be like that. It never blends neighboring pixels.

There's a shift with all other resizers too. And I thought for format conversion purpose, all the resizers should be the same?

Selur
30th October 2021, 17:20
An option to disable auto loading is probably coming soon. With more exciting things as well.
Any news in this regard?

Cu Selur

lansing
30th October 2021, 23:04
When extracting RGB planes from a RGB clip, Shuffleplanes is outputting the wrong clip if I set the "colorfamily" to YUV


rgb_clip = core.resize.Point(clip, matrix_in_s="709", format=vs.RGB24)
clip = core.std.ShufflePlanes(rgb_clip, 0, colorfamily=vs.YUV)


I was expecting to get a yuv clip of a grayscale, but this output a yuv clip of green and pink.

ChaosKing
31st October 2021, 12:27
Is there a replacement for https://github.com/AmusementClub/VapourSynth-EEDI2CUDA ? ( repo was deleted)

If not then I will remove it from vsrepo.

sl1pkn07
31st October 2021, 12:39
https://github.com/kedaitinh12/VapourSynth-EEDI2CUDA

but i'm not sure if is updated

ChaosKing
31st October 2021, 13:10
No releases :(

kedautinh12
31st October 2021, 13:46
Here: https://github.com/kedaitinh12/VapourSynth-EEDI2CUDA/releases

And i ain't a developer, if anyone have attention that project can folk them :D

LigH
1st November 2021, 10:08
I guess that means: If anyone wants to maintain this project, please fork it.

kedautinh12
1st November 2021, 11:43
I guess that means: If anyone wants to maintain this project, please fork it.

Yes, sr for my bad English :D

Selur
1st November 2021, 20:46
Did something change with vs-imwri?
I'm using R1 from https://github.com/vapoursynth/vs-imwri/releases/tag/R1 with Vapoursynth R57 and this code:

[logo, alpha] = core.imwri.Read(filename="C:/Users/Selur/smallLogo.png", alpha=True)

but get "Python exception: not enough values to unpack (expected 2, got 1)" same code worked fine (with the same logo) with R54 and the old plugin.
Tested on MacOS and Windows 10.

Cu Selur

Myrsloik
1st November 2021, 22:00
Did something change with vs-imwri?
I'm using R1 from https://github.com/vapoursynth/vs-imwri/releases/tag/R1 with Vapoursynth R57 and this code:

[logo, alpha] = core.imwri.Read(filename="C:/Users/Selur/smallLogo.png", alpha=True)

but get "Python exception: not enough values to unpack (expected 2, got 1)" same code worked fine (with the same logo) with R54 and the old plugin.
Tested on MacOS and Windows 10.

Cu Selur


logo = core.imwri.Read(filename="C:/Users/Selur/smallLogo.png", alpha=True)
alpha = core.std.PropToClip(logo)

Selur
3rd November 2021, 05:46
Thanks that works!
Any news on an option to disable auto loading ?

ChaosKing
3rd November 2021, 08:15
Thanks that works!
Any news on an option to disable auto loading ?

I'm also waiting for it since 2018 now :D

Myrsloik
3rd November 2021, 22:48
I'm also waiting for it since 2018 now :D

Why U no autoload? There are no plugins that ruin your day like that other unnamed competing application does.

ChaosKing
3rd November 2021, 23:09
I autoload !!!!1111
But for software where I want to use a specific version of let's say ffms2, autoloading is preventing me of loading my version (or you need to use VS portable version). This is one example https://forum.doom9.org/showthread.php?t=176231

Selur
4th November 2021, 05:48
@Myrsloik: because I want to be sure that:
a. no libary gets loaded twice
b. the libaries I need are loaded
c. when hunting for problems switching libaries to check whether the problem was caused by a libary update is easier when I just have to change the script.
this is a pain when users start to mix the plugins that I provide with Hybrid with some they installed from other sources. Being able to disable autoload simple allows to keep control.

Cu Selur

Ps.: libimwri filter is not autoloaded on MacOS, which is why l33tmeatwad included the old version with its installer (see: https://forum.doom9.org/showthread.php?p=1956162#post1956162)

poisondeathray
5th November 2021, 23:50
Another alpha channel question for r57; A prores video with alpha channel , loading with LibavSMASHSource.


setVideoInfo: Video filter LibavSMASHSource has more than one output node but only the first one will be returned


In old R5x versions you could specify clip[1].set_output() for the alpha node, but it looks like it's not even loaded by the source filter

poisondeathray
6th November 2021, 00:02
What is the setup for portable python/vapoursynth setup for accessing "site-packages" folder ?

ChaosKing
6th November 2021, 09:12
For python portable you can control which site-packages to use / access via a path file "python39._pth"

Here's the file I use for my portable fatpack
https://github.com/theChaosCoder/vapoursynth-portable-FATPACK/blob/master/python39._pth

this way I can put all vs scripts into Scripts and the python stuff are Lib\site-packages. You can add as many folders as you want I think.

Yomiko
6th November 2021, 10:02
2. It's an array where you list all the nodes and in which order you will request frames from them to generate the output.
A stupid question:
To what extent does the order matter? For example, if I had vnodes v1 and v2 in the dep list, but v2 was derived by invoking a plugin with v1. What might happen if v1 and v2 were declared in the wrong order?

Selur
6th November 2021, 13:52
In old R5x versions you could specify clip[1].set_output() for the alpha node, but it looks like it's not even loaded by the source filter
I like to know that too how to get the alpha channel.

poisondeathray
7th November 2021, 04:22
For python portable you can control which site-packages to use / access via a path file "python39._pth"

Here's the file I use for my portable fatpack
https://github.com/theChaosCoder/vapoursynth-portable-FATPACK/blob/master/python39._pth

this way I can put all vs scripts into Scripts and the python stuff are Lib\site-packages. You can add as many folders as you want I think.

Works, thanks

What I wanted to do is keep an installed version ,and portable version, but use the portable version for testing purposes and not have to double up on everything . (I was able to edit the path to a custom one)

DTL
7th November 2021, 20:54
pinterf suggest to ask Vapoursynth developers about largepages usage and skipping in the last builds. What was the reason of skipping use of large pages in the last builds ?

As I see it is hard to allocate on running windows enough number of large pages after system and applications running because of memory fragmentation. So for general use in user-ring frequently start and end application for the large allocations it possibly not applicable. And to set ring-0 driver for allocation most of RAM as large pages at boot time mean to lost this memory from all other system and may be not user-friendly for desktop PC.
Or may be special helper process of defragment memory at windows runtime required and immediate gathering defragmented physical parts for application as large pages.

I tried to make avisynth mod with allocating large pages for frame buffers and for unknown reason the performance of MDegrain was lower. But for small vectors buffer of about 1 2 MB LP size it looks like help to reduce TLB reload and runs a bit faster at large frame size.

So may be at current time the use of small amount of large pages for highly loaded random access small buffers is good but for most of RAM for large processing simply not possible or slower ? I hope there is not performance penalty on mixing use of 4 kB and large pages in one process.

Myrsloik
8th November 2021, 07:40
A stupid question:
To what extent does the order matter? For example, if I had vnodes v1 and v2 in the dep list, but v2 was derived by invoking a plugin with v1. What might happen if v1 and v2 were declared in the wrong order?

Order doesn't matter in the list.

Myrsloik
8th November 2021, 07:43
I like to know that too how to get the alpha channel.

Use PropToClip on the output. But at the moment alpha simply gets stored as the _Alpha property. Maybe I should actually do that internally in these filters.

Myrsloik
8th November 2021, 07:45
pinterf suggest to ask Vapoursynth developers about largepages usage and skipping in the last builds. What was the reason of skipping use of large pages in the last builds ?

As I see it is hard to allocate on running windows enough number of large pages after system and applications running because of memory fragmentation. So for general use in user-ring frequently start and end application for the large allocations it possibly not applicable. And to set ring-0 driver for allocation most of RAM as large pages at boot time mean to lost this memory from all other system and may be not user-friendly for desktop PC.
Or may be special helper process of defragment memory at windows runtime required and immediate gathering defragmented physical parts for application as large pages.

I tried to make avisynth mod with allocating large pages for frame buffers and for unknown reason the performance of MDegrain was lower. But for small vectors buffer of about 1 2 MB LP size it looks like help to reduce TLB reload and runs a bit faster at large frame size.

So may be at current time the use of small amount of large pages for highly loaded random access small buffers is good but for most of RAM for large processing simply not possible or slower ? I hope there is not performance penalty on mixing use of 4 kB and large pages in one process.

No measurable performance benefit. At all. So when things were reworked the feature got cut. You can still play around with it in the API3 builds if you don't believe me.

poisondeathray
8th November 2021, 16:54
Use PropToClip on the output. But at the moment alpha simply gets stored as the _Alpha property. Maybe I should actually do that internally in these filters.

_Alpha is apparently not loaded by LSmash ; and there is no "alpha=True" switch.


setVideoInfo: Video filter LibavSMASHSource has more than one output node but only the first one will be returned


The same .dll loads the alpha in vapoursynth R54, and is accessible with clip[1].set_output()



clip = core.lsmas.LibavSMASHSource(r'prores4444.mov')
alpha = core.std.PropToClip(clip)
alpha.set_output()



vapoursynth.Error: PropToClip: no frame stored in property: _Alpha





PropToClip works ok with imwri as source for images, alpha=True

Selur
8th November 2021, 18:35
vapoursynth.Error: PropToClip: no frame stored in property: _Alpha
Yup, same here works fine with imwri, doesn't work with lsmas.LibavSMASHSource.

Myrsloik
8th November 2021, 21:52
Yup, same here works fine with imwri, doesn't work with lsmas.LibavSMASHSource.

Needs to be updated for API4 then. Poke the author.

poisondeathray
8th November 2021, 23:05
Needs to be updated for API4 then. Poke the author.

It works with vA.3g , (vapoursynth only release) by AkarinVS

https://github.com/AkarinVS/L-SMASH-Works/releases

Selur
9th November 2021, 19:05
good find:
https://github.com/VFR-maniac/L-SMASH-Works no updates the last 2 years
https://github.com/enccc/L-SMASH-Works no updates the last 4 years
https://github.com/HolyWu/L-SMASH-Works no updates the last 6 month and is read only
seem like https://github.com/AkarinVS/L-SMASH-Works is the only repository that is seems active,...

Yomiko
11th November 2021, 02:59
How can I get a list of available output indices via vsscript api?

Myrsloik
11th November 2021, 13:52
How can I get a list of available output indices via vsscript api?

You can't. Trial and error is the only way. Note that I only ever use index 0 for video/audio and 1 for audio (when both are present).

Realistically you can test the first 100 outputs in no time and call it good enough if you want to allow fast switching for comparisons and stuff.

Yomiko
11th November 2021, 14:34
I see. That's a nice excuse to not enumerating all the output nodes.

lansing
20th November 2021, 01:30
How do I pass in multiple nodes into a map programmatically for plugin such as StackHorizontal? Like this?


vsapi->mapConsumeNode(pArgumentMap, "clips", A_node, maAppend);
vsapi->mapConsumeNode(pArgumentMap, "clips", B_node, maAppend);
vsapi->mapConsumeNode(pArgumentMap, "clips", C_node, maAppend);

auto resultMap = vsapi->invoke(pStdPlugin, "StackHorizontal", pArgumentMap);

amayra
20th November 2021, 23:13
https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works/

this look like new repo for L-SMASH

kedautinh12
20th November 2021, 23:25
https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works/

this look like new repo for L-SMASH

Your only development for Avisynth. Here only development for Vapoursynth
https://github.com/AkarinVS/L-SMASH-Works/releases

sl1pkn07
21st November 2021, 19:43
Your only development for Avisynth.


not at all. is dual interface

kedautinh12
21st November 2021, 21:10
not at all. is dual interface

Dual but his link don't development for Vapoursynth anymore. And my link don't development for Avisynth anymore

asarian
17th December 2021, 04:26
Every year I'm dealing with the same installation issues:

File "src\cython\vapoursynth.pyx", line 2833, in vapoursynth._vpy_evaluate
File "f:\jobs\interB.vpy", line 4, in <module>
core = vs.get_core ()
AttributeError: module 'vapoursynth' has no attribute 'get_core'

It only works on the Python prompt:

Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> from vapoursynth import core
>>> print(core.version())
VapourSynth Video Processing Library
Copyright (c) 2012-2021 Fredrik Mellbin
Core R57
API R4.0
API R3.6

What is going wrong here?!


EDIT:

I changed to this "core = vs.core ()". Appparently the powers that be decided to mess with the API. Fine, but now I get this:

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2832, in vapoursynth._vpy_evaluate
File "src\cython\vapoursynth.pyx", line 2833, in vapoursynth._vpy_evaluate
File "f:\jobs\interB.vpy", line 4, in <module>
core = vs.core ()
TypeError: 'vapoursynth._CoreProxy' object is not callable

Or without the parentheses, just "Property read unsuccessful due to missing key but no error output: _SceneChangePrev"

poisondeathray
17th December 2021, 04:52
Every year I'm dealing with the same installation issues:

File "src\cython\vapoursynth.pyx", line 2833, in vapoursynth._vpy_evaluate
File "f:\jobs\interB.vpy", line 4, in <module>
core = vs.get_core ()
AttributeError: module 'vapoursynth' has no attribute 'get_core'


Now it's


core = vs.core


instead of


core = vs.get_core()

asarian
17th December 2021, 04:59
Now it's


core = vs.core


instead of


core = vs.get_core()


Thanks. I noticed that yes, but it throws a weird error about _SceneChangePrev (see above).


EDIT: Updated a zillion filters, and now all is good again. :)

Selur
1st January 2022, 18:09
I got the following script:
# Imports
import os
import sys
import ctypes
# Loading Support Files
Dllref = ctypes.windll.LoadLibrary("I:/Hybrid/64bit/vsfilters/Support/libfftw3f-3.dll")
import vapoursynth as vs
# getting Vapoursynth core
core = vs.core
# Import scripts folder
scriptPath = 'I:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# Loading Plugins
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/GrainFilter/RemoveGrain/RemoveGrainVS.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/GrainFilter/AddGrain/AddGrain.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/DenoiseFilter/NEO_FFT3DFilter/neo-fft3d.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/DenoiseFilter/DFTTest/DFTTest.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/EEDI3m.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/ResizeFilter/nnedi3/vsznedi3.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/libmvtools.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/temporalsoften.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/scenechange.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/MiscFilter/MiscFilters/MiscFilters.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/fmtconv.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/SourceFilter/DGDecNV/DGDecodeNV.dll")
# Import scripts
import havsfunc
# source: 'C:\Users\Selur\Desktop\cnpolandecpnextbumpereliotkid.mp4'
# current color space: YUV420P8, bit depth: 8, resolution: 640x480, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: bottom field first
# Loading C:\Users\Selur\Desktop\cnpolandecpnextbumpereliotkid.mp4 using DGSource
clip = core.dgdecodenv.DGSource("E:/Temp/mp4_7121ca84898db5944d8e11d671f2de4e_853323747.dgi",fieldop=2)
# making sure input color matrix is set as 470bg
clip = core.resize.Bicubic(clip, matrix_in_s="470bg",range_s="limited")
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
clip = core.fmtc.resample(clip=clip, kernel="spline16", w=320, h=240, interlaced=True, interlacedd=True)
# setting field order to what QTGMC should assume (bottom field first)
clip = core.std.SetFrameProp(clip=clip, prop="_FieldBased", intval=1)
# Deinterlacing using QTGMC
clip = havsfunc.QTGMC(Input=clip, Preset="Fast", TFF=False) # new fps: 25
# make sure content is preceived as frame based
clip = core.std.SetFieldBased(clip, 0)
clip = clip[::2]
# adjusting output color from: YUV420P16 to YUV420P8 for x264Model
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, range_s="limited")
# set output frame rate to 25.000fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()
which loads fine.
Trying to load the script inside another script:
# Imports
from importlib.machinery import SourceFileLoader
import vapoursynth as vs
# getting Vapoursynth core
core = vs.core
# source: 'C:\Users\Selur\Desktop\small.vpy'
# current color space: YUV420P8, bit depth: 8, resolution: 320x240, fps: 25, color matrix: 470bg, yuv luminance scale: full, scanorder: progressive
# Loading C:\Users\Selur\Desktop\small.vpy
SourceFileLoader('clip', 'C:/Users/Selur/Desktop/small.vpy').load_module()
clip = vs.get_output()
# making sure input color matrix is set as 470bg
clip = core.resize.Bicubic(clip, matrix_in_s="470bg",range_s="full")
# making sure frame rate is set to 25.000
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Setting color range to PC (full) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=0)
# set output frame rate to 25.000fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()
I get;
Failed to evaluate the script:
Python exception: Bicubic: argument clip was passed an unsupported type (expected vnode compatible type but got NoneType)
I used the above back wit API3 and there iirc it worked fine. (https://forum.doom9.org/showthread.php?t=175098)
My guess is that something changed in API4 which I'm not aware of.

-> Does anyone know how to load one script inside another ?

Cu Selur

quietvoid
1st January 2022, 20:15
I think it's because you're using the parent script's vs module (which uses another core?).
This works for both API3/API4 compatibility:


output = SourceFileLoader('script', filepath).load_module().vs.get_output()

try:
if isinstance(output, vs.VideoOutputTuple):
clip = output.clip
else:
clip = output
except AttributeError:
clip = output


Because API4 is returning a clip + alpha tuple.

_Al_
1st January 2022, 21:22
To get clips fro vapoursynth scripts you can use this:

import vapoursynth as vs
from vapoursynth import core
from importlib.machinery import SourceFileLoader
from pathlib import Path

API4 = vs.__api_version__.api_major >= 4

class NoClipError(Exception):
pass

def vs_Source(script_path, wanted_output=None, **kwargs):
'''if no wanted_output is passed it returns first available'''
vs.clear_outputs()
vs_found_outputs = list(SourceFileLoader('script', script_path).load_module().vs.get_outputs().keys())

if not vs_found_outputs:
vs_output_index = wanted_output
raise NoClipError(f'No output found in "{Path(script_path).name}", clip.set_output() needs to be added to the script')
if wanted_output is None:
first_output = next(iter(vs.get_outputs()))
clip = vs.get_output(first_output)[0] if API4 else vs.get_output(first_output)
vs_output_index = first_output
else:
try:
clip = vs.get_output(wanted_output)[0] if API4 else vs.get_output(wanted_output)
except KeyError:
raise NoClipError(f'Output index {wanted_output} not found in "{Path(script_path).name}"')
vs_output_index = wanted_output

#optional, writing output index and all available outputs to clips prop
if API4:
clip = clip.std.SetFrameProps(vs_found_outputs=vs_found_outputs)
clip = clip.std.SetFrameProps(vs_output_index=vs_output_index)
else:
clip = clip.std.SetFrameProp(prop="vs_found_outputs", data=','.join(list(map(str,vs_found_outputs))))
clip = clip.std.SetFrameProp(prop="vs_output_index", intval=vs_output_index)
return clip

script_path = 'C:/Users/Selur/Desktop/small.vpy'
clip = vs_Source(script_path)
because of API4 changes (vs.get_outputs(), f.get_read_array(), SetFrameProps(allows to store a list now, perhaps other python objects), it is a good idea to have on top of script boolean what API is used and then split action, vs.get_outputs() was mentioned, then frame array example:
if API4: planes =[f[i] for i in range(f.format.num_planes)]
else: planes =[f.get_read_array(i) for i in range(f.format.num_planes)]

Selur
2nd January 2022, 09:12
Thanks! That works fine, since I only use API4 I'll stick with quietvvoids solution. :)

Cu Selur

ChaosKing
2nd January 2022, 12:52
There's an api3-api4 bridge now for older VS versions.
Suppose you are stuck with VS R54, but you want to use a video plugin filter.dll that only has api4 support.
You can download the released api3.dll and save it as filter.api3.dll along side with filter.dll into VS plugins directory.
And then you should be able to use the filter in api3 VS as usual.

https://github.com/AmusementClub/vs-api3/releases

_Al_
5th January 2022, 01:41
Thanks! That works fine, since I only use API4 I'll stick with quietvvoids solution. :)

Cu Selur
Yes, like that, clip output must be set always to zero, or as a default clip.set_output().
If it is an unknown script,
-video output could be put in a different index, or as happens all the time to me, actually forgetting to set output, so it should take care of that , not to crash python.
-check if it is audio actually, not video,

Is there a way to figure out video-audio pairing from outputs, or can user "mark" it somehow that an audio output matches what video output?
There should be something to mark those outputs as a pair. Is there something like that?

So far for example there could be output like this(2 video outputs and one audio):

clip.set_output(0)
audio.set_output(1)
clip2.set_output(2)
>>>print(vs.get_outputs())
0: VideoOutputTuple(clip=<vapoursynth.VideoNode object at 0x0000021CC20F4940>, alpha=None, alt_output=0),
1: <vapoursynth.AudioNode object at 0x0000021CC20F49C0>,
2: VideoOutputTuple(clip=<vapoursynth.VideoNode object at 0x0000021CC20F4940>, alpha=None, alt_output=0)}
Or is there going to be a consensus to always interleave video and audio outputs? That's arbitrary though not safe way to handle unknown script. Some kind of info binding might be helpful.

DJATOM
5th January 2022, 15:48
> Or is there going to be a consensus to always interleave video and audio outputs?
There is no interleaving in nodes, they are separate objects and you have to query data on every node independently. However if you asking for automation of stuff, there's 2 possible solutions that coming onto my mind:
1) assume node 0 is video and node 1 is audio (that actually used in avfs)
2) probe every node until reach 1 video and 1 audio, discard further evaluation

_Al_
9th January 2022, 00:16
ok, I guess it is not important or it could be worked with because an individual works with it, it is not shared, like chopping video etc.

I'd like to correct script from above to pull a VideoNode output from script only, not AudioNodes, which I forgot about:

class NoClipError(Exception):
pass

API4 = vs.__api_version__.api_major >= 4

def vs_Source(script_path, wanted_output_index=None, **kwargs):
'''
loads vapoursynth vs.VideoNode outputs from vapoursynth script,
if wanted_output_index (int) is not passed, it gets first available vs.VideoNode if any
vs.AudioNodes are ignored
'''
vs.clear_outputs()
SourceFileLoader('script', script_path).load_module()
if API4: instance = vs.VideoOutputTuple
else: instance = vs.VideoNode
video_output_indexes = [index for index, output in vs.get_outputs().items() if isinstance(output, instance)]
if not video_output_indexes:
raise NoClipError(f'No video output found in "{Path(script_path).name}", vnode.set_output() needs to be added to the script')
if wanted_output_index is None:
index = video_output_indexes[0]
else:
if wanted_output_index not in video_output_indexes:
raise NoClipError(f'Wanted video output index: {wanted_output_index} not found in "{Path(script_path).name}" or index is not a video output')
index = wanted_output_index
return vs.get_output(index)[0] if API4 else vs.get_output(index)

clip = vs_Source("some_vapoursynth_script.vpy")

qyot27
9th January 2022, 05:25
Is R65 broken somehow? At first I blamed Windows 11's new termimal for the very slow throughput (slow pipe transfer?), but nope, even using ffmepeg with -vapoursynth, the process is extremely slow, using CPU for only like 25%. Both QTGMC and MCTemporalDenoise seem to grind to a near halt. All on my new i9 12900K. This used to go blistering fast, even on my old 6700K.

Here's what I do (see below). It's almost as if multi-threading is broken for these two functions (it isn't, but appears to work exceedngly inefficient). This is 4K material, btw.

import vapoursynth as vs
import havsfunc as haf

core = vs.core
core.max_cache_size = 65535

vid = core.dgdecodenv.DGSource (r'c:\jobs\am.dgi', ct=44, cb=44, cl=0, cr=0)

vid = haf.QTGMC (vid, InputType=1, Preset="Very Slow", TR2=3, EdiQual=2, EZDenoise=0.5, NoisePreset="Slower", TFF=True, Denoiser="KNLMeansCL")
vid = haf.MCTemporalDenoise (vid, settings="very low", stabilize=True)
vid = core.neo_f3kdb.Deband (vid, preset="veryhigh", dither_algo=2)
vid = core.std.AddBorders (clip=vid, left=0, right=0, top=44, bottom=44)

vid.set_output ()


Love to learn what's going on.
And is it using only the Performance cores, or is it getting confused and either only using the Efficiency cores, or mixing up the two and throwing tasks to both types, which will bottleneck the P-cores to whatever speed the E-cores are going at?

LigH
9th January 2022, 07:55
Try https://frupic.frubar.net as simple image hoster.

lewyturn
15th January 2022, 06:23
How to use "std.SplitPlanes(vnode clip)'", I can't find an example, can anyone give me an example?

poisondeathray
15th January 2022, 06:30
How to use "std.SplitPlanes(vnode clip)'", I can't find an example, can anyone give me an example?

e.g for YUV clip, . Y plane would be [0], U plane would be [1], V would be [2] ; similar for RGB (0,1,2)

s = core.std.SplitPlanes(clip)
s[0].set_output() #output Y plane

Jukus
15th January 2022, 19:42
I'm trying to get QTGMC to work on Debian, I installed everything need from http://deb-multimedia.org/dists/stable/main/binary-amd64/ and separately the scripts, I get this error:
Failed to evaluate the script:
Python exception: znedi3: error reading weights

Traceback (most recent call last):
File "vapoursynth.pyx", line 2242, in vapoursynth.vpy_evaluateScript
File "vapoursynth.pyx", line 2243, in vapoursynth.vpy_evaluateScript
File "/usr/local/lib/python3.9/dist-packages/havsfunc.py", line 1314, in QTGMC
edi1 = QTGMC_Interpolate(ediInput, InputType, EdiMode, NNSize, NNeurons, EdiQual, EdiMaxD, pscrn, int16_prescreener, int16_predictor, exp, alpha, beta, gamma, nrad, vcheck,
File "/usr/local/lib/python3.9/dist-packages/havsfunc.py", line 1595, in QTGMC_Interpolate
interp = nnedi3(Input, field=field, planes=planes)
File "vapoursynth.pyx", line 2067, in vapoursynth.Function.__call__
vapoursynth.Error: znedi3: error reading weights
What to do?

poisondeathray
15th January 2022, 19:54
I'm trying to get QTGMC to work on Debian, I installed everything need from http://deb-multimedia.org/dists/stable/main/binary-amd64/ and separately the scripts, I get this error:
[CODE]Failed to evaluate the script:
Python exception: znedi3: error reading weights


does the package include nnedi3_weights.bin ?

https://github.com/dubhater/vapoursynth-nnedi3/blob/v6/src/nnedi3_weights.bin

Jukus
15th January 2022, 20:02
does the package include nnedi3_weights.bin ?

https://github.com/dubhater/vapoursynth-nnedi3/blob/v6/src/nnedi3_weights.bin
Yes
/usr/share/nnedi3/nnedi3_weights.bin

Jukus
16th January 2022, 17:59
Need to move nnedi3_weights.bin to
/usr/lib/x86_64-linux-gnu/vapoursynth/

Anyway, something is very bad, before that I used everything new on Arch from AUR and the performance was 2 times better

mastrboy
16th January 2022, 20:47
Could someone help explain how trim and slice works in vapoursynth?

I am struggling converting a simple avisynth script where I replace a segment of a clip with some frames from a different clip and are unable to get it to work in vapoursynth.

video_a = core.dgdecodenv.DGSource(f"E:\video_a.dgi")
video_b = core.dgdecodenv.DGSource(f"E:\video_b.dgi")
video_b = video_b[12:2156] # 2156 - 12 = 2144 frames

#Neither of the following works at all in vapoursynth, I can't figure out how to reference "end of clip/last frame" in vapoursynth trim...
video = core.std.Trim(video_a,0,5298) + video_b + core.std.Trim(video_a,7444,-1)
video = core.std.Trim(video_a,0,5298) + video_b + core.std.Trim(video_a,7444,0)

#The following returns a video, but returns fewer frames than expected (7443 - 5299 = 2144 frames):
video = video_a[0:5298] + video_b + video_a[7444:-1]

Original clip has 34311 frames, but using vapoursynth slice the returned clip only has 34308.
So in python/vapoursynth either 1+1 does not equal 2 or I have forgotten how to do simple math...

ChaosKing
16th January 2022, 20:50
http://www.vapoursynth.com/doc/pythonreference.html#slicing-and-other-syntactic-sugar

clip = clip[5:11] <=> clip = core.std.Trim(clip, first=5, last=10)

mastrboy
16th January 2022, 21:16
http://www.vapoursynth.com/doc/pythonreference.html#slicing-and-other-syntactic-sugar

clip = clip[5:11] <=> clip = core.std.Trim(clip, first=5, last=10)

Wait... You are telling me that the code for slice subtracts 1 for the second argument? What exactly is the purpose for that?

I would then absolutely prefer to just use Trim rather than remembering that -1 stuff, but does anyone know how to reference the last frame in Trim like slice does with "-1" or avisynth does with trim(10,0)?

ChaosKing
16th January 2022, 21:22
(untested) I think it's just std.Trim(10)

mastrboy
16th January 2022, 21:54
(untested) I think it's just std.Trim(10)

Thanks, that worked, and I feel like an idiot for not testing it without the second argument :D

It's a lot better than the "solution" I found in my own: core.std.Trim(video,10,video.num_frames - 1)

Overdrive80
16th January 2022, 22:11
Hi, folks.

Could somebody help me with vapoursynth?

It's been a while since I left the world of publishing but recently I took up a project that I would like to have ready for when my son is born. The fact is that I wanted to install vapoursynth and what used to work for me now doesn't.

I have checked the script and VSEdit says it is correct. The video is fine because I had to install AVS+ and it loads without any problems.

My system is: Windows 11 x64
Python installed: 3.9.9 and 3.10.1 (use VSC)
Vapoursynth: R57
Code: from vapoursynth import core
import vapoursynth as vs
core = vs.core

#video = core.ffms2.Source(source=r"C:\xxx\Movie.mkv") #,format=vs.YUV420P8)
video = core.lsmas.LWLibavSource(r"C:\xxx\Movie.mkv", format=vs.YUV420P8)

video.set_output()

Problem: Error forming pixmap from frame. Expected format CompatBGR32. Instead got 'YUV420P8'.

I have also tried VSEdit2 and when previewing the program it closes.

https://i.postimg.cc/qgxSHFKQ/Captura-de-pantalla-2022-01-16-220433.png (https://postimg.cc/qgxSHFKQ)

Thanks in advance.

poisondeathray
16th January 2022, 22:27
Overdrive80 - are you using vsedit mod for API4 and r57 ?

https://github.com/YomikoR/VapourSynth-Editor/releases

Overdrive80
17th January 2022, 01:49
@Poison

Nop, for VSEditor was using https://bitbucket.org/mystery_keeper/vapoursynth-editor/downloads/ and for V2 https://bitbucket.org/gundamftw/vapoursynth-editor-2/downloads/

Then, do you think that could be for VSeditor??

EDIT: I have tried the version that you post and is the same result, close of application.

_Al_
17th January 2022, 05:53
Wait... You are telling me that the code for slice subtracts 1 for the second argument? What exactly is the purpose for that?
As soon ,as there is a programming involved, it just works. Indexing is always from zero. So for example you need to slice an interval and you know it starts on 10th frame including and length is 5 frames, so it is:
frame=10
length = 5
clip[frame:frame+length]
If both frames were included you'd need to use clip[frame:frame+length-1]. Imagine more intervals, easily turning it into nightmare as well.

Slicing is still better, as long as you remember this rule, because, you do not need to specify position if slicing from beggining:
clip[:100] #slicing first 100 frames (you see again, you want just first 100 frames, you do this and not confusing: clip[:100-1]

or more importandly, better if slicing from a middle to the end:
clip[10:] # using 10th frame index to the end
so
clip = clip.std.Trim(first=10, last=clip.num_frames-1)
is the same as:
clip = clip[10:]

If using keyword arguments always and not just:
clip = clip.std.Trim(10, clip.num_frames-1)
is better way, because above line is not readable much. Avisynth users do that all the time, using lines like: filter(3,56, -1, 45, 1000, 0) is just a nightmare to read. :-)
Prone to make mistakes.

Overdrive80
17th January 2022, 13:15
@poisondeathray

If I trying open script with vdub2 I get this message: "AVI import filter error: (Unknown) (80040154)"

https://i.postimg.cc/TLCq2B6v/Captura-de-pantalla-2022-01-17-131343.png (https://postimg.cc/TLCq2B6v)

EDIT: Solved. I had uninstall all and I had followed the instructions of https://www.l33tmeatwad.com/vapoursynth101/software-setup, with sames versions of files (python and vapoursynth). I could investigate what caused the problem, whether VS or Python

~ VEGETA ~
27th January 2022, 06:09
when I try running a simple scrip which has hafsfunc in it (and other wrappers) it gives me that there is no module named packaging. I installed python 3.9.7 for all users as well as vapoursynth 57.

plus, vs editor 2 stops working right after i press preview... while vs edit 1 works, but it doesn't show the output..

Julek
28th January 2022, 14:24
when I try running a simple scrip which has hafsfunc in it (and other wrappers) it gives me that there is no module named packaging. I installed python 3.9.7 for all users as well as vapoursynth 57.

plus, vs editor 2 stops working right after i press preview... while vs edit 1 works, but it doesn't show the output..

You need LibP2P library for vsedit 2.

Jukus
28th January 2022, 17:54
Need to move nnedi3_weights.bin to
/usr/lib/x86_64-linux-gnu/vapoursynth/

Anyway, something is very bad, before that I used everything new on Arch from AUR and the performance was 2 times better
I built everything new from git, updated proprietary Nvidia drivers from backports and still performance is almost 2 times less on Debian than it was on Arch, it looks magical.

~ VEGETA ~
28th January 2022, 21:45
You need LibP2P library for vsedit 2.

it is installed, everything should be fine but still doesn't work.

I read that it doesn't work after vapoursynth 54.

can you verify?

DJATOM
29th January 2022, 16:29
Try to load explicitly via core.std.LoadPlugin. That way you will see an error if plugin fails to load.

~ VEGETA ~
29th January 2022, 19:38
Try to load explicitly via core.std.LoadPlugin. That way you will see an error if plugin fails to load.

well, now it worked fine by itself. i just re-installed it via the vsrepo after uninstalling it.

my problem now is with vsedit 2 not working

Selur
9th February 2022, 10:19
Small question: Is there a deflicker filter for Vapoursynth? (as alternative to http://avisynth.nl/index.php/DeFlicker or https://github.com/Asd-g/ReduceFlicker on AviSynth)
found https://github.com/VFR-maniac/VapourSynth-ReduceFlicker, but sadly no binaries for it.

kedautinh12
9th February 2022, 11:24
Here:
https://github.com/AmusementClub/ReduceFlicker

Selur
9th February 2022, 11:34
Nice! Thanks! :)

Cu Selur

ChaosKing
9th February 2022, 12:11
Also available via vsrepo.
Btw you can also quickly lookup vsrepo plugins online via https://vsdb.top/vsrepogui

Selur
9th February 2022, 12:21
Thanks :)

Jukus
9th February 2022, 13:24
What can do if the DVD has video in two angles? If just use d2vwitch then get video and audio where 2 seconds of video comes from one angle and then the same action from the other angle.

Selur
9th February 2022, 14:55
Use PGCDemux or similar to extract the content you want.
There is no Vapoursynth filter (neither is there one for Avisynth) which properly parses DVD structures in details.

Boulder
9th February 2022, 16:38
Why not use the good old DGIndex to create the d2v file.

Jukus
9th February 2022, 17:50
I don't feel like using Windows programs even under Wine
Thanks for the answers

ChaosKing
9th February 2022, 18:00
Linux / cross plattform alternative https://github.com/dubhater/D2VWitch

Jukus
9th February 2022, 18:03
Linux / cross plattform alternative https://github.com/dubhater/D2VWitch
What can do if the DVD has video in two angles? If just use d2vwitch then get video and audio where 2 seconds of video comes from one angle and then the same action from the other angle.
Use PGCDemux or similar to extract the content you want.
There is no Vapoursynth filter (neither is there one for Avisynth) which properly parses DVD structures in details.
*****

Boulder
9th February 2022, 18:48
I don't feel like using Windows programs even under Wine
Thanks for the answers

What if you pretend that it's not a Windows program :D:p

Or ask if videoh could do a Linux build. Or use a Linux build of DGIndexNV+DGSource if you have a suitable GPU.

Jukus
9th February 2022, 19:59
not very elegant, but solved my problem with https://www.makemkv.com/

Selur
14th February 2022, 14:22
Is there an Vapoursynth plugin for inpainting?

kedautinh12
14th February 2022, 14:32
Here:
https://github.com/invisiblearts/VapourSynth-Inpaint

Selur
14th February 2022, 14:50
Does that actually work? Code seems rather short with 133lines. (cpp file)
Also is there a compiled version of this?

Selur
17th February 2022, 15:58
Is it possible to restrict the number of threads for just a specific filter?

PRAGMA suggested:
One mistake people are doing is letting VS use the default multi-threading with EGVSR when it should be disabled with `core.num_threads = 1`. Once you do this, it will only run the model on the current frame + n(interval) next frames at a time, instead of e.g. 72 frames with a num_threads of 1
source: https://forum.doom9.org/showpost.php?p=1962294&postcount=83

So I was wonder whether one could limit the threads just for vsgan and keep the rest of the script running with the full number of threads?

Cu Selur

Myrsloik
18th February 2022, 01:27
Recompile/binary hack the filter to be a parallel requests filter instead of true parallel.

I guess.

Selur
18th February 2022, 05:58
Okay, that isn't really an option or generic use, but thanks for clearing that up. :)

Cu Selur

Myrsloik
18th February 2022, 09:25
Okay, that isn't really an option or generic use, but thanks for clearing that up. :)

Cu Selur

Why do you need it for "generic use"? Badger the filter authors until they write it properly instead. Not going to implement hacks for badly programmed things.

Selur
18th February 2022, 10:05
Why do you need it for "generic use"?
So that I don't have to "Badger the filter authors until they write it properly instead." for any filter where this might happen. :D
It's no problem I can live with it. :)
Not going to implement hacks for badly programmed things.
btw. any news regarding the possiblity to disable auto loading filter?

Cu Selur

mastrboy
19th February 2022, 14:24
How does one convert a framenumber to a "audio sample unit"?

Trying to to use std.AudioTrim to match std.Trim for some video cutting.

I already checked the docs (http://www.vapoursynth.com/doc/functions/audio/audiotrim.html) but there is no info how to convert between those units...

lewyturn
20th February 2022, 13:26
How to use this function 'vscomp.comp'. can anyone help me with an example?

DJATOM
20th February 2022, 15:19
How does one convert a framenumber to a "audio sample unit"?

Trying to to use std.AudioTrim to match std.Trim for some video cutting.

I already checked the docs (http://www.vapoursynth.com/doc/functions/audio/audiotrim.html) but there is no info how to convert between those units...

I think it's accurate enough
samples_per_video_frame = sample_rate / 24000 * 1001 (fps)
audio_sample_position = video_frame * samples_per_video_frame

mastrboy
21st February 2022, 00:50
I think it's accurate enough
samples_per_video_frame = sample_rate / 24000 * 1001 (fps)
audio_sample_position = video_frame * samples_per_video_frame

Thanks, you got me on the right track:
samples_per_video_frame = audio.sample_rate / video.fps.numerator * video.fps.denominator
audio_trim_start = trim_start * samples_per_video_frame
audio_trim_end = trim_end * samples_per_video_frame

It's a weird default unit for a mainly video editing tool though...
Would love to see something like a "unit_type" parameter to choose between frames and audio samplerate, would be easier for python noobs like myself.

DJATOM
21st February 2022, 08:23
No, there's a reason to trim on sample positions. Audio and video isn't interleaved, also you cant reliably trim vfr video with audio (it requires evaluation of entire video clip).

mastrboy
6th March 2022, 17:09
Is it possible to get the framenumber to audio sample unit calculation more "accurate" ?

I'm not getting the same result when comparing the same trimmed audio between Vapoursynth and Avisynth.
Vapoursynth audio after trim: 00:23:31.535
Avisynth audio after trim: 00:23:31.576

A 41ms difference, this ends up being noticeable during video playback when using multiple trims unfortunately.

tebasuna51
7th March 2022, 01:29
I'm not getting the same result when comparing the same trimmed audio between Vapoursynth and Avisynth.
Maybe because an AviSynth Trim go from the begining of first frame to the end of last frame?

mastrboy
8th March 2022, 00:38
Maybe because an AviSynth Trim go from the begining of first frame to the end of last frame?

Might be, I think I found audiotrim function for avisynth:
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/edit.cpp#L124

If that is the correct one, it does a lot more than the few python lines I used.
Unfortunately I don't know enough c++ and python to port that over to a vapoursynth function.

I'll just stick with audio work in avisynth until someone writes a more userfriendly wrapper function for trimming audio in vapoursynth.

Selur
10th March 2022, 17:25
Is there a Vapoursynth alternative to Avisynths 'UnDot' filter?

Myrsloik
10th March 2022, 17:46
Is there a Vapoursynth alternative to Avisynths 'UnDot' filter?

UnDot is equivalent to one of the removegrain modes since it's a simple median like thing. I think it's mode 1.

Selur
10th March 2022, 18:07
okay, thanks. :)

Selur
13th March 2022, 15:41
When using:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
core = vs.core
# Loading Plugins
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/SourceFilter/DGDecNV/DGDecodeNV.dll")
# source: 'C:\Users\Selur\Desktop\C0561.MP4'
# current color space: YUV420P8, bit depth: 8, resolution: 3840x2160, fps: 25, color matrix: 2020cl, yuv luminance scale: full, scanorder: progressive
# Loading C:\Users\Selur\Desktop\C0561.MP4 using DGSource
clip = core.dgdecodenv.DGSource("E:/Temp/mp4_ea827f2d745535e110d775a539fd1cdd_853323747.dgi")
# Setting color matrix to 2020cl.
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=10)
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=9)
clip = core.std.SetFrameProps(clip, _Matrix=10)
# Setting color range to PC (full) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=0)
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()
and opening it in https://github.com/YomikoR/VapourSynth-Editor
I get:
Error on frame 0 request:
Resize error: Resize error 3074: invalid colorspace definition (10/2/2 => 0/2/2). May need to specify additional colorspace parameters.
which is cause by
clip = core.std.SetFrameProps(clip, _Matrix=10).
first I thought I used the wrong Matrix value, but looking at http://www.vapoursynth.com/doc/functions/video/resize.html and then https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201612-S!!PDF-E&type=items table E.5 then is correct for "Rec. ITU-R BT.2020-2 constant luminance system" (same indicated in https://github.com/UniversalAl/view/blob/02bbbd982b346d0131e479478ab9949690c4bf7b/view.py#L143)

Using:
VSPipe.exe -p c:\Users\Selur\Desktop\testing.vpy e:\test.y4m
an output file is created, but ffplay reports:
[yuv4mpegpipe @ 0000023b56629440] Format yuv4mpegpipe detected only with low score of 1, misdetection possible!
[yuv4mpegpipe @ 0000023b56629440] Header too large.
and MediaInfo only reports:
General
Complete name : e:\test.y4m
File size : 8.20 GiB

using:
VSPipe.exe c:\Users\Selur\Desktop\testing.vpy -c y4m | i:\Hybrid\64bit\x264.exe --demuxer y4m -o e:\test.mkv -
gives me:

y4m [error]: bad sequence header magic
x264 [error]: could not open input file `-'

I'm using:

VapourSynth Video Processing Library
Copyright (c) 2012-2021 Fredrik Mellbin
Core R57
API R4.0
API R3.6
Options: -

I just tested 'clip = core.std.SetFrameProps(clip, _Matrix=9)' and get a preview.

-> Any idea what am I missing? Do I need to specify some additional info before setting '_Matrix' ? Shouldn't 2020cl(=10) work?

Cu Selur

Myrsloik
25th March 2022, 09:09
R58-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R58-RC1)

Will probably be realeased in a few days unless major bugs are found.

r58:
updated the supported python versions to 3.10 and 3.8
updated visual studio 2022 runtime version
updated projects to visual studio 2022
updated zimg to 3.0.4
fixed certain expressions failing to compile in expr filter
fixed averageframes not respecting scenechange property (sekrit-twc)
added bob filter (sekrit-twc)
added support for separable convolutions and optimized convolution in general (sekrit-twc)
fixed audionode get_frame() in python
enabled cache for nodes with no registered dependencies, this means nodes returned by getoutput won't need to manually have the cache enabled if they have no filter consumers

Yomiko
25th March 2022, 11:50
Could you please mention in the changelog that "prefer_props" is no more an argument of internal resizers? I'm sure people are going to ask because this breaks existing previewers.

Selur
25th March 2022, 16:28
I agree. Is there some overview somewhere what API-wise changed from R57 to R58?

Myrsloik
25th March 2022, 20:15
I agree. Is there some overview somewhere what API-wise changed from R57 to R58?

Nothing should have changed. Maybe I'll add back a dummy prefer_props argument to avoid breakage.

Selur
26th March 2022, 13:08
One thing that did change is that since Python 3.9 isn't supported all the ml based filters form HolyWu don't work any more. So anyone who uses them should not upgrade to Vapoursynth R58 just yet.
-> okay filters should work again when https://pypi.org/project/VapourSynth/#files get's updated. So probably when R58 final gets release. :)

@Myrsloik: Any update on an option to stop autoloading?

l33tmeatwad
31st March 2022, 22:13
Nothing should have changed. Maybe I'll add back a dummy prefer_props argument to avoid breakage.
That would be great to help support older systems that may not be able to update to the latest preview versions.

Myrsloik
1st April 2022, 13:50
One thing that did change is that since Python 3.9 isn't supported all the ml based filters form HolyWu don't work any more. So anyone who uses them should not upgrade to Vapoursynth R58 just yet.
-> okay filters should work again when https://pypi.org/project/VapourSynth/#files get's updated. So probably when R58 final gets release. :)

@Myrsloik: Any update on an option to stop autoloading?

Sure, it's called "use the portable version". Maybe another option will appear at some later date but not a high priority.

Selur
1st April 2022, 14:36
Sure, it's called "use the portable version". Maybe another option will appear at some later date but not a high priority.
Problem is I use a portable version in Hybrid, but folks sometimes also have installed a system wide version where they have dlls in that version that get autoloaded. Which results in users complaining about errors like:
vapoursynth.Error: Plugin D:/Programs/Hybrid/64bit/vsfilters/DenoiseFilter/KNLMeansCL/KNLMeansCL.dll already loaded (com.Khanattila.KNLMeansCL) from D:/Programs/VapourSynth64Portable/VapourSynth64/vapoursynth64/plugins/KNLMeansCL.dll
To avoid these it would be nice to have a way to disable the autoloading inside the script. :)

Myrsloik
1st April 2022, 15:32
Problem is I use a portable version in Hybrid, but folks sometimes also have installed a system wide version where they have dlls in that version that get autoloaded. Which results in users complaining about errors like:
vapoursynth.Error: Plugin D:/Programs/Hybrid/64bit/vsfilters/DenoiseFilter/KNLMeansCL/KNLMeansCL.dll already loaded (com.Khanattila.KNLMeansCL) from D:/Programs/VapourSynth64Portable/VapourSynth64/vapoursynth64/plugins/KNLMeansCL.dll
To avoid these it would be nice to have a way to disable the autoloading inside the script. :)

Or you could catch the exception and move on? If the user wants to override plugin versions you don't have to fail...

Selur
1st April 2022, 15:48
Sure I could write a wrapper which does a try&catch, but that really seems like a really ugly workaround and it would only lead to more confusion, because then you wouldn't know what file versions are loaded.
Would it may be possible to add an additional parameter to 'core.std.LoadPlugin' to change the default behaviour from 'throw error if dll is already loaded' to 'drop already loaded dll and use the one explicitly called' ?
(explicitly loaded libaries should trump out automatically loaded ones)

Cu Selur

_Al_
1st April 2022, 16:48
On occasions I experienced some problems too. Having installed vs and also many portable versions with different python and vs versions. Giving portable frozen versions to someone where user might load different DLL.

Reading Selur idea to "unload" dll if a conflict happens, and load portable dll, would it be possible to use ctypes as well? Like here:
https://stackoverflow.com/questions/19547084/can-i-explicitly-close-a-ctypes-cdll
windows:
file = ctypes.CDLL('file.dll')
handle = file._handle
windll.kernel32.FreeLibrary(handle)
or linux:
file = CDLL('./file.so')
handle = file._handle
cdll.LoadLibrary('libdl.so').dlclose(handle)

Not sure where windll and cdll comes from, are they ctype modules? Upper or lower case could be used?

Even if it worked it introduces os dependancy so vs solution to "unload" might be the best. But only if it sort of knows what dlls are to be loaded beforehand. Because if already loaded, would vs have to deal with this also depending on operating system?

So a choice not to load dll's explicitly by vs seams like a solution.

_Al_
1st April 2022, 17:07
this has more details too: https://stackoverflow.com/questions/359498/how-can-i-unload-a-dll-using-ctypes-in-python
in the middle of page there are examples for win, linux, darwin, msys, cygwin, freeBSD

EDIT: fixed the link

Selur
1st April 2022, 17:17
@_AI_: that link doesn't work,...

Myrsloik
1st April 2022, 17:21
R58-RC2 (https://github.com/vapoursynth/vapoursynth/releases/tag/R58-RC2)
Adds a dummy prefer_props argument. Test so it actually fixinates things.

Selur
13th April 2022, 18:53
Thanks for R58. :)
https://github.com/vapoursynth/vapoursynth/releases/tag/R58

Cu Selur

Ps.: btw. who updates the version over at https://pypi.org/search/?q=Vapoursynth&o= ?

l33tmeatwad
14th April 2022, 18:29
So I've stumbled upon an issue I didn't realize was there for macOS, apparently R55+ will crash when using subtext. So the few tests I did revealed the lib that works in R54 hard crashes on R55+, and compiling from the new respiratory doesn't give any different results. I'm using static libs for the dependencies and I'm going to test with shared libs sometime next week, but I was just curious if there was some change in R55 they would have completely broke it. It appears it's saying it's missing calls from freetype, however this was not an issue on R54 with the same lib.

Myrsloik
14th April 2022, 19:45
So I've stumbled upon an issue I didn't realize was there for macOS, apparently R55+ will crash when using subtext. So the few tests I did revealed the lib that works in R54 hard crashes on R55+, and compiling from the new respiratory doesn't give any different results. I'm using static libs for the dependencies and I'm going to test with shared libs sometime next week, but I was just curious if there was some change in R55 they would have completely broke it. It appears it's saying it's missing calls from freetype, however this was not an issue on R54 with the same lib.

Try to get something out of gdb. I'm curious where things go wrong exactly. The code itself has very little changes from when it was a part of the main repo so it shouldn't affect anything.

l33tmeatwad
14th April 2022, 21:03
I'll see what I can find out when I get the chance next week, and just to be clear, the lib from R54 crashes too with VapourSynth R55+, but still works fine with R54.

ChaosKing
19th April 2022, 09:29
Are there offical doc pages somewhere available for the former included plugins like subtext? http://www.vapoursynth.com/doc/plugins/subtext.html
Or is this now the offical "doc page"? https://github.com/vapoursynth/subtext/blob/master/docs/subtext.rst

Myrsloik
19th April 2022, 10:11
Are there offical doc pages somewhere available for the former included plugins like subtext? http://www.vapoursynth.com/doc/plugins/subtext.html
Or is this now the offical "doc page"? https://github.com/vapoursynth/subtext/blob/master/docs/subtext.rst

That is indeed the most official page. I should set it up to generate a proper html again some day.

Selur
19th April 2022, 16:46
btw.: does anyone have an idea when Vapoursynth R58 will be available through pip?

Myrsloik
19th April 2022, 22:40
btw.: does anyone have an idea when Vapoursynth R58 will be available through pip?

The current packager no longer has a windows computer and effectively quit.

Write your application for the position below the line.
-----------------------------------------------------------

Selur
20th April 2022, 04:03
The current packager no longer has a windows computer and effectively quit.
Thanks for the info. :)

sofakng
27th April 2022, 19:18
Does VapourSynth depend on memory (RAM) speed? I'm having issues with extremely large videos (6K-8K). They are choppy when playback is started but then it smooths out.

However, it also heavily stutters using interpolation (SVP/RIFE) but I'm seeing low CPU/GPU usage so I'm thinking it might be RAM related?

Myrsloik
27th April 2022, 20:38
Does VapourSynth depend on memory (RAM) speed? I'm having issues with extremely large videos (6K-8K). They are choppy when playback is started but then it smooths out.

However, it also heavily stutters using interpolation (SVP/RIFE) but I'm seeing low CPU/GPU usage so I'm thinking it might be RAM related?

Yes, it's extremely dependent on ram bandwidth for 4k+ resolutions.

sofakng
27th April 2022, 21:18
Is there a benchmark that I can run or how can I determine what speed is required?

For example, I'm on an i7-8700k (5.0 GHz) and the RAM is 32GB (8GBx4) but it's DDR4 at 3200 MHz. I can upgrade to DDR4 4133 MHz but I'm not sure if that is enough or if I need DDR5 (and a new motherboard/cpu, etc).

(Also, I think my issue might not be related to RAM [I've posted an issue on the VapourSynth GitHub] but I'm still interested in RAM requirements, etc)

ChaosKing
27th April 2022, 21:28
You could also try to set a high max_cache_size and see if it helps http://www.vapoursynth.com/doc/pythonreference.html?#Core.max_cache_size

Selur
6th May 2022, 13:44
Can someone compile https://github.com/Setsugennoao/VapourSynth-removedirt for Win 64bit?
I'd like to know whether the fixes and changes Setsugennoa made to the source fix the crashes I encountered (https://forum.doom9.org/showthread.php?p=1964324#post1964324).

kedautinh12
6th May 2022, 13:57
So simple if you ask author :D

Selur
6th May 2022, 14:31
no issue tracker -> no clue how to contact the author :)

kedautinh12
6th May 2022, 14:47
Ask in another issues tab project and say sorry cause don't have issues tab in removedirt :D
https://github.com/Setsugennoao/vs-parsedvd/issues

Selur
6th May 2022, 16:56
Got in touch with Setsugennoao, sadly his build also crashed the same way :( as https://github.com/handaimaoh/removedirtvs and https://github.com/pinterf/removedirtvs do.

stax76
25th May 2022, 16:19
A guide showing how to use VapourSynth in mpv.net:

https://github.com/stax76/mpv.net/wiki/Using-VapourSynth-in-mpv.net

stax76
25th May 2022, 16:19
A guide showing how to use VapourSynth in mpv.net:

https://github.com/stax76/mpv.net/wiki/Using-VapourSynth-in-mpv.net

Myrsloik
25th May 2022, 19:07
https://github.com/vapoursynth/vapoursynth/releases/tag/R59-RC1 (R59-RC1)
r59:
fixed several convolution crashes
fixed averageframes weights with float input
fixed rare cython memory leak on error

Selur
26th May 2022, 15:10
Thanks. (still hoping an option to disable 'auto loading' will come some time)

Myrsloik
5th June 2022, 11:50
R59 is out (https://github.com/vapoursynth/vapoursynth/releases/tag/R59)

Pure bug fix release.

ChaosKing
16th June 2022, 07:00
The link “Plugins and Scripts“ is still linked to the old page (which does not exist anymore) on vapoursynth.com

Yomiko
21st June 2022, 14:17
Any chance for an official audio visualization plugin?

Selur
25th June 2022, 07:10
How would one port Avisynth: "mt_expand(y=3,u=-128,v=-128)" to Vapoursynth using core.std.Maximum ?

Greenhorn
25th June 2022, 19:26
How would one port Avisynth: "mt_expand(y=3,u=-128,v=-128)" to Vapoursynth using core.std.Maximum ?

If I read that correctly, that call just processes the y plane normally and sets u and v to 128. (According to http://avisynth.nl/index.php/MaskTools2/mt_expand)

So I think you could do:

y, u, v = your_clip.std.SplitPlanes()
y = y.std.Maximum()
u = core.std.BlankClip(u, color=128)
v = core.std.BlankClip(v, color=128)
your_choice_of_name = core.std.ShufflePlanes([y,u,v], [0,0,0], vs.YUV)

Does that work? (If your clip isn't actually 8bpc, I suppose you'll need to scale 128 to an appropriate value with either simple algebra or one of the various helper functions out there.)

Selur
25th June 2022, 20:50
I get:
ry, ru, rv = core.std.SplitPlanes(rainbow)
ValueError: too many values to unpack (expected 3))

Here's where I use this:
from vapoursynth import core
import vapoursynth as vs

# requires:
# * BiFrost: https://github.com/dubhater/vapoursynth-bifrost
# * TemporalSoften: https://github.com/dubhater/vapoursynth-temporalsoften
# I think this could be replaced by TemporalSoften2 https://github.com/dubhater/vapoursynth-temporalsoften2

# raidus = temporal radius
# th = threshold
def ChubbyRain2(clip: vs.VideoNode, th: int= 0, radius: int=3, show: bool=False, interlaced: bool=False):
if interlaced:
es = core.std.SeparateFields(clip=clip)
else:
res = clip

y = core.std.ShufflePlanes(res, planes=0, colorfamily=vs.GRAY)
u = core.std.ShufflePlanes(res, planes=1, colorfamily=vs.GRAY)
v = core.std.ShufflePlanes(res, planes=2, colorfamily=vs.GRAY)

uc = core.std.Convolution(u, [1,-2,1], mode = "v")
vc = core.std.Convolution(v, [1,-2,1], mode = "v")


ucc = core.std.Convolution(u, [1,2,1], planes=0, mode = "v")
vcc = core.std.Convolution(v, [1,2,1], planes=0, mode = "v")

cc = core.std.ShufflePlanes([y,ucc,vcc], planes=[0, 0, 0], colorfamily=vs.YUV)
cc = core.bifrost.Bifrost(cc)
cc = core.focus.TemporalSoften(cc, radius=radius,luma_threshold=0, chroma_threshold=255,scenechange=2 , mode=2)

expr = "x y + " + str(th) + " > " + str(256 << (clip.format.bits_per_sample - 8)) + " 0 ?"
rainbow = core.std.Expr([uc,vc],expr)
rainbow = core.resize.Point(rainbow, res.width, res.height)

ry, ru, rv = core.std.SplitPlanes(rainbow)
ry = std.Maximum(ry)
ru = core.std.BlankClip(ru, color=128 << (clip.format.bits_per_sample - 8))
rv = core.std.BlankClip(rv, color=128 << (clip.format.bits_per_sample - 8) )
rainbow = core.std.ShufflePlanes([ry,ru,rv], [0,0,0], vs.YUV)

resfinal = core.std.MaskedMerge(res, cc, rainbow)

if show:
output = rainbow
else:
if interlaced:
output = core.std.DoubleWeave(resfinal)
output = core.std.SelectEvery(output, 2, 0)
else:
output = resfinal

return output
Original AviSynth version: http://avisynth.nl/images/ChubbyRain2.avsi

mastrboy
25th June 2022, 22:28
While I don't have a solution to your current issue, are you not missing the cnr2() function call? (http://avisynth.nl/index.php/Cnr2)

I doubt it would function the same without it?

Selur
26th June 2022, 05:13
@mastrboy: yes, you are right I missed the cnr2 call.

---
Okay, I see why the ValueError happens rainbow is Gray8

def ChubbyRain2(clip: vs.VideoNode, th: int=10, radius: int=3, show: bool=False, sft: int=10, interlaced: bool=False):
if interlaced:
res = core.std.SeparateFields(clip=clip)
else:
res = clip

y = core.std.ShufflePlanes(res, planes=0, colorfamily=vs.GRAY)
u = core.std.ShufflePlanes(res, planes=1, colorfamily=vs.GRAY)
v = core.std.ShufflePlanes(res, planes=2, colorfamily=vs.GRAY)

uc = core.std.Convolution(u, [1,-2,1], mode = "v")
vc = core.std.Convolution(v, [1,-2,1], mode = "v")


ucc = core.std.Convolution(u, [1,2,1], planes=0, mode = "v")
vcc = core.std.Convolution(v, [1,2,1], planes=0, mode = "v")

cc = core.std.ShufflePlanes([y,ucc,vcc], planes=[0, 0, 0], colorfamily=vs.YUV)
cc = core.bifrost.Bifrost(cc)
cc = core.cnr2.Cnr2(cc)
cc = core.focus.TemporalSoften(cc, radius=radius, luma_threshold=0, chroma_threshold=sft, scenechange=2 , mode=2)
#cc = core.focus2.TemporalSoften2(cc, radius=radius, luma_threshold=0, chroma_threshold=sft, scenechange=2 , mode=2)

shift = (clip.format.bits_per_sample - 8)
expr = "x y + " + str(th) + " > " + str(256 << shift) + " 0 ?"
rainbowMask = core.std.Expr([uc,vc],expr)
rainbowMask = core.resize.Point(rainbowMask, res.width, res.height)
rainbowMask = core.std.Maximum(rainbowMask)

resfinal = core.std.MaskedMerge(res, cc, rainbowMask)

if show:
output = rainbowMask
else:
if interlaced:
output = core.std.DoubleWeave(resfinal)
output = core.std.SelectEvery(output, 2, 0)
else:
output = resfinal

return output

doesn't crash, but the output is kind of broken. :/ doh "th: int=0" -> "th: int=10"

ChaosKing
26th June 2022, 06:57
es = core.std.SeparateFields(clip=clip) should be res = ...

Selur
26th June 2022, 07:02
thanks, fixed.

Selur
30th June 2022, 19:30
btw. does someone know an alternative to ExBlend for Vapoursynth, something that tries to fix blends and not 'just' try to drop the fields like sRestore, Cdeblend?

Julek
30th June 2022, 23:08
btw. does someone know an alternative to ExBlend for Vapoursynth, something that tries to fix blends and not 'just' try to drop the fields like sRestore, Cdeblend?

https://github.com/dnjulek/jvsfunc/blob/main/jvsfunc/deblend.py#L16-L40

Selur
1st July 2022, 15:45
Will try thanks. :)(sadly unlike exblend in Avisynth it doesn't seem to do anything for the clip, see exblend thread)

ChaosKing
3rd July 2022, 21:25
Will there be a binary for the R2 imwri release?

Myrsloik
4th July 2022, 15:26
Will there be a binary for the R2 imwri release?

Done. Forgot to check back for the artifacts to grab binaries.

Selur
7th July 2022, 17:20
Using BlankClip (http://www.vapoursynth.com/doc/functions/video/blankclip.html) there is a color parameter,
float[] color=<black>
is there some documentation about this? What range are these floats? I guess one should use three or four, right? Is the color selection etc. dependend of the used color space (type, sampling, bit depth)?

Myrsloik
7th July 2022, 17:43
Using BlankClip (http://www.vapoursynth.com/doc/functions/video/blankclip.html) there is a color parameter,
float[] color=<black>
is there some documentation about this? What range are these floats? I guess one should use three or four, right? Is the color selection etc. dependend of the used color space (type, sampling, bit depth)?

They are 1:1 copied into the destination clip (rounded for int formats of obviously). Out of range values for the format throws an error. Number of planes values expected.

Selur
7th July 2022, 18:07
Okay,.. so the best way if I got a rgb(50,205,50) color coding would be to first create a RGB24 clip with my values and then use for example:
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, matrix_s="470bg", range_s="limited")
to convert to YUV420P8 if that is the color space I need, right?

Myrsloik
7th July 2022, 18:20
Okay,.. so the best way if I got a rgb(50,205,50) color coding would be to first create a RGB24 clip with my values and then use for example:
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, matrix_s="470bg", range_s="limited")
to convert to YUV420P8 if that is the color space I need, right?

Yes. That's the easiest way.

Selur
7th July 2022, 18:21
Okay, thanks. :)

Selur
7th July 2022, 18:52
Using:
# Imports
import vapoursynth as vs
import os
import sys
# getting Vapoursynth core
core = vs.core
# Import scripts folder
scriptPath = 'i:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# Loading Plugins
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")
# Import scripts
import havsfunc
# source: 'G:\TestClips&Co\files\test.avi'
# current color space: YUV420P8, bit depth: 8, resolution: 640x352, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: progressive
# Loading source using FFMS2
clip = core.ffms2.Source(source="G:/TestClips&Co/files/test.avi",cachefile="E:/Temp/avi_6c441f37d9750b62d59f16ecdbd59393_853323747.ffindex",format=vs.YUV420P8,alpha=False)
# Setting color matrix to 470bg.
clip = core.std.SetFrameProps(clip, _Matrix=5)
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=5)
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=5)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
## Starting left=60, top=60, right=50, bottom=50
clip = core.resize.Bicubic(clip=clip, format=vs.YUV444P8, range_s="limited") # convert clip to 4:4:4 to allow uneven positions
clipVline = core.std.BlankClip(clip=clip, width=1, format=vs.RGB24, color=[50,205,5]) # set color of vertical line
clipHline = core.std.BlankClip(clip=clip, height=1,format=vs.RGB24, color=[50,205,5]) # set color of horizontal line
clipVline = core.resize.Bicubic(clip=clipVline, format=vs.YUV444P8, matrix_s="470bg", range_s="limited") # change color to that of clip
clipHline = core.resize.Bicubic(clip=clipHline, format=vs.YUV444P8, matrix_s="470bg", range_s="limited") # change color to that of clip
#overlay vertical lines
clip = havsfunc.Overlay(base=clip, overlay=clipVline, x=60)
clip = havsfunc.Overlay(base=clip, overlay=clipVline, x=clip.width-50)
clip = havsfunc.Overlay(base=clip, overlay=clipHline, y=60)
#overlay horizontal lines
clip = havsfunc.Overlay(base=clip, overlay=clipHline, y=clip.height-50)
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, range_s="limited")
## Finished

# set output frame rate to 25fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()
I basically get what I expected, but something seems to be amiss, since I see some pinkg lines
https://i.ibb.co/ChQh1PX/pink.png (https://ibb.co/f4H41DK)
that should not be there,...
https://i.ibb.co/CQSzxSC/pink-zoomed.png (https://ibb.co/RcJ9LJr)
any idea where I go wrong?
Did I do something wrong or this a bug in overlay or somewhere else? (it's not much of an issue for my use case here, but seem to be wrong)

Cu Selur

Ps.: In case it's helps, I got the source clip I used in my google drive (https://drive.google.com/file/d/1xchtRU6uZyLm9xJWh4HgNxDrSqC70zhl/view?usp=sharing).

Julek
7th July 2022, 20:02
Using:
any idea where I go wrong?
Did I do something wrong or this a bug in overlay or somewhere else? (it's not much of an issue for my use case here, but seem to be wrong)

Cu Selur

Ps.: In case it's helps, I got the source clip I used in my google drive (https://drive.google.com/file/d/1xchtRU6uZyLm9xJWh4HgNxDrSqC70zhl/view?usp=sharing).
It's just chroma subsampling effect.

MonoS
7th July 2022, 20:10
Did I do something wrong or this a bug in overlay or somewhere else? (it's not much of an issue for my use case here, but seem to be wrong)

Cu Selur

That's an artifact from doing chroma subsampling, 4:2:0 (YUV420Px) has a 1/4 resolution for chroma and using a bicubic kernel (which use some negative lobe IIRC) generate that purple line (if you invert your green to [155,50,250] you will in fact generate a faint green line), if you use a kernel without negative lobes such a bilinear one you can avoid that kind of artifact, but introducing a strong chroma contrast line like that i a subsampled pic will always introduce some artifact, leave in in 444 subsampling (or RGB) and you will avoid that.

Selur
8th July 2022, 17:22
Okay, thanks for clearing that. :)

lansing
20th July 2022, 03:16
I have a problem with the R59 installer. I have both Python 3.8 and 3.9 installed with 3.9 being the default. But the installer is only able to detect 3.8. I tested R57 and it is able to see both python versions.

Julek
20th July 2022, 03:57
I have a problem with the R59 installer. I have both Python 3.8 and 3.9 installed with 3.9 being the default. But the installer is only able to detect 3.8. I tested R57 and it is able to see both python versions.

Since R58 VS supports only 3.8 OR 3.10.
3.8 is still kept because it is the latest version available for windows 7.

More info: https://github.com/vapoursynth/vapoursynth/issues/858

lansing
20th July 2022, 17:59
Since R58 VS supports only 3.8 OR 3.10.
3.8 is still kept because it is the latest version available for windows 7.

More info: https://github.com/vapoursynth/vapoursynth/issues/858

The documentation should be updated, as it is still stating 3.9 to be the supported version.

http://www.vapoursynth.com/doc/installation.html#windows-installation

Julek
20th July 2022, 19:56
The documentation should be updated, as it is still stating 3.9 to be the supported version.

http://www.vapoursynth.com/doc/installation.html#windows-installation

Yes, the site usually takes longer to update, even though it is already updated on GitHub (https://github.com/vapoursynth/vapoursynth/blob/master/doc/installation.rst#prerequisites).

Myrsloik
3rd August 2022, 18:29
R60 RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R60-RC1)

r60:
fixed blankclip crashing when fpsnum or fpsden is 0 despite it being allowed
fixed invalid format ids sometimes being treated as api3 values when passed to resize
fixed error message frame generation in vfw
fixed writing beyond end out output buffer for audio in vfw
blankaudio now takes an array of channel constants since this better matches how most other functions work
fixed splitchannels crash on certain channel configurations (YomikoR)
added makefulldiff and mergefulldiff, these are versions of makediff and mergediff that don't clamp the difference to half range and instead use a higher precision diff clip
better error messages when filters get unsupported input formats or combinations thereof
freezeframes now accepts empty arrays and simply passes through the source clip
you can directly assign to frame-props
removed all deprecated (and replaced by better versions) functions in python: get_frame_async_raw, get_plugins, get_functions, list_functions, get_format, register_format
fixed convolution output for 9-15 bit material

Note that MakeFullDiff and MergeFullDiff are experimental functions that may be killed off if nobody does fun things with them. That's all.

Greenhorn
3rd August 2022, 23:02
What's the difference between Make/MergeDiff and Make/MergeFullDiff when using float format? Was that also clamped?

Myrsloik
4th August 2022, 11:58
What's the difference between Make/MergeDiff and Make/MergeFullDiff when using float format? Was that also clamped?

It's the same for float.

mastrboy
7th August 2022, 19:16
ColorYUV std.Lut/std.Expr Do the adjustment yourself
https://github.com/amichaelt/vapoursynth/blob/master/doc/avisynthcomp.rst

Honestly, this is just too complicated to figure out for me, is there any helper functions available for this?

I tried to understand the code here: https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/color.cpp

But can not figure out how the Lut/expression for off_v is built from those functions...

I'm just trying to do the avisynth equivalent to "coloryuv(off_v=0.5)"

Myrsloik
7th August 2022, 20:22
Honestly, this is just too complicated to figure out for me, is there any helper functions available for this?

I tried to understand the code here: https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/color.cpp

But can not figure out how the Lut/expression for off_v is built from those functions...

I'm just trying to do the avisynth equivalent to "coloryuv(off_v=0.5)"

Add .5 to the third plane of a float format?

Expr(clip, ["", "", "x 0.5 +"])

mastrboy
7th August 2022, 21:29
Add .5 to the third plane of a float format?

Expr(clip, ["", "", "x 0.5 +"])

Thanks, that works... I have a difficult time properly understanding lut/expr, is there any decent documentation freely available that is recommended for beginners that want to learn?

That only works for 8bit though, I guess ColorYUV scales input values internally... So what is the math to convert 8bit Expr to 16bit?

Edit: nevermind, found a helper function for scaling values between bitdepths: https://github.com/Irrational-Encoding-Wizardry/vsutil/blob/master/vsutil/info.py#L129

Selur
15th September 2022, 15:19
R60 is released. :)

fixed blankclip crashing when fpsnum or fpsden is 0 despite it being allowed
fixed invalid format ids sometimes being treated as api3 values when passed to resize
fixed error message frame generation in vfw
fixed writing beyond end out output buffer for audio in vfw
blankaudio now takes an array of channel constants since this better matches how most other functions work
fixed splitchannels crash on certain channel configurations (YomikoR)
added makefulldiff and mergefulldiff, these are versions of makediff and mergediff that don't clamp the difference to half range and instead use a higher precision diff clip
better error messages when filters get unsupported input formats or combinations thereof
freezeframes now accepts empty arrays and simply passes through the source clip
you can directly assign to frame-props
removed all deprecated (and replaced by better versions) functions in python: get_frame_async_raw, get_plugins, get_functions, list_functions, get_format, register_format
fixed convolution output for 9-15 bit material
source: https://github.com/vapoursynth/vapoursynth/releases

Thanks!

Cu Selur

Yomiko
18th September 2022, 11:16
Is there a way (with API4) to tell if a clip has "valid" variable format?

Myrsloik
18th September 2022, 12:26
Is there a way (with API4) to tell if a clip has "valid" variable format?

What do you mean by "valid"? If you get an input clip that's variable format it'll always be valid. If a filter returns a frame that doesn't fit the description things will error out.

Yomiko
18th September 2022, 15:09
I was thinking about the recently fixed resize issue, where a clip with "dynamic" format might be mistakenly made. Although previewers actually can handle such output nodes, I hope users can be well informed.

Yomiko
29th September 2022, 12:48
In the C headers of API 3, VideoFormat is provided as a pointer in VSVideoInfo, effectively preventing me from creating a var format clip in a filter. Since API 4 it has been changed in the C header, but in python it remains to be None when the clip format is variable. Do you have any plan to also change in python?

Myrsloik
1st October 2022, 18:29
In the C headers of API 3, VideoFormat is provided as a pointer in VSVideoInfo, effectively preventing me from creating a var format clip in a filter. Since API 4 it has been changed in the C header, but in python it remains to be None when the clip format is variable. Do you have any plan to also change in python?

Change it to what? I don't understand the question.

Txico
24th October 2022, 11:12
Hello there,
As with any new Ubuntu release, I compile VapouSynth and plug-in from scratch. That's a new compiler versions used so it might help (or not).
With a newly installed Ubuntu 22.10 and after compiling VapourSynth and plug-ins I get an error every time I try a vpy script:
Script evaluation failed:
Python exception: attempted relative import with no known parent package

Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 2819, in vapoursynth._vpy_evaluate
File "src/cython/vapoursynth.pyx", line 2820, in vapoursynth._vpy_evaluate
File "example.mp4.vpy", line 2, in <module>
import havsfunc as haf
File "/usr/local/lib/python3.10/site-packages/havsfunc.py", line 69, in <module>
import mvsfunc as mvf
File "/usr/local/lib/python3.10/site-packages/mvsfunc.py", line 59, in <module>
from ._metadata import __version__
ImportError: attempted relative import with no known parent package

I know, I know. It suck to be me but, can anyone at least point me in the correct direction?

Selur
24th October 2022, 14:26
Have you installed mvsfunc like mentioned over at https://github.com/HomeOfVapourSynthEvolution/mvsfunc or did you just copy the mvsfunc.py file?
If you did the latter, it would explain the issue. (since _metadata.py is missing which includes the __version__-variable)

Cu Selur

Txico
24th October 2022, 16:05
Have you installed mvsfunc like mentioned over at https://github.com/HomeOfVapourSynthEvolution/mvsfunc or did you just copy the mvsfunc.py file?
If you did the latter, it would explain the issue. (since _metadata.py is missing which includes the __version__-variable)

Cu Selur

I have uninstalled mvsfunc with pip3 uninstall mvsfunc and after that pip3 install git+https://github.com/HomeOfVapourSynthEvolution/mvsfunc as specified in the Git Hub page.
Perhaps there some reboot needed in between? Any cache that needs to be redone? Any other package that needs to be installed like this that I need to know?

Thank you for your quick answer Selur.
Txico

Txico
24th October 2022, 16:21
Hello again,

After you pointed me to the mvsfunc issue I have uninstalled it again and then searched for any other mvsfunc file in my filesystem, and guess what... I found one where there should be none.
After deleting it and looking for it again without results this time, installing mvsfunc using pip again gets everything working. Flabbergasted.

Thank you, Cu Selur. That solved the issue.

Txico

Selur
30th October 2022, 07:00
Can someone tell me how to translate:
clip.Mt_Convolution(Horizontal=" 1 1 1 ", vertical = " 1 ", u=1, v=1)
my guess atm. is 'clip.std.Convolution(matrix=[ 1 1 1 ], planes= [ 0 ])'
and
MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1) (no clue)
and
Mt_AddDiff(Blurred, ReconstructedMedian)
to Vapoursynth? (Diff, Blurred, ReconstructedMedian are vs.Videonode and THR is a string-representation of an int)

Thanks!

Cu Selur

Selur
31st October 2022, 08:32
Okay,
Avisynth: Mt_AddDiff(Blurred, ReconstructedMedian)
<>
Vapoursynth: core.std.MergeDiff(Blurred, ReconstructedMedian))

Avisynth:
MT_Luts(Diff, Diff, mode="med", pixels = " 0 0 1 0 -1 0 " , expr = " X Y - X Y - X Y - abs 1 + * X Y - abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + / - 128 +", u=1,v=1)
<>
Vapoursynth:
partial_expr = lambda M, N: f" x x[{M},{N}] - x x[{M},{N}] - x x[{M},{N}] - abs 1 + * x x[{M},{N}] - abs 1 + {THR} 1 >= {thr_s} 0.5 pow {THR} ? + / - 128 + "
medianDiff = core.akarin.Expr(diff, [partial_expr(0,0) + partial_expr(1,0) + partial_expr(-1,0) + "sort3 drop swap drop", ""])



=> But how to convert,
Avisynth
Mt_Convolution(Horizontal=" 1 1 0 0 1 0 0 1 1 ", vertical = " 1 ", u=1, v=1)
to Vapoursynth?

Cu Selur

Selur
31st October 2022, 10:30
got it,
clip.std.Convolution(matrix=[ 1, 1, 0, 0, 1, 0, 0, 1, 1 ], mode='v', planes=[0])
works. (the mode='v' was the main issue)
Uploaded it to: https://github.com/Selur/VapoursynthScriptsInHybrid/blob/master/fromDoom9.py

Cu Selur

Myrsloik
20th November 2022, 18:21
R61-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R61-RC1) is out. Bug fixes only.

Selur
20th November 2022, 19:22
Thanks :)

Myrsloik
29th November 2022, 19:52
Thanks :)

R61 released now. No changes from RC1.

Selur
29th November 2022, 20:01
Thanks again. :)

lansing
7th December 2022, 05:08
I'm testing out the VSGAN filter in vsedit2, how do I free the gpu ram usage after running it? vsapi->freeFrame() doesn't free it.

Selur
18th December 2022, 19:31
I get totally different decimated output when using:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
core = vs.core
# Loading Plugins
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/DeinterlaceFilter/TIVTC/libtivtc.dll")
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/vslsmashsource.dll")
# source: 'C:\Users\Selur\Desktop\sample_from_DVD.mkv'
# current color space: YUV420P8, bit depth: 8, resolution: 720x480, fps: 29.97, color matrix: 470bg, yuv luminance scale: limited, scanorder: telecine
# Loading C:\Users\Selur\Desktop\sample_from_DVD.mkv using LWLibavSource
clip = core.lsmas.LWLibavSource(source="C:/Users/Selur/Desktop/sample_from_DVD.mkv", format="YUV420P8", stream_index=0, cache=0, prefer_hw=0)
# Setting color matrix to 470bg.
clip = core.std.SetFrameProps(clip, _Matrix=5)
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=5)
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=5)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# making sure frame rate is set to 29.97
clip = core.std.AssumeFPS(clip=clip, fpsnum=30000, fpsden=1001)
clip = core.std.SetFrameProp(clip=clip, prop="_FieldBased", intval=0)
# cropping the video to 704x480
clip = core.std.CropRel(clip=clip, left=6, right=10, top=0, bottom=0)
# Deinterlacing using TIVTC
clip = core.tivtc.TFM(clip=clip, mode=4)
clip = core.tivtc.TDecimate(clip=clip)# new fps: 23.976
# make sure content is preceived as frame based
clip = core.std.SetFieldBased(clip, 0)
# adjusting output color from: YUV420P8 to YUV420P10 for x265Model
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P10, range_s="limited")
# set output frame rate to 23.976fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# Output
clip.set_output()
compared to:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
core = vs.core
# Loading Plugins
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/DeinterlaceFilter/TIVTC/libtivtc.dll")
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/SourceFilter/DGDecNV/DGDecodeNV.dll")
# source: 'C:\Users\Selur\Desktop\sample_from_DVD.mkv'
# current color space: YUV420P8, bit depth: 8, resolution: 720x480, fps: 29.97, color matrix: 470bg, yuv luminance scale: limited, scanorder: telecine
# Loading C:\Users\Selur\Desktop\sample_from_DVD.mkv using DGSource
clip = core.dgdecodenv.DGSource("G:/Temp/mkv_6971e61a600461af6ca6ccf15732fb4f_853323747.dgi",fieldop=2)
# Setting color matrix to 470bg.
clip = core.std.SetFrameProps(clip, _Matrix=5)
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=5)
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=5)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# making sure frame rate is set to 29.97
clip = core.std.AssumeFPS(clip=clip, fpsnum=30000, fpsden=1001)
clip = core.std.SetFrameProp(clip=clip, prop="_FieldBased", intval=0)
# cropping the video to 704x480
clip = core.std.CropRel(clip=clip, left=6, right=10, top=0, bottom=0)
# Deinterlacing using TIVTC
clip = core.tivtc.TFM(clip=clip, mode=4)
clip = core.tivtc.TDecimate(clip=clip)# new fps: 23.976
# make sure content is preceived as frame based
clip = core.std.SetFieldBased(clip, 0)
# adjusting output color from: YUV420P8 to YUV420P10 for x265Model
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P10, range_s="limited")
# set output frame rate to 23.976fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# Output
clip.set_output()
And the only difference between it is the source filter.
With dgdecodenv.DGSource I get wrong decimation hits. :(
In Avisynth I would use "clip = clip.PreRoll(Int(clip.FrameRate())" to handle this, but what to do in Vapoursynth?
I encountered this with the source from https://forum.videohelp.com/threads/407942-29-97-to-23-976-interlace-dilemma

Okay, scratch that, using PreRoll in Avisynth doesn't help either, only switching away from DGDecNV.
The question whether there is an alternative to PreRoll still remains.

Cu Selur

poisondeathray
19th December 2022, 04:38
And the only difference between it is the source filter.
With dgdecodenv.DGSource I get wrong decimation hits. :(


I get similar results between avs and vpy versions of simple TIVTC script using DGSource (frames match up, but not bit identical, I think libtivtc might be taking a slightly different field on some matches, but still resulting in the same frame visually)

Selur
20th December 2022, 21:35
Is there another SourceFilter than DGDecNV which has 'soft telecine' (ForceFilm) handling?

poisondeathray
20th December 2022, 21:49
Is there another SourceFilter than DGDecNV which has 'soft telecine' (ForceFilm) handling?

d2vsource ? RFF = False ? or DGIndex FF ?


Unlike DGDecode, it's up to the user to apply RFF flags as they see fit, by passing rff=True to the source function, or by passing rff=False and using core.d2v.ApplyRFF(clip, d2v=r'C:\path\to\my.d2v') after calling the source function. Unless you know your source is 100% FILM, you probably want to apply these. DGDecode's traditional "Force FILM" mode isn't really present in this plugin, but if your source or part of it is 100% FILM, which is the only time you should be Force FILMing anyway, you can simply set Force FILM in DGIndex, which will set the framerate properly in the D2V file, and then not apply RFF flags. It's also feasible to trim away any non-FILM frames and still Force FILM.


Maybe ffms2 ... but rffmode might not be present in the vapoursynth version of ffms2 (or maybe it's always mode=0 ?)

Selur
5th January 2023, 15:53
Issue was resolved over at: https://www.rationalqm.us/board/viewtopic.php?f=8&t=1220
It was my mistake, I misunderstood how fieldop in DGSource source worked.
Instead of fieldop=2, I should have used fieldop=0. :/
(so not a bug in DGDecNV, but in my mind :))

Cu Selur

_Al_
9th January 2023, 23:13
About _ColorRange prop,
I have to specify it this way: RANGE = {0:'limited', 1:'full'}, I checked Zimg and it has it the same way.
But manual has it backwards, http://www.vapoursynth.com/doc/apireference.html#reserved-frame-properties
Could it be fixed in that documentation?

Julek
10th January 2023, 01:18
About _ColorRange prop,
I have to specify it this way: RANGE = {0:'limited', 1:'full'}, I checked Zimg and it has it the same way.
But manual has it backwards, http://www.vapoursynth.com/doc/apireference.html#reserved-frame-properties
Could it be fixed in that documentation?


Frame prop and zimg arg are different things.
1 is limited in _ColorRange prop and full in zimg arg.

_Al_
10th January 2023, 19:28
I have to define range and matrix using strings, otherwise things are off:

print(vs.__api_version__)
clip = core.lsmas.LibavSMASHSource('YUV.mp4')
rgb1 = clip.resize.Bicubic(format=vs.RGB24, matrix_in_s='709', range_in_s='full')
rgb2 = clip.resize.Bicubic(format=vs.RGB24, matrix_in_s='709', range_in=0)
>>>VapourSynthAPIVersion(api_major=3, api_minor=6)
and rgb1 and rgb2 are not the same, is it an old bug? I do not have portable tkinter in portable API4 right now to quick check

Oh, I get it now, it is swapped, so if wanting to set 'limited' in props, we have to use:

API3:
clip = clip.std.SetFrameProp(prop='_ColorRange', intval=1)
API4:
clip = clip.std.SetFrameProps(_ColorRange=1)
but if wanting to specify limited range for YUV before conversion, we have to:
rgb = clip.resize.Bicubic(format=vs.RGB24, matrix_in_s='709', range_in=0)
Wow, I wonder how many headaches this caused, I certainly was confused for a long while ... :-)

Selur
15th January 2023, 08:55
Trying to port CQTGMC (https://forum.doom9.org/showthread.php?t=183823) to Vapoursynth, I started with:
def CQTGMC(clip: vs.VideoNode, Sharpness: float=0.25, thSAD1: int=192, thSAD2: int=320, thSAD3: int=128, thSAD4: int=320) -> vs.VideoNode:

flip = core.std.FlipHorizontal(clip)
flip = Padding(clip=clip,top=clip.width%64)
flip = Padding(clip=clip,right=clip.height%64)
padded = core.std.StackHorizontal([clip,flip])
# todo: optional use nnedi3CL
bobbed = core.znedi3.nnedi3(clip=padded, field=2)
denoised = core.rgvs.RemoveGrain(clip=bobbed,mode=12)
denoised = core.fmtc.resample(clip=denoised, kernel="gauss", w=denoised.width, h=denoised.height, scaleh=denoised.width+0.0001, interlaced=False, interlacedd=False)
denoised = core.resize.Bicubic(clip=denoised, format=bobbed.format, dither_type="error_diffusion") # adjust format after fmtc
denoised = core.std.Merge(clipa=denoised, clipb=bobbed,weight=0.25)

srchClip = denoised
csuper = core.mv.Super(clip=denoised);
bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32)
fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32)
Comp1 = core.mv.Compensate(denoised,csuper,bvec,thsad=thSAD2)
Comp2 = core.mv.Compensate(denoised,csuper,fvec,thsad=thSAD2)
denoised = core.std.Interleave([Comp1,denoised,Comp2])
csuper = core.vs.Super(clip=denoised)
bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32)
fvec = core.Analyse(csuper,isb=False,blksize=64,overlap=32)
Inter = core.mv.FlowInter(csuper,bvec,fvec,blend=False)
# global CQTGMC_A = Inter.SelectEvery(3,0)
# global CQTGMC_B = Inter.SelectEvery(3,1)
# srchClip
# ScriptClip("""
# P = YDifferenceFromPrevious()
# N = Trim(1,0).YDifferenceFromPrevious()
# N < P ? CQTGMC_A : CQTGMC_B
# """)
# super = MSuper()
# bVec1 = MAnalyse(super,isb=true,overlap=4,delta=1)
# fVec1 = MAnalyse(super,isb=false,overlap=4,delta=1)
# bobbed
# super = MSuper(levels=1)
# bComp1 = MCompensate(super,bVec1,thSAD=thSAD3)
# fComp1 = MCompensate(super,fVec1,thSAD=thSAD3)
# Interleave(\
# SeparateFields(bobbed).SelectEvery(4,0),\
# SeparateFields(fComp1).SelectEvery(4,1),\
# SeparateFields(bComp1).SelectEvery(4,2),\
# SeparateFields(bobbed).SelectEvery(4,3))
# Weave()
# # super = MSuper(levels=1)
# bComp1 = MCompensate(super, bVec1,thSAD=thSAD4)
# fComp1 = MCompensate(super, fVec1,thSAD=thSAD4)
# tMax = mt_logic(fComp1,"max",U=3,V=3).mt_logic(bComp1,"max",U=3,V=3)
# tMin = mt_logic(fComp1,"min",U=3,V=3).mt_logic(bComp1,"min",U=3,V=3)
# MDegrain1(super,bVec1,fVec1,thSAD=thSAD1)
# sharpen = mt_adddiff(mt_makediff(Removegrain(20),u=3,v=3),u=3,v=3)
# mt_clamp(sharpen,tMax,tMin,Sharpness,Sharpness,3,3,3)
# super = MSuper(levels=1)
# MDegrain1(super,bVec1,fVec1,thSAD=thSAD1)
# Crop(0,0,-(input.width()%64),-(input.height()%64))
# return last

# from havsfunc
def Padding(clip: vs.VideoNode, left: int = 0, right: int = 0, top: int = 0, bottom: int = 0) -> vs.VideoNode:
if not isinstance(clip, vs.VideoNode):
raise vs.Error('Padding: this is not a clip')

if left < 0 or right < 0 or top < 0 or bottom < 0:
raise vs.Error('Padding: border size to pad must not be negative')

width = clip.width + left + right
height = clip.height + top + bottom

return clip.resize.Point(width, height, src_left=-left, src_top=-top, src_width=width, src_height=height)

but now I'm stuck.
Can someone tell me how to convert this part:
global CQTGMC_A = Inter.SelectEvery(3,0)
global CQTGMC_B = Inter.SelectEvery(3,1)
srchClip
ScriptClip("""
P = YDifferenceFromPrevious()
N = Trim(1,0).YDifferenceFromPrevious()
N < P ? CQTGMC_A : CQTGMC_B
""")
to Vapoursynth?

Thanks!

Cu
Selur

kedautinh12
15th January 2023, 10:12
SelectEvery(3,0) -> std.SelectEvery(clip=clip, cycle=2, offsets=0)
SelectEvery(3,1) -> SelectEvery(clip=clip, cycle=2, offsets=1)
YDifferenceFromPrevious() -> core.std.PlaneStats(clip, clip[0] + clip)

Selur
15th January 2023, 10:33
Okay, but why:
SelectEvery(3,0) -> std.SelectEvery(clip=clip, cycle=2, offsets=0)
shouldn't cycle stay 3 ?

kedautinh12
15th January 2023, 10:45
Okay, but why:
SelectEvery(3,0) -> std.SelectEvery(clip=clip, cycle=2, offsets=0)
shouldn't cycle stay 3 ?

Lol, i'm forgot change that, sr

Selur
15th January 2023, 12:03
Okay. Thanks :)
Opened a separate thread for the porting. https://forum.doom9.org/showthread.php?p=1981140

Cu
Selur

~ VEGETA ~
30th January 2023, 22:47
I've been trying to use fvf insertsign to overlay a lagarith .avi with alpha on top of my video. however, it does not work.

how can i specify it right so that it takes the alpha channel properly?

I used the same files with avs and it worked... i think i am missing something related to telling vs about the alpha channel?

the logo appears but without being overlayed properly

_Al_
31st January 2023, 00:05
havsfunc could be used:
import havsfunc
clip=havsfunc.Overlay(clip1,clip2,mask=alpha)
https://github.com/HomeOfVapourSynthEvolution/havsfunc/blob/master/havsfunc.py#L5960

Julek
31st January 2023, 02:31
I've been trying to use fvf insertsign to overlay a lagarith .avi with alpha on top of my video. however, it does not work.

how can i specify it right so that it takes the alpha channel properly?

I used the same files with avs and it worked... i think i am missing something related to telling vs about the alpha channel?

the logo appears but without being overlayed properly

https://github.com/Irrational-Encoding-Wizardry/fvsfunc/pull/12

~ VEGETA ~
31st January 2023, 15:46
havsfunc could be used:
import havsfunc
clip=havsfunc.Overlay(clip1,clip2,mask=alpha)
https://github.com/HomeOfVapourSynthEvolution/havsfunc/blob/master/havsfunc.py#L5960

overlay succeeded but the result was bad, the alpha overlay is not good. it didn't get completely transparent as it should be.

also, it does not have options to specify ranges.

also:

video1= lvf.misc.overlay_sign(clip=video1,overlay=fixed_logo,frame_ranges=[8508,8655])

didn't work and put this: https://pastebin.com/GSZRYLqi

first it didn't accept 2 colorspaces as alpha clip in RGBA, so I did:

video1= lsmash...
fixed_logo = core.ffms2.Source(source=path..., alpha=True)
fixed_logo = core.resize.Bilinear(fixed_logo, format=vs.YUV420P8, matrix_s="709")
video1= lvf.misc.overlay_sign(clip=video1,overlay=fixed_logo,frame_ranges=[8508,8655])

but it still showed the error above.

On insertsign side, I still cannot use it even after modifying it with the mentioned commit manually in scripts folder.

_Al_
31st January 2023, 16:16
overlay succeeded but the result was bad, the alpha overlay is not good. it didn't get completely transparent as it should be.Make mask a grayscale clip with only values 0 or 255 (for 8bits). You can use Levels or Expr to make it from your logo.

~ VEGETA ~
31st January 2023, 16:34
Make mask a grayscale clip with only values 0 or 255 (for 8bits). You can use Levels or Expr to make it from your logo.

like converting to yuv then shuffleplanes first plane?

levels needs inputs and outputs 0-255, how to do your idea?

_Al_
31st January 2023, 17:14
I'd check alpha first, it needs to be 255 to have full transparency to see logo over clip, and zero values to see clip without any transition. In a previewer using color pickers. The borders would be some grayscale for smooth transitions. And it looks like mask has to be specifically used as a keyword, havsfunc.Overlay(clip, logo, mask=alpha)

oh those levels, ..., if alpha values do not reach 255, then using something like, for grayscale clip (plane does not have to be specified):
core.std.Levels(max_in=230, max_out=255) to get it to 255, that number 235 you test in previewer, could be a bit higher or lower

~ VEGETA ~
31st January 2023, 17:25
I'd check alpha first, it needs to be 255 to have full transparency to see logo over clip, and zero values to see clip without any transition. In a previewer using color pickers. The borders would be some grayscale for smooth transitions. And it looks like mask has to be specifically used as a keyword, havsfunc.Overlay(clip, logo, mask=alpha)


thanks but i managed to make insertsign work by just using the string of file location as input rather than ffms2.

~ VEGETA ~
7th February 2023, 11:13
I'd like to ask about better ways to sharpen anime rather than using regular sharpeners (like LSFmod). this is regardless of descale or not to descale.

I found AI or NN upscalers with nice results in terms of denoise, deblock, and sharpening but are they used on actual fansub encodes (modern anime)? I am only interested in making the encodes slightly more sharp (no halos) but not too sharp.

Doing one of these upscalers then SSIM downsample to 1080p... then doing maskedmerge using an edge mask to only get sharp edges from the upscaled clip. is this a good approach? I have Ryzen 7900X CPU, 3060TI GPU, 32G DDR5 5600MHz PC so I think it can handle high work load.

what do you think?

Selur
7th February 2023, 20:18
You might also want to look into vsgan models from https://upscale.wiki/wiki/Model_Database, most of them are trained on animes.

~ VEGETA ~
7th February 2023, 21:20
You might also want to look into vsgan models from https://upscale.wiki/wiki/Model_Database, most of them are trained on animes.

i will dig into this soon, to learn the syntax of using them in VS.

however, what do you think about the approach I explained above?

also, besides vsgan, what other similar tools which are used in encoding anime real releases not just for testing.

I feel like such tools can do some damage to backgrounds or some unwanted features like denoise and deblock. thus i pointed out the masks.

Selur
8th February 2023, 17:47
Yes, your approach might work too.
Anime release groups usually use tons of masking and rarely use a filter as is. :) (+ they often filter per scene)
You might also want to check out the 'Enhance Everything!' discord channel (https://discord.com/invite/cpAUpDK) and the 'Irrational Encoding Wizardry' (https://discord.gg/qxTxVJGtst) channel.

i will dig into this soon, to learn the syntax of using them in VS.
Here's a simple example:
# resizing using VSGAN
from vsgan import ESRGAN
vsgan = ESRGAN(clip=clip,device="cuda")
model = "I:/Hybrid/64bit/vsgan_models/1x_BroadcastToStudioLite_485k.pth"
vsgan.load(model)
vsgan.apply()
clip = vsgan.clip
the VSGAN (https://github.com/rlaphoenix/VSGAN)-site also has some good documentation.

Cu Selur

~ VEGETA ~
8th February 2023, 18:37
Yes, your approach might work too.
Anime release groups usually use tons of masking and rarely use a filter as is. :) (+ they often filter per scene)
You might also want to check out the 'Enhance Everything!' discord channel (https://discord.com/invite/cpAUpDK) and the 'Irrational Encoding Wizardry' (https://discord.gg/qxTxVJGtst) channel.


Here's a simple example:
# resizing using VSGAN
from vsgan import ESRGAN
vsgan = ESRGAN(clip=clip,device="cuda")
model = "I:/Hybrid/64bit/vsgan_models/1x_BroadcastToStudioLite_485k.pth"
vsgan.load(model)
vsgan.apply()
clip = vsgan.clip
the VSGAN (https://github.com/rlaphoenix/VSGAN)-site also has some good documentation.

Cu Selur

thanks for this my friend.

what other tools exist for this task rather than vsgan\esrgan? how can we compare their results and see which is best for anime?

I know these stuff do many enhancements but i am only interested in getting lines sharper, the line art itself not background or texture.

so I don't want to do these silly "4k upscaled anime" releases or even do very sharp everything... i think you got what i mean.

I know fansub releases do many masking, me included. However, i didn't see a vs script for a release which has stuff like vsgan in it which made me wonder why it is not used.

Selur
8th February 2023, 19:19
afaik. most release groups use normal filters or script collections like lvsfunc&co and no magic tools.
Why it's not used is probably easy:
a. requires up-to-date hardware, especially if you want to encode tons of content. Encoding with on multiple machines to speed up the processing is hard if each of them require a 3000+ NVIDIA GPU to not totally suck and are not really fast even then.
b. assuming you don't need to do restoration, you can archive the stuff most ai filtering does through other filters when you spend enough effort.
c. you don't have much control aside from different types of masking to control what the ai stuff does (assuming you didn't train the models yourself)
d. folks filtering anime often want to keep artifacts which they perceive as details of the source. (there is also the discussion of which release of anime xy has the colors 'right', often it has to be the one that came out earlier,...)
=> to get to the bottom of things, you probably will need to go to the discord channels of the groups and ask them and some might actually reply honestly and not simply say 'ai bad => you bad' *gig*

Cu Selur

~ VEGETA ~
8th February 2023, 19:32
I get this error: https://pastebin.com/Kj8QBQDi

I tried doing many tools but could not get the release to be as sharp as another good one. talked to them but didn't give many details how they achieved it. thus I thought of this method.

I have Ryzen 7900X and 3060Ti so I guess my PC qualifies.

I get it that AI upscale is bad for anime releases but i don't plan to use it that way.. I only want the good sharp lines. ALL other stuff are exactly as they were.

Selur
8th February 2023, 19:46
btw. can someone port EZDenoise to Vapoursynth?
Original:
function EZdenoise(clip Input, int "thSAD", int "thSADC", int "TR", int "BLKSize", int "Overlap", int "Pel", bool "Chroma", bool "out16")
{
thSAD = default(thSAD, 150)
thSADC = default(thSADC, thSAD)
TR = default(TR, 3)
BLKSize = default(BLKSize, 8)
Overlap = default(Overlap, 4)
Pel = default(Pel, 1)
Chroma = default(Chroma, false)
out16 = default(out16, false)

Super = Input.MSuper(Pel=Pel, Chroma=Chroma)
Multi_Vector = Super.MAnalyse(Multi=true, Delta=TR, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma)

Input.MDegrainN(Super, Multi_Vector, TR, thSAD=thSAD, thSAD2=int(float(thSAD*0.9)), thSADC=thSADC, thSADC2=int(float(thSADC*0.9)), out16=out16)
}


Cu Selur

Selur
8th February 2023, 19:52
@~ VEGETA ~: No clue. First time I see that error. :/
I can send you a link to my current 'torch-AddOn' for Hybrid which basically is a folder with a portable Vapoutsynth, which also includes vsgan (and tons of other stuff).

Cu Selur

~ VEGETA ~
28th February 2023, 07:56
Hello

I am trying to use this https://github.com/YomikoR/GetFnative with base dimensions of 1920x1080p and fractional height of 847.047 (or so, don't remember now).

However, I'd like to use SSIM downsampler instead of regular spline36 if possible. I tried so but could not because it always produces a shifted image.

I tried different manual values but couldn't do it properly as the original code example shown in linked page.

any tips?

DTL
6th March 2023, 22:44
btw. can someone port EZDenoise to Vapoursynth?
Cu Selur

The magic is inside mvtools - not in this simple mvtools usage function. First is good to port to vapoursynth all new features of todays mvtools (post 2.7.45 builds to the end of 2022 or with some new planned features to 2023 like finally fixing quality issue of https://github.com/pinterf/mvtools/issues/59 for non-4:4:4 sources).

At first VS may still not support simple MDegrainN from old 2.7.45 era. As in latest commit in 2023 https://github.com/dubhater/vapoursynth-mvtools/commit/b5d58cb7ca1cfe27bdcb30fbcff67254580b7ab9 it is only start to support fixed-tr to 6. It is lightyears behind latest end of 2022 MDegrainN already having 'spatial' multi-pass blending modes and going to go into 'temporal' multi-pass blending as a next step.

Also the most useful features like several interpolated overlap modes (at the MDegrain stage - running MAnalyse in max speed non-overlapped or using hardware accelerator of MVs from MPEG encoder chip) including new quality/performance balanced mode of 'diagonal' overlap having only 2x number of blocks and giving close to blksize/2 4x overlap mode quality in old mvtools overlap design. Also runtime sub-sample shifting allowing to save host RAM traffic and expensive onboard CPU caches trashing with pre-calculated subsample refined planes. The required for correct pel=4 UV processing in 4:2:0 granularity is pel/8. So if designed in old way via MSuper it will bug memory subsystem even more.

Also running MVs analysis in 'large' tr of 10 and more opens better possibility to perform intermediate linear or non-linear MVs grading in time axis after MAnalyse and before MDegrain (MVLPF current implemented feature of MDegrainN). Using too few tr for 1..6 gives too low timed samples of MVs to make good FIR convolution linear LPF.

Selur
7th March 2023, 13:44
Okay, so in conclusion with https://github.com/dubhater/vapoursynth-mvtools EZDenoise can't be ported atm. .
Sad news, but I will have to live with it.
Thanks.

mastrboy
8th April 2023, 16:28
Myrsloik, can we get a weight parameter for std.MaskedMerge like there is for std.Merge?

Myrsloik
8th April 2023, 22:21
Myrsloik, can we get a weight parameter for std.MaskedMerge like there is for std.Merge?

What? Tbe weight is already in the mask

Selur
9th April 2023, 15:48
He, probably, wants a weight since he isn't using a grayscale, but a binary mask,...

mastrboy
9th April 2023, 20:42
What? Tbe weight is already in the mask

Might just be some lack of knowledge on my understanding of how masks works...

Consider the following mask/merge:
edge_mask = core.tedgemask.TEdgeMask(video, link=1, threshold=5.0).std.Maximum(threshold=128)
edge_merged = core.std.MaskedMerge(clipa=video, clipb=filtered, mask=edge_mask, planes=[0, 1, 2], first_plane=True)
output = core.std.Merge(clipa=video, clipb=edge_merged, weight=[0.45])

If I can control the weight in the mask itself, how would that code snippet look if I wanted to replace the "core.std.Merge(clipa=video, clipb=edge_merged, weight=[0.45]" part by reducing the mask weight 45%?

Selur
15th April 2023, 13:39
@masterboy: TEdgeMask by default creates a binary mask, but if you set threshold to 0 you can set scale,... doesn't that do what you are aiming for?

Selur
21st April 2023, 17:52
How can I get the current scan type (tff/bff/progressice) of the clip I'm using, so that I can use it in a script? (I don't want to display it.)

_Al_
22nd April 2023, 20:05
from the props, not sure if I understand

n = 0
try:
field_based = clip.get_frame(n).props.get('_FieldBased', None)
except (vs.Error, IndexError) as e:
raise ValueError(f'requesting prop for a frame: {n} failed, {e}')
print(field_based)

Selur
23rd April 2023, 07:25
Strange, I would have bet I tried that and it didn't work.
Worked now, must have made a typo.
Thanks.

Cu Selur

Selur
25th April 2023, 19:54
Cdblend and srestore both use std.Cache(make_linear=True) which turned in to a noop function in API4 (are there more noop functions? is there some documentation about this?)
Is there a way to get the same effect as "std.Cache(make_linear=True)" with API4 Vapoursynth that would allow to fix those two scripts which now return worse results than before?

Myrsloik
25th April 2023, 21:44
Cdblend and srestore both use std.Cache(make_linear=True) which turned in to a noop function in API4 (are there more noop functions? is there some documentation about this?)
Is there a way to get the same effect as "std.Cache(make_linear=True)" with API4 Vapoursynth that would allow to fix those two scripts which now return worse results than before?

http://www.vapoursynth.com/doc/functions/video/setvideocache.html
Basically this is the closest you get. You can't set the linear mode from scripts but if you need it something else is wrong. Which source filter are you using?

Create an issue where you link the specific versions of the functions you're using, full script and source filter and I'll check it. Should be fairly quick to figure out where things go wrong.

Selur
29th April 2023, 06:31
Trying to assess how broken of a state current filter scripts are, are there more such 'dummy' functions in API4?

Myrsloik
29th April 2023, 10:07
Trying to assess how broken of a state current filter scripts are, are there more such 'dummy' functions in API4?

Nope. Also it only worked by accident previously. The world is threaded now.

Selur
29th April 2023, 10:15
Nope. Also it only worked by accident previously.
Okay, good to know, I just need to throw away all functions containing 'std.Cache(make_linear=True)'. :)
Thanks for the info.

Since I have little hope that anyone will write a sRestore filter, I will have to rethink some of my workflows and probably add an intermediate step to filter with Avisynth.

Cu Selur

Selur
3rd May 2023, 19:08
I can't find any deblenders in Vapoursynth that work with current Vapoursynth R61/62, does anyone know one?

Myrsloik
14th June 2023, 21:14
R63 has been released. Minor bug fixes mostly. This is also the last release I'm going to make official 32 bit binaries for. Nobody downloads them anyway except by accident.

ChaosKing
15th June 2023, 08:51
R63 has been released. Minor bug fixes mostly. This is also the last release I'm going to make official 32 bit binaries for. Nobody downloads them anyway except by accident.

Half of the compiled plugins on Github are only available as 64 bit anyway.

Myrsloik
21st June 2023, 19:25
Speaking of deprecating things. How many win7 users remain nowadays? I'm curious if there actually is a real userbase still remaining.

Emulgator
24th June 2023, 15:01
2x Win10, 2x Win7, 5x WinXP here, 7 single and 1 dual-boot Win7+WinXP.
Paid, abandoned, but working and irreplaceable softwares made that necessary.

Win7 should be minimum supported, or does that restrict coding seriously?
The default compiler switches that intentionally introduce incompatibilities are well known by now and can be avoided most of the time.
Well, I won't need VapourSynth to work under WinXP, I can use a Win10 machine for that.

As long as there is one Swiss Army Knife that can run under more than the latest forced-updating-and then-bluescreening (again) OS...

AviSynth works under these 3 Win generations, and the just recently introduced XP-compatible Audio preview makes it fun again to edit, even restore and encode on WinXP machines.

LigH
25th June 2023, 11:01
A major difference between Windows 7 and 10 is in hardware access and security aspects; most software focused on just calculations should be quite compatible, even when using more modern SIMD instructions Windows 7 did not yet prepare well for, with some caution.

Myrsloik
25th June 2023, 17:08
A major difference between Windows 7 and 10 is in hardware access and security aspects; most software focused on just calculations should be quite compatible, even when using more modern SIMD instructions Windows 7 did not yet prepare well for, with some caution.

I have no reason to remove win7 support yet as it doesn't require additional work to maintain. The only problem is that I can't be bothered to test win7 (or 8.1 for that matter) anymore and therefore check now and then if anyone still actually use it and it receives testing. This is simply a check I do now and then to see if any actual (and possibly bug reporting) users remain.

One of the previous posts also mention xp support in avs+ still but that's intermittent due to a very low volume of testing, even the visual studio runtime breaks now and then because Microsoft doesn't care that much either. Once win7 reaches the same level of neglect or the latest visual studio drops support I'll also drop it in VapourSynth. Obviously.

If someone wants to encode on winxp level hardware with VapourSynth it's still very possible. Just install linux, it'll run much faster due to vastly superior memory management too.

Selur
26th June 2023, 14:31
I'm using R63 with this script:
# Imports
import vapoursynth as vs
import os
import sys
# getting Vapoursynth core
core = vs.core
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# Loading Plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/libmvtools.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/FrameFilter/Interframe/svpflow2_vs64.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/FrameFilter/Interframe/svpflow1_vs64.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/vslsmashsource.dll")
# Import scripts
import havsfunc
import filldrops
# source: 'C:\Users\Selur\Desktop\002 - Copia.mkv'
# current color space: YUV420P8, bit depth: 8, resolution: 1920x1080, fps: 23.976, color matrix: 709, yuv luminance scale: limited, scanorder: progressive
# Loading C:\Users\Selur\Desktop\002 - Copia.mkv using LWLibavSource
clip = core.lsmas.LWLibavSource(source="C:/Users/Selur/Desktop/002 - Copia.mkv", format="YUV420P8", stream_index=0, cache=0, prefer_hw=0)
# making sure frame rate is set to 23.976
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
clip = core.std.SetFrameProp(clip=clip, prop="_FieldBased", intval=0) # progressive
clip = filldrops.InsertSingle(clip=clip,method="mv")
#clip = filldrops.InsertSingle(clip=clip,method="svp_gpu")
#clip = filldrops.InsertSingle(clip=clip,method="svp")

# Output
clip.set_output()
and filldrops.py:
import vapoursynth as vs
core = vs.core

def fillWithMVTools(clip):
super = core.mv.Super(clip, pel=2)
vfe = core.mv.Analyse(super, truemotion=True, isb=False, delta=1)
vbe = core.mv.Analyse(super, truemotion=True, isb=True, delta=1)
return core.mv.FlowInter(clip, super, mvbw=vbe, mvfw=vfe, time=50)

def fillWithRIFE(clip, firstframe=None, rifeModel=1, rifeTTA=False, rifeUHD=False, rifeThresh=0.15):
clip1 = core.std.AssumeFPS(clip, fpsnum=1, fpsden=1)
start = core.std.Trim(clip1, first=firstframe-1, length=1)
end = core.std.Trim(clip1, first=firstframe+1, length=1)
startend = start + end
if clip.format != vs.RGBS:
r = core.resize.Point(startend, format=vs.RGBS, matrix_in_s="709")
if rifeThresh != 0:
r = core.misc.SCDetect(clip=r,threshold=rifeThresh)
r = core.rife.RIFE(r, model=rifeModel, tta=rifeTTA,uhd=rifeUHD)
if clip.format != vs.RGBS:
r = core.resize.Point(r, format=clip.format, matrix_s="709")

r = core.std.Trim(r, first=1, last=1)
r = core.std.AssumeFPS(r, fpsnum=1, fpsden=1)
a = core.std.Trim(clip1, first=0, last=firstframe-1)
b = core.std.Trim(clip1, first=firstframe+1)
join = a + r + b
return core.std.AssumeFPS(join, src=clip)


def fillWithGMFSSUnion(clip, firstframe=None, gmfssModel=0, gmfssThresh=0.15):
from vsgmfss_fortuna import gmfss_fortuna
clip1 = core.std.AssumeFPS(clip, fpsnum=1, fpsden=1)
start = core.std.Trim(clip1, first=firstframe-1, length=1)
end = core.std.Trim(clip1, first=firstframe+1, length=1)
startend = start + end
if clip.format != vs.RGBH:
r = core.resize.Point(startend, format=vs.RGBH, matrix_in_s="709")
r = gmfss_fortuna(r, model=gmfssModel, sc_threshold=gmfssThresh)
if clip.format != vs.RGBH:
r = core.resize.Point(r, format=clip.format, matrix_s="709")
r = core.std.Trim(r, first=1, last=1)
r = core.std.AssumeFPS(r, fpsnum=1, fpsden=1)
a = core.std.Trim(clip1, first=0, last=firstframe-1)
b = core.std.Trim(clip1, first=firstframe+1)
join = a + r + b
return core.std.AssumeFPS(join, src=clip)



def fillWithSVP(clip, firstframe=None, gpu=False):
clip1 = core.std.AssumeFPS(clip, fpsnum=1, fpsden=1)
start = core.std.Trim(clip1, first=firstframe-1, length=1)
end = core.std.Trim(clip1, first=firstframe+1, length=1)
startend = start + end

if gpu:
super = core.svp1.Super(startend,"{gpu:1}")
else:
super = core.svp1.Super(startend,"{gpu:0}")
vectors= core.svp1.Analyse(super["clip"],super["data"],startend,"{}")
r = core.svp2.SmoothFps(startend,super["clip"],super["data"],vectors["clip"],vectors["data"],"{}")

r = core.std.Trim(r, first=1, last=1)
r = core.std.AssumeFPS(r, fpsnum=1, fpsden=1)
a = core.std.Trim(clip1, first=0, last=firstframe-1)
b = core.std.Trim(clip1, first=firstframe+1)
join = a + r + b
return core.std.AssumeFPS(join, src=clip)

def FillSingleDrops(clip, thresh=0.3, method="mv", rifeModel=0, rifeTTA=False, rifeUHD=False, rifeThresh=0.15, gmfssModel=0, gmfssThresh=0.15, debug=False):
core = vs.core
if not isinstance(clip, vs.VideoNode):
raise ValueError('This is not a clip')

def selectFunc(n, f):
if f.props['PlaneStatsDiff'] > thresh or n == 0:
if debug:
return core.text.Text(clip=clip,text="Org, diff: "+str(f.props['PlaneStatsDiff']),alignment=8)
return clip
else:
if method == "mv":
filldrops=fillWithMVTools(clip)
elif method == "svp":
filldrops=fillWithSVP(clip,n)
elif method == "svp_gpu":
filldrops=fillWithSVP(clip,n,gpu=True)
elif method == "rife":
filldrops = fillWithRIFE(clip,n,rifeModel,rifeTTA,rifeUHD,rifeThresh)
elif method == "gmfssfortuna":
filldrops = fillWithGMFSSUnion(clip,n,gmfssModel,gmfssThresh)
else:
raise vs.Error('FillDrops: Unknown method '+method)
if debug:
return core.text.Text(clip=filldrops,text=method+", diff: "+str(f.props['PlaneStatsDiff']),alignment=8)
return filldrops

diffclip = core.std.PlaneStats(clip, clip[0] + clip)
fixed = core.std.FrameEval(clip, selectFunc, prop_src=diffclip)
return fixed


def InsertSingle(clip, afterEveryX=2, method="mv", rifeModel=0, rifeTTA=False, rifeUHD=False, rifeThresh=0.15, gmfssModel=0, gmfssThresh=0.15, debug=False):
core = vs.core
if not isinstance(clip, vs.VideoNode):
raise ValueError('This is not a clip')

def selectFunc(n):
if n == 0 or n%afterEveryX != 0:
return clip
else:
if method == "mv":
insertFrame=fillWithMVTools(clip)
elif method == "svp":
insertFrame=fillWithSVP(clip,n)
elif method == "svp_gpu":
insertFrame=fillWithSVP(clip,n,gpu=True)
elif method == "rife":
insertFrame = fillWithRIFE(clip,n,rifeModel,rifeTTA,rifeUHD,rifeThresh)
elif method == "gmfssfortuna":
insertFrame = fillWithGMFSSUnion(clip,n,gmfssModel,gmfssThresh)
else:
raise vs.Error('InsertSingle: Unknown method '+method)
return insertFrame.text.Text("Interpolated")

return core.std.FrameEval(clip, selectFunc)

When using method="mv", I get:
Explicitly instantiated a Cache. This is no longer possible and the original clip has been passed through instead.
I think this is the effect of:
added a warning every time the deprecated cache filter is instantiated and ignored source: https://github.com/vapoursynth/vapoursynth/releases/tag/R63
and somehow this is triggered by:

def fillWithMVTools(clip):
super = core.mv.Super(clip, pel=2)
vfe = core.mv.Analyse(super, truemotion=True, isb=False, delta=1)
vbe = core.mv.Analyse(super, truemotion=True, isb=True, delta=1)
return core.mv.FlowInter(clip, super, mvbw=vbe, mvfw=vfe, time=50)



=> How can I fix this or does this require a mvtools update/fix/change to be really compatible with Vapoursynth R63?

Cu Selur

Myrsloik
26th June 2023, 21:36
It's just a warning. The actual behavior hasn't changed from previous versions. I've added it to flush out the last pieces of not fixed code.

In this case I guess mvtools was never updated to api4. I'll have to add it to my todo list...

Selur
27th June 2023, 03:58
Okay, thanks for the info.

Patman
30th August 2023, 07:24
Can anyone help with the following issue?
http://forum.doom9.org/showthread.php?p=1991055#post1991055

For me the changes made by DJATOM are correct.

Myrsloik
18th September 2023, 21:31
R64-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R64-RC1)

Just your average bug fix release to keep up with new things. Will be released in a week or so if nobody finds horrible regressions.

Changes:
added json output of video frame properties to vspipe
fixed clearMap function, previously it would forget to properly clear the error state in maps which could cause crashes in frameeval and other filters
32 bit binaries are no longer provided for windows
updated zimg to fix issues on zen4 cpus
added support for cython 3.x

Myrsloik
27th September 2023, 20:14
R64 has been released.
r64:
fixed compilation on osx where the default standard library doesn't have a full implementation of std::from_chars
added -- as an alternate to . to indicate no output in vspipe since shells have a tendency to expand .
added json output of video frame properties to vspipe
fixed clearMap function, previously it would forget to properly clear the error state in maps which could cause crashes in frameeval and other filters
32 bit binaries are no longer provided for windows
updated zimg to fix issues on zen4 cpus
added support for cython 3.x

Selur
30th September 2023, 13:01
Should R64 simply work as replacement, or should one expect new warnings, errors, not working scripts?

Ci Selur

lansing
2nd October 2023, 08:07
I'm having problem with vapoursynth not releasing all memory in vsedit2 after I closed the file. I had a script opening a dvd video, when I preview it, it took about 530 MB of ram. When I closed the file, there were still 200 MB of ram remained in use. I tried with Virtualdub2 and the same thing happened.

Myrsloik
3rd October 2023, 14:28
I'm having problem with vapoursynth not releasing all memory in vsedit2 after I closed the file. I had a script opening a dvd video, when I preview it, it took about 530 MB of ram. When I closed the file, there were still 200 MB of ram remained in use. I tried with Virtualdub2 and the same thing happened.

New problem in R64 or also in previous versions? Does it happen with trivial scripts too?

lansing
3rd October 2023, 19:05
New problem in R64 or also in previous versions? Does it happen with trivial scripts too?

False alarm. After a few reinstalls of the older version for testing, my problem went away.

Dan64
7th October 2023, 09:47
Hello _Al_,

I found your post very interesting :

Just as a curiosity sort of, you could pipe ffmpeg cmd line in vapoursynth directly in your script.
It is not ideal, it is one way only, no searching etc.
vs script is always python script so all python woo-doo is available in vs script as well. Not sure how many folks realize that.
import vapoursynth as vs
from vapoursynth import core
import subprocess
import ctypes

ffmpeg = r'C:\tools\ffmpeg.exe'
source_path=r'C:\videos\video.mp4'
clip = core.lsmas.LibavSMASHSource(source_path) #this clip is not not needed, just to get width and height
clip = core.std.BlankClip(clip)

w = clip.width
h = clip.height
Ysize = w * h
UVsize = w * h//4
frame_len = w * h * 3 // 2 #YUV420

command = [ ffmpeg, '-i', source_path,'-vcodec', 'rawvideo', '-pix_fmt', 'yuv420p', '-f', 'rawvideo', '-']
pipe = subprocess.Popen(command, stdout = subprocess.PIPE, bufsize=frame_len)

def load_frame(n,f):
try:
vs_frame = f.copy()
for i, size in enumerate([Ysize, UVsize, UVsize]):
ctypes.memmove(vs_frame.get_write_ptr(i), pipe.stdout.read(size), size)
pipe.stdout.flush()
except Exception as e:
raise ValueError(repr(e))
return vs_frame

try:
clip = core.std.ModifyFrame(clip, clip, load_frame)
except ValueError as e:
pipe.terminate()
print(e)

clip.set_output()

The video used for test has resolution: 720x300
The script used for the test is the following:


import vapoursynth as vs
from vapoursynth import core
import subprocess
import ctypes

ffmpeg = r'E:\VideoTest\TestSubs\ffmpeg.exe'
source_path=r'E:\VideoTest\TestSubs\TestVideo.mp4'
# Loading Plugins
core.std.LoadPlugin(path="E:/VideoTest/TestSubs/BestSource.dll") #from https://forum.doom9.org/showthread.php?t=184255
#current color space: YUV420P10, bit depth: 10
#resolution: 720x300, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: progressive
clip = core.bs.VideoSource(source="E:/VideoTest/TestSubs/TestVideo.mp4") #this clip is not not needed, just to get width and height
# Setting detected color matrix (470bg).
clip = core.std.SetFrameProps(clip, _Matrix=5)
# Setting color transfer info (470bg), when it is not set
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=5)
# Setting color primaries info (BT.709), when it is not set
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
clip = core.std.SetFrameProp(clip=clip, prop="_FieldBased", intval=0) # progressive
# set output frame rate to 25fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# adjusting output color from: YUV420P8 to YUV420P10
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P10, range_s="limited")

#clip = core.std.BlankClip(clip)

w = clip.width
h = clip.height
Ysize = w * h
UVsize = w * h//4
frame_len = w * h * 3 // 2 #YUV420

command = [ ffmpeg, '-i', source_path,'-vcodec', 'rawvideo', '-pix_fmt', 'yuv420p', '-f', 'rawvideo', '-']
pipe = subprocess.Popen(command, stdout = subprocess.PIPE, bufsize=frame_len)

def load_frame(n,f):
try:
vs_frame = f.copy()
for i, size in enumerate([Ysize, UVsize, UVsize]):
ctypes.memmove(vs_frame.get_write_ptr(i), pipe.stdout.read(size), size)
pipe.stdout.flush()
except Exception as e:
raise ValueError(repr(e))
return vs_frame

try:
clip = core.std.ModifyFrame(clip, clip, load_frame)
except ValueError as e:
pipe.terminate()
print(e)

clip.set_output()


But I was unable to replicate your script. You can find a script and the video used for the test at the following link: https://filebin.net/4t266xvy94ylt74o/TestVideo_Preview.zip

I commented the creation of BlankClip in order to understand better what is happen. Moreover I added the conversion from: YUV420P8 to YUV420P10 (without I don't see nothing).

In this image you can see the result

https://i.ibb.co/XDcsYCR/preview-ffmpeg-Test-Video-v1-frame.jpg

As you can see is not copied all the frame in output, but only a small part (see square 1) which is duplicated (see square 2). The rectangle 3 represent the part of the original script that is not overridden by ctypes.memmove(). More interesting it is possible to see that the square 3 is not in sync with square 1 & 2.
I was unable to get you script working, could you help me ?

Thanks,
Dan

Dan64
7th October 2023, 17:44
It seems that there is a problem in reading properly the raw video.

I tried the following commands

ffmpeg.exe -i "TestVideo.mp4" -vcodec rawvideo -pix_fmt yuv420p -f rawvideo - | vlc.exe --demux=rawvideo --rawvid-fps=25 --rawvid-width=700 --rawvid-height=300 --rawvid-chroma=I420 -
ffmpeg.exe -i "TestVideo.mp4" -vcodec rawvideo -pix_fmt yuv420p -f rawvideo - | ffplay.exe -f rawvideo -pixel_format yuv420p -video_size 720x300 -i -


and both ffplay and vlc are unable to properly play the video (with ffplay being better than vlc).

It seems to me strange that a problem like this has never been already discovered. So what's wrong ?

_Al_
8th October 2023, 02:22
Quick tested it with another 1920x1080 mp4, 4:2:0 video I have here and it worked, so ffmpeg's rawvideo loaded it ok, but your mp4 file did not work.

I suspect that height mod might be a problem, it is 4 for 300, maybe mod 8 is needed for ffmpeg. Would resizing it to 304 help for example? Source video, not in vapoursynth.

Dan64
8th October 2023, 09:16
Quick tested it with another 1920x1080 mp4, 4:2:0 video I have here and it worked, so ffmpeg's rawvideo loaded it ok, but your mp4 file did not work.

I suspect that height mod might be a problem, it is 4 for 300, maybe mod 8 is needed for ffmpeg. Would resizing it to 304 help for example? Source video, not in vapoursynth.

I found the problem regarding the "ffplay". It was due to the fact that i was running the scripts in PowerShell, by running them in the command dos (cmd.exe) all the version of ffpay tested are woking. Even without resize mod 8.

But the problem on Vapoursynth side still remain...

Dan64
8th October 2023, 10:09
I was finally able to get the following script working

import vapoursynth as vs
from vapoursynth import core
import subprocess
import ctypes

ffmpeg = r'E:\VideoTest\TestSubs\ffmpeg.exe'
source_path=r'E:\VideoTest\TestSubs\TestVideo.mp4'
# Loading Plugins
core.std.LoadPlugin(path="E:/VideoTest/TestSubs/BestSource.dll") #from https://forum.doom9.org/showthread.php?t=184255
#current color space: YUV420P8, bit depth: 8
#resolution: 1280x536, fps: 25, color matrix: 470bg, yuv luminance scale: limited, scanorder: progressive

#this clip is not not needed, just to get width and height
clip = core.bs.VideoSource(source=source_path)
# Setting detected color matrix (470bg).
clip = core.std.SetFrameProps(clip, _Matrix=5)
# Setting color transfer info (470bg), when it is not set
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=5)
# Setting color primaries info (BT.709), when it is not set
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=1)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
clip = core.std.SetFrameProp(clip=clip, prop="_FieldBased", intval=0) # progressive
# set output frame rate to 25fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)

clip = core.std.BlankClip(clip)

w = clip.width
h = clip.height
Ysize = w * h
Usize = w * h//4
Vsize = w * h//4
frame_len = Ysize + Usize + Vsize #YUV420

command = [ ffmpeg, '-i', source_path,'-vcodec', 'rawvideo', '-pix_fmt', 'yuv420p', '-f', 'rawvideo', '-']

pipe = subprocess.Popen(command, stdout = subprocess.PIPE, bufsize=frame_len)

def load_frame_from_pipe(n,f):
vs_frame = f.copy()
try:
for plane, size in enumerate([Ysize, Usize, Vsize]):
ctypes.memmove(vs_frame.get_write_ptr(plane), pipe.stdout.read(size), size)
pipe.stdout.flush()
except Exception as e:
raise ValueError(repr(e))
return vs_frame

try:
clip = core.std.ModifyFrame(clip, clip, load_frame_from_pipe)
except ValueError as e:
pipe.terminate()
print(e)

clip.set_output()


It seems that the problem was related to mod 8 and to conversion to YUV420P810. :)

P.S.
The video used for test is available here: https://filebin.net/trb7yof9h0g335e0

Myrsloik
9th October 2023, 17:42
R65-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R65-RC1)
frame properties in python are now return as str type instead of bytes when hinted as utf8 printable
fixed how unprintable data is returned from plugin functions in python, previously it would leak a ctypes pointer with no length instead of returning a bytes object
fixed a bug in the avx2 maskedmerge float premultiplied code path that would switch the two input clips
reverted the from_chars code a bit more to make no locale affects float parsing
fixed the sar adjustment for real this time
Test and verify the fixes. Report if there are any scripts that actually break due to the change in how frame properties are returned.

_Al_
9th October 2023, 20:18
It seems that the problem was related to mod 8 and to conversion to YUV420P10.
ffmpeg and vapoursynth have to have same video, it cannot be changed in vapoursynth, because bytes that ffmpeg reads go right into vapoursynth clip planes
, it should be the same.
If source video is 10bit though, then byte sizes would be different, 10bit uses 2bytes per value:
Ysize = w * h * 2
Usize = w * h//2
Vsize = w * h//2
YUVsize = Ysize + Usize + Vsize

Selur
22nd October 2023, 09:34
Has anyone an updated SMDegrain for Vapoursynth? (latest Vapoursynth version I know of is v3.1.2d, current Avisynth version is v4.5.0d afaik.)

Jukus
7th November 2023, 16:01
Upgraded my ArchLinux and now I have a similar error, how to fix it?
Failed to evaluate the script:
Python exception: Expr: failed to convert '129.0' to float, not the whole token could be converted

Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 3121, in vapoursynth._vpy_evaluate
File "src/cython/vapoursynth.pyx", line 3122, in vapoursynth._vpy_evaluate
File "/tmp/1/script.vpy", line 30, in
#v = haf.QTGMC(v, Preset='Very Slow', Sharpness=0.4, FPSDivisor=1, TFF=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/havsfunc/havsfunc.py", line 2561, in QTGMC
repair0 = QTGMC_KeepOnlyBobShimmerFixes(binomial0, bobbed, Rep0, RepChroma and ChromaMotion)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/havsfunc/havsfunc.py", line 3181, in QTGMC_KeepOnlyBobShimmerFixes
)

File "src/cython/vapoursynth.pyx", line 2857, in vapoursynth.Function.__call__
vapoursynth.Error: Expr: failed to convert '129.0' to float, not the whole token could be converted

Myrsloik
7th November 2023, 17:36
Upgraded my ArchLinux and now I have a similar error, how to fix it?
Failed to evaluate the script:
Python exception: Expr: failed to convert '129.0' to float, not the whole token could be converted

Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 3121, in vapoursynth._vpy_evaluate
File "src/cython/vapoursynth.pyx", line 3122, in vapoursynth._vpy_evaluate
File "/tmp/1/script.vpy", line 30, in
#v = haf.QTGMC(v, Preset='Very Slow', Sharpness=0.4, FPSDivisor=1, TFF=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/havsfunc/havsfunc.py", line 2561, in QTGMC
repair0 = QTGMC_KeepOnlyBobShimmerFixes(binomial0, bobbed, Rep0, RepChroma and ChromaMotion)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/havsfunc/havsfunc.py", line 3181, in QTGMC_KeepOnlyBobShimmerFixes
)

File "src/cython/vapoursynth.pyx", line 2857, in vapoursynth.Function.__call__
vapoursynth.Error: Expr: failed to convert '129.0' to float, not the whole token could be converted

Will we ever know the version? The suspense IS KILLING ME!

Jukus
7th November 2023, 18:47
R64-1

Myrsloik
7th November 2023, 19:01
R64-1

It was probably fixed in R65

Selur
11th November 2023, 19:56
Is there a port of ffmpegs colortemperature (https://www.ffmpeg.org/ffmpeg-all.html#toc-colortemperature) for Vapoursynth or an alternative filter or way to do this?

poisondeathray
12th November 2023, 01:38
Is there a port of ffmpegs colortemperature (https://www.ffmpeg.org/ffmpeg-all.html#toc-colortemperature) for Vapoursynth or an alternative filter or way to do this?


a crappy workaround to use any ffmpeg processing in vpy script is ffmpeg pipe into vsrawsource

Selur
13th November 2023, 18:04
I found this (https://stackoverflow.com/questions/11884544/setting-color-temperature-for-a-given-image-like-in-photoshop), which uses OpenCV and using:
import cv2
import muvsfunc_numpy as mufnp
import numpy as np
from PIL import Image

kelvin_table = {
1000: (255,56,0),
1500: (255,109,0),
2000: (255,137,18),
2500: (255,161,72),
3000: (255,180,107),
3500: (255,196,137),
4000: (255,209,163),
4500: (255,219,186),
5000: (255,228,206),
5500: (255,236,224),
6000: (255,243,239),
6500: (255,249,253),
7000: (245,243,255),
7500: (235,238,255),
8000: (227,233,255),
8500: (220,229,255),
9000: (214,225,255),
9500: (208,222,255),
10000: (204,219,255)}

def numpy2pil(np_array: np.ndarray) -> Image:
"""
Convert an HxWx3 numpy array into an RGB Image
"""

assert_msg = 'Input shall be a HxWx3 ndarray'
assert isinstance(np_array, np.ndarray), assert_msg
assert len(np_array.shape) == 3, assert_msg
assert np_array.shape[2] == 3, assert_msg

img = Image.fromarray(np_array, 'RGB')
return img

def pil2numpy(img: Image = None) -> np.ndarray:
"""
Convert an HxW pixels RGB Image into an HxWx3 numpy ndarray
"""
np_array = np.asarray(img)
return np_array

def convert_temp(image, temp):
r, g, b = kelvin_table[temp]
matrix = ( r / 255.0, 0.0, 0.0, 0.0,
0.0, g / 255.0, 0.0, 0.0,
0.0, 0.0, b / 255.0, 0.0 )
img = numpy2pil(image)
return pil2numpy(img.convert('RGB', matrix))

range = "full"
if core.text.FrameProps(clip,'_ColorRange'):
range = "limited"

clip = core.resize.Bicubic(clip=clip, format=vs.RGB24, range_s=range)
clip = mufnp.numpy_process(clip, convert_temp, temp=6500, input_per_plane=False, output_per_plane=False)
it seems to work, but the problem with that is it requires OpenCV and I'm not really sure how 'good' this is.
Instead of using the kelvin_table one could probably use something similar to: https://academo.org/demos/colour-temperature-relationship/ which uses:
/**
* http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
* */
function KToRGB(Temperature){

Temperature = Temperature / 100;

if (Temperature <= 66){
Red = 255;
} else {
Red = Temperature - 60;
Red = 329.698727466 * Math.pow(Red, -0.1332047592);
if (Red < 0){
Red = 0;
}
if (Red > 255){
Red = 255;
}
}

if (Temperature <= 66){
Green = Temperature;
Green = 99.4708025861 * Math.log(Green) - 161.1195681661;
if (Green < 0 ) {
Green = 0;
}
if (Green > 255) {
Green = 255;
}
} else {
Green = Temperature - 60;
Green = 288.1221695283 * Math.pow(Green, -0.0755148492);
if (Green < 0 ) {
Green = 0;
}
if (Green > 255) {
Green = 255;
}
}

if (Temperature >= 66){
Blue = 255;
} else {
if (Temperature <= 19){
Blue = 0;
} else {
Blue = Temperature - 10;
Blue = 138.5177312231 * Math.log(Blue) - 305.0447927307;
if (Blue < 0){
Blue = 0;
}
if (Blue > 255){
Blue = 255;
}
}
}

rgb = new Array(Math.round(Red),Math.round(Green),Math.round(Blue));
return rgb;

}

Maybe a c++ port of this would be a cool thing,..

cubicibo
13th November 2023, 20:57
Anythig numpy can go turbo with Numba njit. And in this case even benefit of parallelism thanks to independant processing of the planes. However, muvsfunc would have to be rewritten extensively to only access Python and numpy primitives in its core muvsfunc_numpy module.

Is the sample you posted incomplete? There are no acccess to cv2 and the import is unused.

Selur
13th November 2023, 21:05
You are right, I don't need openCV, I first had it in there for some image handling, but I noticed that just using numpy was faster.
Okay, so the next question is: is numpy really needed?

cubicibo
13th November 2023, 21:31
You can drop Pillow, not numpy.


def convert_temp(frame: np.ndarray, temp: int) -> np.ndarray:
return frame*(np.array(kelvin_table[temp], dtype=float)/255.0)


You may additionally want to np.round() before casting back to np.uint8.

WolframRhodium
14th November 2023, 00:09
colortemperature can be implemented using only vanilla std.Expr + std.ShufflePlanes.

_Al_
14th November 2023, 03:14
You can drop Pillow, not numpy.


def convert_temp(frame: np.ndarray, temp: int) -> np.ndarray:
return frame*(np.array(kelvin_table[temp], dtype=float)/255.0)


You may additionally want to np.round() before casting back to np.uint8.
I tried this and it seams to work, more testing maybe needed. Basics are used, just numpy and vapoursynth, no muvsfunc_numpy , no PIL:

import vapoursynth as vs
from vapoursynth import core
import numpy as np

class Temperature:
KELVIN_TABLE = {
1000: (255,56,0),
1500: (255,109,0),
2000: (255,137,18),
2500: (255,161,72),
3000: (255,180,107),
3500: (255,196,137),
4000: (255,209,163),
4500: (255,219,186),
5000: (255,228,206),
5500: (255,236,224),
6000: (255,243,239),
6500: (255,249,253),
7000: (245,243,255),
7500: (235,238,255),
8000: (227,233,255),
8500: (220,229,255),
9000: (214,225,255),
9500: (208,222,255),
10000: (204,219,255)}

def __init__(self, temp):
self.rgb = self.KELVIN_TABLE[temp]

def change(self, n, f):
f_out = f.copy()
for p in range(3):
npArray = np.asarray(f[p])
npArray = npArray*(np.array(self.rgb[p], dtype=float)/255.0)
np.copyto(np.asarray(f_out[p]), npArray[:,:])
return f_out

clip = core.lsmas.LibavSMASHSource('video.mp4')
clip = clip.resize.Point(format=vs.RGBS, matrix_in_s = '709')
clip = core.std.ModifyFrame(clip, clip, Temperature(4000).change)
clip = clip.resize.Point(format=vs.YUV420P8, matrix_s = '709')
clip.set_output(0)

_Al_
14th November 2023, 05:29
colortemperature can be implemented using only vanilla std.Expr + std.ShufflePlanes.
this seams to perform about the same speed as example above:

import vapoursynth as vs
from vapoursynth import core

KELVIN_TABLE = {
1000: (255,56,0),
1500: (255,109,0),
2000: (255,137,18),
2500: (255,161,72),
3000: (255,180,107),
3500: (255,196,137),
4000: (255,209,163),
4500: (255,219,186),
5000: (255,228,206),
5500: (255,236,224),
6000: (255,243,239),
6500: (255,249,253),
7000: (245,243,255),
7500: (235,238,255),
8000: (227,233,255),
8500: (220,229,255),
9000: (214,225,255),
9500: (208,222,255),
10000: (204,219,255)}

def change_temperature(clip, temp):
rgb = KELVIN_TABLE[temp]
rgb = [value/255.0 for value in rgb]
planes = core.std.SplitPlanes(clip)
planes = [core.std.Expr(plane, expr=[f"x {rgb[i]} *"]) for i, plane in enumerate(planes)]
return core.std.ShufflePlanes(clips=planes, planes=[0], colorfamily=vs.RGB)

clip = core.lsmas.LibavSMASHSource('video.mp4')
clip = clip.resize.Point(format=vs.RGBS, matrix_in_s = '709')
clip = change_temperature(clip, 4000)
clip = clip.resize.Point(format=vs.YUV420P8, matrix_s = '709')
clip.set_output(0)

_Al_
14th November 2023, 06:06
to not use KELVIN_TABLE, and using Selur's code in python to use any temperature, not just selected from a table:

import vapoursynth as vs
from vapoursynth import core
import math

def get_rgb(temp):
temp = temp / 100
if temp <= 66:
r = 255
else:
r = temp - 60
r = 329.698727466 * math.pow(r, -0.1332047592)
r = min(max(0, r), 255)

if temp <= 66:
g = temp
g = 99.4708025861 * math.log(g) - 161.1195681661
else:
g = temp - 60
g = 288.1221695283 * math.pow(g, -0.0755148492)
g = min(max(0, g), 255)

if temp >= 66:
b = 255
else:
if temp <= 19:
b = 0
else:
b = temp - 10
b = 138.5177312231 * math.log(b) - 305.0447927307
b = min(max(0, b), 255)

return round(r), round(g), round(b)

def change_temperature(clip, temp):
rgb = get_rgb(temp)
r, g, b = [value/255.0 for value in rgb]
return core.std.Expr([clip], expr=[f"x {r} *", f"x {g} *", f"x {b} *"])

clip = core.lsmas.LibavSMASHSource('video.mp4')
clip = clip.resize.Point(format=vs.RGBS, matrix_in_s = '709')
clip = change_temperature(clip, 4345)
clip = clip.resize.Point(format=vs.YUV420P8, matrix_s = '709')
clip.set_output(0)
Expr seams to perform faster than working with numpy arrays.

Selur
14th November 2023, 06:46
Nice, thanks.

rgr
23rd November 2023, 10:56
Vapoursynth needs a specific version of Python (3.11)? I have 3.13 and it doesn't want to install.

cubicibo
23rd November 2023, 11:06
You need 3.11.
Why would you even use Python 3.13? It is in an early alpha and the Python fundation strongly advise to not use it [for production].

Selur
19th December 2023, 23:00
Are there color constants that can be used with AddBorders?
'float[] color=<black>' seems to suggest they are, if there are, is there a list somewhere?

Myrsloik
20th December 2023, 09:16
Are there color constants that can be used with AddBorders?
'float[] color=<black>' seems to suggest they are, if there are, is there a list somewhere?

No, it's just a simpler way than trying to express black in all different formats and bitdepths.

I've chosen to directly pass through values in all functions unlike avisynth which usually takes 8 bit RGB values and converts.

Selur
20th December 2023, 09:17
Thanks for clearing that up. :)

Cu Selur

Adub
4th March 2024, 21:27
I had a few plugin development questions I wanted to pose to the community, and I figured I'd just post here instead of opening a new thread (although I'm happy to start one).

My questions:
1. When it comes to parameter handling based on bit-depth, what's the preferred behavior? For example, if a parameter normally ranges from 0-255 for 8-bit content, should plugins default to autoscaling parameters based on the input clip's bit depth, or should they not scale the parameter value and let the user handle it? A third option would be to make the scaling behavior configurable, with something like a boolean "scale_param" parameter that would let a user toggle autoscaling behavior if they want to be extra precise.
2. What open source licenses are preferred by this community? I see a broad mix with plugins, where some don't specify a license, some use MIT, and Vapoursynth itself uses LGPL (I believe). So I was wondering if there was a preferred standard license.
3. Are there any preferences for "skinny" vs "fat" plugins? In other words, creating a new plugin for every filter, or creating one plugin that houses a number of (at least semi-related) filters?

For reference, I'm experimenting with a new plugin that I'm writing in my free time, which currently consists of various smoothing/denoising related functions (things like averages, medians, etc). I'm kind of leaning towards making it "fat" by bundling a bunch of these filters into the same code base (think of having something like TemporalMedian, TemporalSoften2, and FluxSmooth all offered by the same code base).

Myrsloik
4th March 2024, 21:42
I had a few plugin development questions I wanted to pose to the community, and I figured I'd just post here instead of opening a new thread (although I'm happy to start one).

My questions:
1. When it comes to parameter handling based on bit-depth, what's the preferred behavior? For example, if a parameter normally ranges from 0-255 for 8-bit content, should plugins default to autoscaling parameters based on the input clip's bit depth, or should they not scale the parameter value and let the user handle it? A third option would be to make the scaling behavior configurable, with something like a boolean "scale_param" parameter that would let a user toggle autoscaling behavior if they want to be extra precise.
2. What open source licenses are preferred by this community? I see a broad mix with plugins, where some don't specify a license, some use MIT, and Vapoursynth itself uses LGPL (I believe). So I was wondering if there was a preferred standard license.
3. Are there any preferences for "skinny" vs "fat" plugins? In other words, creating a new plugin for every filter, or creating one plugin that houses a number of (at least semi-related) filters?

For reference, I'm experimenting with a new plugin that I'm writing in my free time, which currently consists of various smoothing/denoising related functions (things like averages, medians, etc). I'm kind of leaning towards making it "fat" by bundling a bunch of these filters into the same code base (think of having something like TemporalMedian, TemporalSoften2, and FluxSmooth all offered by the same code base).

1. Unscaled if there's actually some kind of direct relation to the pixel values.

2. MIT or GPL for plugins. If you use AGPL I will mock you for being special.

3. Not really.

efschu
6th March 2024, 15:36
Hello,

I'm modifying my jellyfin right now and replaced the ffmpeg binary with a script that calls vspipe together with ffmpeg. So I'm upscaling my content with realesr and interpolate it with RIFE in realtime on the server and watch the improved content on my clients.

This works fine for local files on server. But I also want to do this for live TV stream. But I did not figure out how to use a stream with vapoursynth. As I understood neither ffms2 nor l-smash nor bestsource support a stream as input.

Then I tried a workaround, to first save the stream in segments to disk, and then call vapoursynth script with a loop over all temporary stream files, but the loop didnt wait the files to finish one by one, instead the loop started to process all files at once (which resulted in out of gpu memory and forsure in not sequencial raw output frames) and crashed.

Sooo ladys and gents, do you have an idea how I could process live TV stream with vapoursynth? Or how I could process segmential files one by one with vapoursynth directly?

LigH
6th March 2024, 15:46
Hi.

I believe in your case, a custom build of ffmpeg or mpv with VPY filter support might be suitable, instead of frameserving.

efschu
7th March 2024, 12:10
Do you mean running it with ffmpeg -f vapoursynth - i script.vpy

But how would that help me with source dont have to be a "finished" file?

This is my script right now:
from vsrife import RIFE
from pathlib import Path
import vapoursynth as vs
import sys
import os

core = vs.core
core.num_threads = 14

core.std.LoadPlugin(path='/usr/lib/x86_64-linux-gnu/libffms2.so')
core.std.LoadPlugin(path="/mnt/hts/libs/libvstrt.so")

sys.path.append("/home/efeu/Downloads/VSGAN-tensorrt-docker/")
from src.rife_trt import rife_trt

clip = core.ffms2.Source(source='/tmp/tmpvideo', cache=False)

clip = core.resize.Bicubic(clip, width=640, height=480, format=vs.RGBS, matrix_in_s='709') # RGBS means fp32, RGBH means fp16

clip = core.trt.Model(clip, engine_path="/workspace/realesr-general-wdn-x4v3_opset16_640_480.engine", num_streams=4, device_id=0)

clip = core.resize.Bicubic(clip, width=1280, height=960, format=vs.RGBS, matrix_in_s='709') # RGBS means fp32, RGBH means fp16

clip = rife_trt(clip, multi = 2, scale = 1.0, device_id = 1, num_streams=4, engine_path="rife46_ensembleFalse_op18_clamp_1280x960_P40.engine")

clip = core.resize.Bicubic(clip, format=vs.YUV420P8, matrix_s='709')
clip.set_output()

Btw, do you have an idea why vspipe sometimes only runs on one core, then I abort command and try it again, then it runs fine over "all cores"? (it mostly only runs on one core)

https://private-user-images.githubusercontent.com/51944948/310850632-b796b5ee-121e-4809-a092-489a1d4bad0c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MDk4MDk5MTgsIm5iZiI6MTcwOTgwOTYxOCwicGF0aCI6Ii81MTk0NDk0OC8zMTA4NTA2MzItYjc5NmI1ZWUtMTIxZS00ODA5LWEwOTItNDg5YTFkNGJhZDBjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDAzMDclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwMzA3VDExMDY1OFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWU4YzZlMWI3MjhhOTY5NWFlMGE3MTZmYTM1YTAwZjUzZmZmOGExZGUxYmViYzdhM2Y1YWE5ZDE0OWI2MmUzNGMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.VqtksnGAXUAEj5iS6lNNd-d1GVa4MPq5A5vYQ1WQpqM

https://private-user-images.githubusercontent.com/51944948/310850985-d90cbb46-3354-4ea5-90ba-9d5718607694.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MDk4MDk5MTgsIm5iZiI6MTcwOTgwOTYxOCwicGF0aCI6Ii81MTk0NDk0OC8zMTA4NTA5ODUtZDkwY2JiNDYtMzM1NC00ZWE1LTkwYmEtOWQ1NzE4NjA3Njk0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDAzMDclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwMzA3VDExMDY1OFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTMxOTI2ODZhZjdiNzM5NDljOWIwYTA4M2UyNzMxNjgyODFhZWFjYjE3MmU3ZWViNWU4OTJhMjE2ZmQyZWU1MzEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.DKGnVjGmzxnZkOA6LXZhHfvS7P2-Q9z_GEtCKg4AxCw

Myrsloik
8th March 2024, 23:03
R66 (https://github.com/vapoursynth/vapoursynth/releases/tag/R66) is finally out. REQUIRES PYTHON 3.12!

See this blog post for an easier to read summary (https://www.vapoursynth.com/2024/03/r66-r65-installation-scripts-and-many-small-improvements/).

Selur
9th March 2024, 09:00
Thanks!

Cu Selur
Ps.: Argh, there are no TensorRT Python bindings for 3.12 from the looks of it, so no R66 for me atm. (tensorrt-8.6.1-cp311-none-win_amd64.whl is the latest currently :()

PPs.: seems like R66 portable is broken: https://github.com/vapoursynth/vapoursynth/issues/1033 -> turns out the install instructions have changed und you need now to also install the right wheel file matching your Python version.

LigH
9th March 2024, 13:24
hydra3333 reported a few issues regarding the portability support and installation in M-AB-S (https://github.com/m-ab-s/media-autobuild_suite/issues/2583#issuecomment-1986585894), to be tested...

amayra
10th March 2024, 13:23
are you going to drop support for CPU without AVX2 like intel ivy bridge architecture (i have i7 3770)

i think there way to optimize VapourSynth for new CPU extensions when it detect without breaking support for old one right ?

LigH
10th March 2024, 13:33
AVX2 should not be a minimum requirement, but one of several optimization paths. VapourSynth, as a Python extension, could also run on non-intel CPUs, where a required SSE/AVX support would make no sense but comparable SIMD instruction sets are available instead...

Myrsloik
10th March 2024, 16:48
are you going to drop support for CPU without AVX2 like intel ivy bridge architecture (i have i7 3770)

i think there way to optimize VapourSynth for new CPU extensions when it detect without breaking support for old one right ?

Not planned. I do however think it's pointless to write optimized code paths for anything less than AVX2 for new code.

Things that definitely will be dropped at some point:

API3 compatibility - in a year or so, everything of value has been converted or will be soon
Windows 7 support - probably as a result of Python 3.8 becoming too old, not enough users actually testing it or MS relegating it to a separate compiler option with a long list of quirks much like windows XP support


Also a big part of the reason for requiring SSE2 was feature parity with x64 builds. Lots of instruction support checks that could be skipped and compiling with SSE2 instructions also produces a bit faster code.

amayra
10th March 2024, 19:27
i always hate it when developers forced minimum requirement by not optimized application instead they use compiler flags like ("-march=cpu-type", CFLAGS, CCFLAGS and CXXFLAGS )

i fully understand and agreed with dropping old OS that not even modern web browser support

any CPU that don't support SSE2 i don't think can do anything with VS or any other applications

Myrsloik
13th March 2024, 12:31
The portable install script and portable zip have now been sneakily updated to fix several annoying issues related to plugin and script paths. Windows 7 support also added, however you'll need to install powershell 5.0 or later to actually run it since the bundled version on win7 is ancient.

_Al_
13th March 2024, 19:59
issues related to plugin and script paths
Loading vapoursynth clip from any path to portable vapoursynth could be done via loading script text using importlib module, not using scripts path.
If python loading script utility is in portable directory (or as an app), current path is an utility directory (portable directory), so dlls are loaded from portable directory. VSPipeloads that script (from portable directory) ok.

Is it related to that?
But vapoursynth installed dll's are preferred if vapoursynth is installed, dll's from Program Files/VapourSynth or AppData/Roaming/VapourSynth directory (Selur brought it up couple of times).



import importlib
vs.clear_outputs()
spec = importlib.util.spec_from_loader('vs_script_text', loader=None)
my_script_module = importlib.util.module_from_spec(spec)
exec(script_text, my_script_module.__dict__)
clip = vs.get_output(index)[0]
#or: clip = my_script_module.clip

Selur
13th March 2024, 20:11
Selur brought it up couple of times
Yeah, still hoping that we will one day get a way to disable autoloading inside a script.

Selur
27th April 2024, 07:14
How can one validate the frame properties?
I want to check that '_Transfer', '_Matrix', 'Primaries', '_ColorRange', '_FieldBased' are set to valid values.
Are the enums of valid values for these properties accessible in a script, so I can compare against them?

Cu Selur

_Al_
28th April 2024, 23:31
besides manually provide dictionaries or lists (as in the other thread) , vapoursynths Enums could be used:
vs.MatrixCoefficients
vs.TransferCharacteristics
vs.ColorPrimaries
vs.ColorRange
vs.FieldBased

using MatrixCoefficients Enum for example getting names and values:
print(vs.MatrixCoefficients.__members__)
getting values only:
print(vs.MatrixCoefficients.__members__.values())

so for matrix, checking if value is valid might be:

clip = vs.core.std.BlankClip()
frame = clip.get_frame(0)
value = frame.props.get('_Matrix', None)
if value in [None, 2, 3] or value not in vs.MatrixCoefficients.__members__.values():
clip = clip.std.SetFrameProps(_Matrix=1) # defaulting
frame = clip.get_frame(0)
print(frame.props)

<vapoursynth.FrameProps {'_DurationNum': 1, '_DurationDen': 24, '_Matrix': 1}>
>>>

Selur
29th April 2024, 04:14
@_AI_: Thanks! That's what I was looking for. :)

Cu Selur

Selur
2nd May 2024, 15:31
Does anyone have an alternative TemporalDegrain2 for Vapoursynth?
(the one in G41Fun.py (https://github.com/Selur/VapoursynthScriptsInHybrid/blob/d6fe1c881046f2678f592129f02eb38f85a0c54b/G41Fun.py#L2143)) crashes with extraSharp=True and I can't figure out why)
Update:
=> fixed it; problem was in CTMF

Cu Selur

Adub
3rd May 2024, 19:17
There's also a version in VSDenoise: https://github.com/Jaded-Encoding-Thaumaturgy/vs-denoise/blob/master/vsdenoise/funcs.py#L193

Selur
3rd May 2024, 19:24
Nice! Thanks for the info! :)
(sadly: vs-denoise does not seem to work with Vapoursynth R65 portable, https://github.com/Jaded-Encoding-Thaumaturgy/vs-denoise/issues/121; works with R66)

Adub
3rd May 2024, 19:24
@Myrsloik - plugin development question for you

Is it possible for a plugin to deterministically calculate max memory usage in Vapoursynth? For example, if I have a plugin that I know is going to work on N number of frames (say 3, prev + current + next), then can I use some aspect of the VS API to calculate the upper bound of memory usage?

It might even as simple as saying a plugin needs to process N frames, where each frame requires Y amount of data per frame and multiply that by the Z cores returned from the VS API?

I ask, because I'm considering the potential of allocating all required memory in one fell swoop (say at plugin Create) and then passing that pointer in the plugin data to GetFrame, using that as a pool, and then freeing that memory in plugin Free. Basically, I'm trying to minimize as many calls to malloc as possible.

Myrsloik
3rd May 2024, 19:32
@Myrsloik - plugin development question for you

Is it possible for a plugin to deterministically calculate max memory usage in Vapoursynth? For example, if I have a plugin that I know is going to work on N number of frames (say 3, prev + current + next), then can I use some aspect of the VS API to calculate the upper bound of memory usage?

It might even as simple as saying a plugin needs to process N frames, where each frame requires Y amount of data per frame and multiply that by the Z cores returned from the VS API?

I ask, because I'm considering the potential of allocating all required memory in one fell swoop (say at plugin Create) and then passing that pointer in the plugin data to GetFrame, using that as a pool, and then freeing that memory in plugin Free. Basically, I'm trying to minimize as many calls to malloc as possible.

Technically the upper bound would be the number of threads times the buffer space you need. But usually you don't even get remotely close to that due to threads spending time in other places. If you do it, WHICH YOU ABSOLUTELY SHOULDN'T, you'd be better off simply making new allocations when your filter local pool doesn't have an available set of buffers.

What you should do:
For small allocations (up to a few kb) are handled very well by new/delete/malloc/free and the process heap is your pool.

For larger allocation (like frame sizes) you can simply create a new frame (gray format for single plane). The overhead is very low and it's fast. The memory is now in the frame buffer pool and can be shared between everything. Including other instances of your own plugin.

Work with the system, don't reimplement it.

Selur
4th May 2024, 15:09
@Mysrloik: I encountered that vsedits memory usage increases on each reload (when having biforst.dll in my scripts). Can you chime in whether this (https://github.com/YomikoR/VapourSynth-Editor/issues/55) is likely an issue of vedit, bifrost or Vapoursynth itself?
Thanks!

Myrsloik
4th May 2024, 18:51
R67 is out. A pure bugfix release that should make everyone snooze.

wubikens
13th May 2024, 15:52
Dumb question, but how do you load a clip? I'm trying to use BasicVSR++, and I followed the instructions here: https://github.com/HolyWu/vs-basicvsrpp?tab=readme-ov-file and got this running in a PyCharm project. All of the dependencies were correctly installed, but I'm having a hell of a time figuring out how to just load a clip with VapourSynth. I'm currently using R65 with Python 3.10. I see in the documentation that VapourSynth recommends using BestSource?

https://www.vapoursynth.com/doc/gettingstarted.html#example-script

It all starts with a .vpy script. Here’s a sample script to be inspired by, it assumes that BestSource is installed and auto-loaded.

from vapoursynth import core # Get an instance of the core
clip = core.bs.VideoSource(source='filename.mkv') # Load a video track in mkv file
clip = core.std.FlipHorizontal(clip) # Flip the video clip in the horizontal direction
clip.set_output() # Set the video clip to be accessible for output


But I can't seem to pip install it. If somebody could direct me at the very least to some instructions I could follow, I'd really appreciate it. Thanks!

Selur
19th May 2024, 16:29
@all:
R68 was released:
fixed portable base path detection, was broken in r67
fixed is_inspectable, was broken in r67
reverted widestring print changes in vspipe from r67
source: https://github.com/vapoursynth/vapoursynth/releases/tag/R68

------
@Myrsloik:
When using:
import vapoursynth as vs
core = vs.core
import site
clip = core.std.BlankClip()
clip = core.text.Text(clip, str(core))
audio = vs.core.std.BlankAudio()
clip = core.std.Trim(clip=clip, first=0, last=1)
clip.set_output(index=0)
audio.set_output(index=1)
and calling vspipe --info "path to script"
I only get just the video info.
R65 and R68 and both just return:
Width: 640
Height: 480
Frames: 2
FPS: 24/1 (24.000 fps)
Format Name: RGB24
Color Family: RGB
Alpha: No
Sample Type: Integer
Bits: 8
SubSampling W: 0
SubSampling H: 0
no mention of the audio.

I noticed, that when using:
clip.set_output(index=1)
audio.set_output(index=0)
(setting audio to be the first index)
or using:
VSPipe.exe --info "Path to script" -o 1
I get:
Samples: 441000
Sample Rate: 44100
Format Name: Audio16 (2 CH)
Sample Type: Integer
Bits: 16
Channels: 2
Layout: Front Left, Front Right

=>
Would be nice if VSPipes '--info' could be adjusted, when called without '-o X' to either:
a. output the first index and some additional info what other indexes exist
or
b. output the info for all indexes, like:

OutputIndex: 0
Width: 640
Height: 480
Frames: 2
FPS: 24/1 (24.000 fps)
Format Name: RGB24
Color Family: RGB
Alpha: No
Sample Type: Integer
Bits: 8
SubSampling W: 0
SubSampling H: 0

OutputIndex: 1
Samples: 441000
Sample Rate: 44100
Format Name: Audio16 (2 CH)
Sample Type: Integer
Bits: 16
Channels: 2
Layout: Front Left, Front Right


Thanks for thinking about this.

Cu Selur

Myrsloik
19th May 2024, 16:49
Makes sense but there are a few problems.
Some people parse the info output so changing it would break things.
There's also no actual api function to obtain the set output indices so that needs to be added as well.
Create an issue and I'll probably do it in a bit.

Selur
19th May 2024, 17:03
Some people parse the info output so changing it would break things.
I do :)

Create an issue and I'll probably do it in a bit.
will do, thanks!

NoX1911
7th June 2024, 22:46
List of all known plugins and scripts (http://www.vapoursynth.com/doc/pluginlist.html)
Link is dead. Any alternative script collections?

Selur
8th June 2024, 06:06
https://vsdb.top/ might be a good start (https://github.com/Selur/VapoursynthScriptsInHybrid has the scripts Hybrid uses)

Myrsloik
8th June 2024, 09:56
Link is dead. Any alternative script collections?

Fixed it so it points at vsdb.top, you can also simply use vsrepo.py available to get a fairly complete list.

NoX1911
8th June 2024, 10:10
Ok, just thought there would be another collection of turnkey-ready vpy files. Its functions then.

amayra
9th June 2024, 16:06
out of curiosity i tried to find a way to play VPY script in android phone but i don't find any results

is that even possible ?

LigH
10th June 2024, 07:49
VapourSynth is based on Python. Where Python runs, there is at least a chance.

I believe to remember that Selur's Hybrid works on several platforms (Windows and Linux at least) where OS independent operation is supported (Avisynth not so easily, but core and VapourSynth). Android may be a special Linux variant, yet it is distinct in several features, so porting Linux ready software may not be as trivial.

Selur
10th June 2024, 08:13
Can't really comment on Android, but especially on phones I see multiple problems:
a. what python version is installed (R68 only supports Python 3.8 and 3.12)
b. are all the libraries Vapoursynth uses are available on Android
c. are the plugins one wants to use be compiled for arm. (probably not)
d. does the mobile even have enough power to run this stuff.
=> I doubt running Vapoursynth (with some plugins) on ARM is feasible atm.

Myrsloik
10th June 2024, 08:19
Can't really comment on Android, but especially on phones I see multiple problems:
a. what python version is installed (R68 only supports Python 3.8 and 3.12)
b. are all the libraries Vapoursynth uses are available on Android
c. are the plugins one wants to use be compiled for arm. (probably not)
d. does the mobile even have enough power to run this stuff.
=> I doubt running Vapoursynth (with some plugins) on ARM is feasible atm.

To add to this:
a: Python 3.8 (possibly 3.6) or later is supported. It's only to keep down the number of configurations on windows I don't provide more.
b: Very few libraries are used so if you have python the answer is yes.
c: You always have to compile that for every platform. No worse than the average linux distro.
d: I talked to a guy a few years ago who made it work on ios. Don't think it was ever made public but you can definitely run simpler things. Keep in mind that modern phones are like super awesome gaming computers 10 years ago.

Selur
20th June 2024, 18:12
I want to delete line 0-4 keep 5-9, delete 10-14, keep 15-19,...
(using tons of Crop and StackVertical calls seems like a bad idea)
Something like SeparateFields, but not splitting even and odd lines, but packages of 5 ?
(no problem if not, just playing with some ideas,..)

Boulder
20th June 2024, 18:32
I want to delete line 0-4 keep 5-9, delete 10-14, keep 15-19,...
(using tons of Crop and StackVertical calls seems like a bad idea)
Something like SeparateFields, but not splitting even and odd lines, but packages of 5 ?
(no problem if not, just playing with some ideas,..)

I think you could use a Python for loop for that to keep it quite simple.

Myrsloik
20th June 2024, 20:17
I want to delete line 0-4 keep 5-9, delete 10-14, keep 15-19,...
(using tons of Crop and StackVertical calls seems like a bad idea)
Something like SeparateFields, but not splitting even and odd lines, but packages of 5 ?
(no problem if not, just playing with some ideas,..)

AddBorders to make the input a 2^n height
Call SeparateFields until every frame consists of only one field
StackVertical([SelectEvery(cycle=addborder_clip.height, offset=something), ...]) <= this bit you'll probably have to automatically generate somehow

Or jusr write a filter, that's so much easier.

Selur
20th July 2024, 06:36
Looking at https://forum.videohelp.com/threads/415197 I was wondering whether there is a HShear and VShear version for Vapoursynth?
I know I can use:
core.avs.LoadPlugin(r"F:\Hybrid\64bit\Avisynth\avisynthPlugins\Rotate_x64.dll")
clip = core.avs.HShear(clip, 63.45)
but I wondered if there is a native version I'm not aware of.

amayra
18th September 2024, 01:20
Looking at https://forum.videohelp.com/threads/415197 I was wondering whether there is a HShear and VShear version for Vapoursynth?
I know I can use:
core.avs.LoadPlugin(r"F:\Hybrid\64bit\Avisynth\avisynthPlugins\Rotate_x64.dll")
clip = core.avs.HShear(clip, 63.45)
but I wondered if there is a native version I'm not aware of.

are you looking for something like this :

http://avisynth.nl/users/vcmohan/vcm/rotate.html

Selur
18th September 2024, 04:26
@amayra: thanks, not totally sure :)

lewyturn
10th October 2024, 08:00
Seek help:
I installed 'vapoursynth 7.0' as a portable version, and there was a problem.
I added the path to 'vsscript.dll' to the 'vsedit' settings.
Opening the script with the 'vsedit 6.8' but still returns error: Failed to get VSScript API!

what should i do?

lewyturn
10th October 2024, 13:18
Seek help:
I installed 'vapoursynth 7.0' as a portable version, and there was a problem.
I added the path to 'vsscript.dll' to the 'vsedit' settings.
Opening the script with the 'vsedit 6.8' but still returns error: Failed to get VSScript API!

what should i do?


The reason was found: the 'vapoursynth.dll' file was missing from the compressed file.

asarian
11th November 2024, 14:15
Updated to R70 today. Suddenly VSpipe outputs all kinds of warning, like

Warning: Plugin C:\Program Files\VapourSynth\plugins\SubText.dll already loaded

Is there any way to suppress these warnings? I see nothing in its options. Thanks.

Myrsloik
11th November 2024, 16:24
Updated to R70 today. Suddenly VSpipe outputs all kinds of warning, like

Warning: Plugin C:\Program Files\VapourSynth\plugins\SubText.dll already loaded

Is there any way to suppress these warnings? I see nothing in its options. Thanks.

No, there's no way to silence them.

asarian
11th November 2024, 20:30
No, there's no way to silence them.

That's too bad. (R57 never had this) But I'll live. :) And thanks for the great VS tool!

Myrsloik
12th November 2024, 12:22
That's too bad. (R57 never had this) But I'll live. :) And thanks for the great VS tool!

If there's actual popular demand I could add a silent option. So reply to this if you care.

asarian
12th November 2024, 14:23
If there's actual popular demand I could add a silent option. So reply to this if you care.


For the record, I care. :)

Reason I'd love to see a silent option, is because many scripts keep importing the stuff everyone else imports too; so the VSPipe output almost always starts with a sheer endless barage of WARNINGS (none of which I can resolve myself, mind you, short of editing all side-packages individually).

Z2697
12th November 2024, 15:17
For the record, I care. :)

Reason I'd love to see a silent option, is because many scripts keep importing the stuff everyone else imports too; so the VSPipe output almost always starts with a sheer endless barage of WARNINGS (none of which I can resolve myself, mind you, short of editing all side-packages individually).

It should have nothing to do with the packages, it's for duplicated plugins. Unless the package ships with plugin included and calls std.LoadPlugin to load it in side the python code, which I haven't seen one like this.
The better thing to do is check and remove duplicates your auto load folder, or clear your script (from std.LoadPlugin) or auto load folder (completely rely on std.LoadPlugin)

amayra
13th November 2024, 17:18
is it not possible to have plug-in that run every platform and architecture ?

just like some mods in games

LigH
13th November 2024, 17:39
Only if they are written in an architecture-independent programming language. Like, in Python; but not in C/C++ which would create CPU dependent byte code. But that would be faster. CPU dependent binary plugins can be optimized for speed using SIMD instructions (like SSE or AVX on intel x86-64 architecture). Plugins in an interpreted script language will always be less performant.

Selur
16th November 2024, 11:16
@Myrsloik: Question regarding "https://www.vapoursynth.com/doc/installation.html#os-x"
Can there be only one 'UserPluginDir' or can I (how?) specify multiple dirs with plugins?
In case, there can only be one: "Feature request: Please support multiple user dirs. :)"

Cu Selur

Myrsloik
18th November 2024, 16:00
@Myrsloik: Question regarding "https://www.vapoursynth.com/doc/installation.html#os-x"
Can there be only one 'UserPluginDir' or can I (how?) specify multiple dirs with plugins?
In case, there can only be one: "Feature request: Please support multiple user dirs. :)"

Cu Selur

GOOD NEWS EVERYONE!

I've now beaten the frivolous spam allegations and can once again answer you questions.

Why do you need multiple dirs? Why isn't LoadAllPlugins good enough? If you have a sane workflow that needs it maybe I'll add it.

ChaosKing
18th November 2024, 16:35
I always wanted either a custom dir with loading priority or simply the ability to unload a plugin.

In case of FrameSeeker https://forum.doom9.org/showthread.php?t=176231, I could use it to test the source filter installed by the user or test an "external" source filter without Appdata dll copy/delete/rename hacks.

Myrsloik
18th November 2024, 16:46
I always wanted either a custom dir with loading priority or simply the ability to unload a plugin.

In case of FrameSeeker https://forum.doom9.org/showthread.php?t=176231, I could use it to test the source filter installed by the user or test an "external" source filter without Appdata dll copy/delete/rename hacks.

Unloading is quite unlikely to happen since it's very complex and generally not required/a good idea.
If you want to load multiple different copies you have the secret arguments forceid and forcens in LoadPlugin to override a plugin's unique id and namespace which will let you get around the unique requirement.
Maybe that's helpful. Please only use this for testing/development or I'll have to kill you all.

ChaosKing
18th November 2024, 17:06
Unloading is quite unlikely to happen since it's very complex and generally not required/a good idea.
If you want to load multiple different copies you have the secret arguments forceid and forcens in LoadPlugin to override a plugin's unique id and namespace which will let you get around the unique requirement.
Maybe that's helpful. Please only use this for testing/development or I'll have to kill you all.

Finally the secret knowledge is mine!

I use windows, I was killed by Bill long ago :devil:

asarian
18th November 2024, 23:20
It should have nothing to do with the packages, it's for duplicated plugins. Unless the package ships with plugin included and calls std.LoadPlugin to load it in side the python code, which I haven't seen one like this.
The better thing to do is check and remove duplicates your auto load folder, or clear your script (from std.LoadPlugin) or auto load folder (completely rely on std.LoadPlugin)

My bad. I had installed R70, after a thorough cleanup, as there were many stubs left of various Python and VapourSynth versions. Apparently there was still one of those 'stubs' left for a plugins dir in AppData somewhere.

'Care' withdrawn, as the issue is resolved now.

Selur
20th November 2024, 20:07
Why do you need multiple dirs? Why isn't LoadAllPlugins good enough? If you have a sane workflow that needs it maybe I'll add it.
Would be useful on to load for example the plugins installed by homebrew and https://github.com/yuygfgg/Macos_vapoursynth_plugins and maybe vsrepo on MacOS.
Not really much of a problem.
But you are right LoadAllPlugins (https://www.vapoursynth.com/doc/functions/general/loadallplugins.html) should work fine. I simply wasn't aware of it. :)

Thanks!

Cu Selur

Selur
7th January 2025, 18:21
Is there a Vapoursynth alternative to Avisynths "TFM(pp=1).TDeint(hints=true)' ?

Jamaika
7th January 2025, 18:52
Is there a Vapoursynth alternative to Avisynths "TFM(pp=1).TDeint(hints=true)' ?
https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod

Selur
9th January 2025, 20:52
@Jamaika: TDeintMod does not seem to support 'hints':
tdm.TDeintMod(clip clip, int order[, int field=-1, int mode=0, int length=10, int mtype=1, int ttype=1, int mtql=-1, int mthl=-1, int mtqc=-1, int mthc=-1, int nt=2, int minthresh=4, int maxthresh=75, int cstr=4, int athresh=-1, int metric=0, int expand=0, bint link=True, bint show=False, clip edeint=None, int opt=0, int[] planes]) source: https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod/blob/master/README.md
which is why I suspect it will not look at the hints from ' "TFM(pp=1)' :(

Cu Selur

Selur
9th January 2025, 20:54
Oh, just read:
IsCombed is a utility function to check whether or not a frame is combed and stores the result (0 or 1) as a frame property named _Combed. It's intended to be used within std.FrameEval to process only combed frames and leave non-combed frames untouched..
So some wrapper FrameEval might work,..

Jamaika
10th January 2025, 10:41
@Jamaika: TDeintMod does not seem to support 'hints':
tdm.TDeintMod(clip clip, int order[, int field=-1, int mode=0, int length=10, int mtype=1, int ttype=1, int mtql=-1, int mthl=-1, int mtqc=-1, int mthc=-1, int nt=2, int minthresh=4, int maxthresh=75, int cstr=4, int athresh=-1, int metric=0, int expand=0, bint link=True, bint show=False, clip edeint=None, int opt=0, int[] planes]) source: https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod/blob/master/README.md
which is why I suspect it will not look at the hints from ' "TFM(pp=1)' :(

Cu Selur
VIVTC is a set of filters that can be used for inverse telecine. It is a rewrite of some of tritical’s TIVTC filters.
https://amusementclub.github.io/doc/plugins/vivtc.html#vivtc.VFM
Creators apparently decided that these functions were unnecessary. :rolleyes:
Unlike TFM, VFM does not have any postprocessing capabilities.
Topic from 2015. https://forum.doom9.org/showthread.php?t=172185

Selur
12th January 2025, 06:04
Thanks.

Selur
1st February 2025, 21:19
@Myrsloik: Would be nice if core.text.Text would also support RGBH in the future, atm. it gives:
vapoursynth.Error: Text: Input clip must be 8..16 bit integer or 32 bit float, passed RGBH
so I have to convert to RGS and back ;)

Myrsloik
3rd February 2025, 09:04
@Myrsloik: Would be nice if core.text.Text would also support RGBH in the future, atm. it gives:
vapoursynth.Error: Text: Input clip must be 8..16 bit integer or 32 bit float, passed RGBH
so I have to convert to RGS and back ;)

It's on the todo list. The reason it hasn't happened yet is that only some compilers support half precision types natively (gcc/clang both have the _Float16 and __fp16 extensions at least) and visual studio doesn't.

Software fp16 support is pointless since then single precision would be faster for all processing anyway. At best it would become a performance trap. Internally x86 cpus need to convert everything to single precision anyway.

Myrsloik
12th February 2025, 09:05
Does anyone still use the Python 3.8 support? Are the windows 7 fanatics still around? It's now been quite a few years since my last check.

_Al_
14th February 2025, 01:59
I use 3.8 because of using old opencv before opencv introduced a bug, reading wrong pixel information for a pixel (it is3/4 quadrant of pixel off), and they do not care to fix it. So forced to use older numpy, older python etc.
But do not mind me. Just saying, you do not have to be win7 fanatic to use older version. :-)

Selur
29th March 2025, 07:51
Does anyone know how to do the same as Avisynth
overlay(o, t, mode="subtract", opacity=0.15)
in Vapoursynth?
The widely used Overlay function from havsfunc, does not work as the Avisynth function does.
see: https://forum.doom9.org/showthread.php?t=186264
Vapoursynth overlay uses expr = f'x y -' which seems the intuitive way, but that is not what Avisynth does.


Cu Selur

Ps.: is there an alternative port of Avisynths Overlay than the one in havsfunc, that I'm not aware of?

Myrsloik
15th April 2025, 14:41
https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/overlay/OF_add.cpp#L83
With of_add=false
Start transcribing into expr

ChaosKing
15th April 2025, 17:03
I asked chagpt for fun and it "corrected" it to expr = 'x y - 0 max'

Should read as max(x - y, 0), but this is only a simple version of subtract.


Chatgpt: If your parser accepts this, you could use the following:

exprY = 'x y maskY * maskMode * y * (1 - maskMode) + -'
exprY = 'x (maskMode * y * maskY + (1 - maskMode) * y) -'
exprY = 'x (maskMode ? y * maskY : y) -'


For UV
exprU = 'xU (maskMode ? ((half * (1 - maskU) + maskU * yU)) : yU) - + half'
exprV = 'xV (maskMode ? ((half * (1 - maskV) + maskV * yV)) : yV) - + half'

Superdark-correction:
exprU = 'Yneg = max(0, -Y); mult = min(Yneg, over32); U = ((U * (over32 - mult)) + (half * mult)) >> shift'

ps I don't know what I'm doing :rolleyes:

GeoffreyA
16th April 2025, 12:24
VSPipe from R71 detected as malware in AVG. I reported it as a false positive.

Z2697
16th April 2025, 15:10
AVG is now owned by the "security giant" Gen Digital.
https://en.wikipedia.org/wiki/AVG_AntiVirus
https://en.wikipedia.org/wiki/Gen_Digital#Mergers_and_acquisitions

It's hard to imagine why they are taking such act. I mean look how many companies and softwares acquired! (and agreed to be acquired?)
Some stories say that those products are much worse after the merges or acquisitions.

It's almost like they are trying to dictate what's malware and what's not.

GeoffreyA
16th April 2025, 15:53
AVG is now owned by the "security giant" Gen Digital.
https://en.wikipedia.org/wiki/AVG_AntiVirus
https://en.wikipedia.org/wiki/Gen_Digital#Mergers_and_acquisitions

It's hard to imagine why they are taking such act. I mean look how many companies and softwares acquired! (and agreed to be acquired?)
Some stories say that those products are much worse after the merges or acquisitions.

It's almost like they are trying to dictate what's malware and what's not.

From Grisoft to Gen Digital! I find that AVG has always been a bit high on the false positives. When I compile FFmpeg occasionally, every second executable from the Media Autobuild Suite gets quarantined, likely owing to heuristics, so I've got to add the whole directory as an exception. With OCCT, the linpack executable gets blocked. Other than that, AVG Free has been all right for me. I've been using it since 2007.

Myrsloik
17th April 2025, 13:05
This time I have something slightly different for you to test. This version should be functionally identical to the R71 release but with one important difference: Python 3.12 and later support. As in 3.13 and 3.14 as well.

Try it out and see if it works. The portable install script will probably download the wrong file or fail in some other hilarious way so install the portable version manually.

https://github.com/vapoursynth/vapoursynth/releases/tag/R71-limited-api-test1

Z2697
17th April 2025, 14:53
This time I have something slightly different for you to test. This version should be functionally identical to the R71 release but with one important difference: Python 3.12 and later support. As in 3.13 and 3.14 as well.

Try it out and see if it works. The portable install script will probably download the wrong file or fail in some other hilarious way so install the portable version manually.

https://github.com/vapoursynth/vapoursynth/releases/tag/R71-limited-api-test1

It should also work for any version >= 3.8? (also combine the two separate wheels for 3.8 and newer?)

Myrsloik
17th April 2025, 15:29
It should also work for any version >= 3.8? (also combine the two separate wheels for 3.8 and newer?)

No. Anything older than 3.12 (technically 3.11 if compiled for it but then it's slower) doesn't have a complete enough python version independent api.

So 3.8 support remains as it is for the windows 7 fans. In the future I probably won't drop support for python versions until they're end of life. So 3.12 is good until 2029 unless something unexpected happens.

Z2697
17th April 2025, 17:18
No. Anything older than 3.12 (technically 3.11 if compiled for it but then it's slower) doesn't have a complete enough python version independent api.

So 3.8 support remains as it is for the windows 7 fans. In the future I probably won't drop support for python versions until they're end of life. So 3.12 is good until 2029 unless something unexpected happens.

Do you mean that 3.11 is generally slower for VapourSynth, or the version independent api of it is slower?

Myrsloik
17th April 2025, 17:37
Do you mean that 3.11 is generally slower for VapourSynth, or the version independent api of it is slower?

It's python 3.11. I also think most people already have migrated to 3.12.

Z2697
17th April 2025, 18:38
It's python 3.11. I also think most people already have migrated to 3.12.

Somehow I'm still on 3.11 and think building new VS releases for 3.11 is easier than upgrading Python LOL :o
Better find some time to finally do it.

Selur
17th April 2025, 19:37
In the future I probably won't drop support for python versions until they're end of life.
:goodpost: :thanks: That lessens the burden of trying to get pytorch&co working with Vapoursynth a lot. :)

Cu Selur

Selur
20th April 2025, 23:29
Using: https://github.com/Selur/VapoursynthScriptsInHybrid/blob/master/FillDuplicateFrames.py
with FillDuplicateFrames(clip=clip, method="MV", thresh=0.030000).out
that calls:
def interpolateWithMV(self, clip, n, start, end):
num = end - start
sup = core.mv.Super(clip, pel=2, hpad=0, vpad=0)
bvec = core.mv.Analyse(sup, blksize=16, isb=True, chroma=True, search=3, searchparam=1)
fvec = core.mv.Analyse(sup, blksize=16, isb=False, chroma=True, search=3, searchparam=1)
self.smooth = core.mv.FlowFPS(clip, sup, bvec, fvec, num=num, den=1, mask=2)
self.smooth_start = start
self.smooth_end = end
out = self.smooth[n-start]
if self.debug:
return out.text.Text(text="MV",alignment=9)
return out
gives me tons of :
Explicitly instantiated a Cache. This is no longer possible and the original clip has been passed through instead.
and I'm wondering why?
Where am I explicitly instantiating a cache? How can I fix this?

Cu Selur

Myrsloik
21st April 2025, 07:15
You probably have an old version of some plugin that does it internally. Or that's my guess.

Selur
21st April 2025, 07:57
Since I this does not happen with other interpolation methods, it must be mvtools.
I checked, I'm using https://github.com/dubhater/vapoursynth-mvtools/releases/tag/v24 which seems to be the latest version.
Strangely using:
sup = core.mv.Super(clip, pel=2, hpad=0, vpad=0)
bvec = core.mv.Analyse(sup, blksize=16, isb=True, chroma=True, search=3, searchparam=1)
fvec = core.mv.Analyse(sup, blksize=16, isb=False, chroma=True, search=3, searchparam=1)
clip = core.mv.FlowFPS(clip, sup, bvec, fvec, num=50, den=1, mask=2)
instead of:
fdf = FillDuplicateFrames(clip=clip, method="MV")
clip = fdf.out
the problem does not occur.
So it must be something else in FillDuplicateFrames. Strange.
=> Thanks for the feedback, I'll try to figure out what is causing this.

Cu Selur

Selur
21st April 2025, 08:23
Correction this is caused by mvtools!
I simplified the script to:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
import sys
import os
core = vs.core
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))

# loading plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/Support/libmvtools.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/LSMASHSource.dll")

clip = core.lsmas.LWLibavSource(source="G:/TestClips&Co/files/test.avi", format="YUV420P8", stream_index=0, cache=0, prefer_hw=0)

sup = core.mv.Super(clip, pel=2, hpad=0, vpad=0)
bvec = core.mv.Analyse(sup, blksize=16, isb=True, chroma=True, search=3, searchparam=1)
fvec = core.mv.Analyse(sup, blksize=16, isb=False, chroma=True, search=3, searchparam=1)
clip = core.mv.FlowFPS(clip, sup, bvec, fvec, num=50, den=1, mask=2)

# output
clip.set_output()
and calling:
VSPipe.exe c:\Users\Selur\Desktop\FillDuplicateFrames_MV_Cache.vpy NUL -c y4m
gave me:

Warning: Explicitly instantiated a Cache. This is no longer possible and the original clip has been passed through instead.
Warning: Explicitly instantiated a Cache. This is no longer possible and the original clip has been passed through instead.
Warning: Explicitly instantiated a Cache. This is no longer possible and the original clip has been passed through instead.
Warning: Explicitly instantiated a Cache. This is no longer possible and the original clip has been passed through instead.
Output 857 frames in 0.44 seconds (1926.36 fps)
=> will report to dubhater => https://github.com/dubhater/vapoursynth-mvtools/issues/87

Selur
23rd April 2025, 16:53
mvtools problem should be fixed in current git (https://github.com/dubhater/vapoursynth-mvtools/issues/87), sadly there wasn't a new release
=> could someone build and share a new Windows 64bit build?

Selur
24th April 2025, 13:47
Thanks to yuygfgg for the link.
=> Working libmvtools version: https://github.com/Mr-Z-2697/vapoursynth-mvtools/releases/tag/v24%2B8%2Bpatch-1

Myrsloik
21st May 2025, 12:26
R72-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R72-RC1)

Go test it. Has named pipe support in vspipe and supports ALL python versions starting with 3.12. The portable install script also works unlike the the previous test build.

Selur
21st May 2025, 14:08
Nice! Thanks, for the info. Initial tests did not show a problem here.

Myrsloik
27th May 2025, 07:49
R72-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R72-RC1)

Go test it. Has named pipe support in vspipe and supports ALL python versions starting with 3.12. The portable install script also works unlike the the previous test build.

I've added a clang build as well (same link). Speed comparisons welcome.

Myrsloik
2nd June 2025, 16:13
R72 (https://github.com/vapoursynth/vapoursynth/releases/tag/R72) is out. Blag post here (https://www.vapoursynth.com/2025/06/r72-named-pipes-and-python-3-12-support-on-windows/).

Myrsloik
5th June 2025, 17:37
Does anyone here still use a CPU without AVX2 instructions?

It's been standard in all CPUs for 15 years now

Adub
8th June 2025, 00:40
At least on my end - that's a negative ghost rider.

If anything, my oldest system is an AVX2 Zen 2 Threadripper. Then making extensive use of AVX512 on a Zen 5 9950X, and then ARM NEON on an M4 Mac.

It's for this reason that I made AVX2 the bare minimum support in Zsmooth (https://github.com/adworacz/zsmooth/commit/a3857a93386c37b32196366722a489ecf378eae8) and I have yet to receive any requests to make an older build.

Selur
8th June 2025, 06:40
Only, non-AVX2 system here is my Linux old NAS.
I know of a few Windows users of Hybrid that use non-AVX2 systems. (got reports when I started adding zsmooth support ;))
afaik starting with Windows 11 24H2 any supported cpu has AVX2, so the Windows 11 users are probably fine.
=> personally, I think it's reasonable to require AVX2 in future Vapoursynth versions, but folks with old Windows 7 and Windows 10 capture systems might complain. :)

Adub
9th June 2025, 04:36
Interesting to hear that there were some complaints - I honestly don't mind making a non-AVX2 build, if it's useful for some users. Zig makes it trivial. I just didn't receive any requests for one.

Myrsloik
15th June 2025, 17:01
Interesting to hear that there were some complaints - I honestly don't mind making a non-AVX2 build, if it's useful for some users. Zig makes it trivial. I just didn't receive any requests for one.

The builds were benchmarked and AVX2 clang was slower than normal clang so there won't be special builds anytime soon.

I've also just started migrating vapoursynth.com to a new registrar and host so vsrepo updates may stop working for a short amount of time.

lansing
6th September 2025, 17:56
Is the core.max_cache_size working correctly? I have a 1280 x 720 video and set the max cache size to 1000. But some random seeks in Virtualdub2 or vseditor2 makes the ram usage jumps over 2 GB.

Myrsloik
6th September 2025, 17:59
Is the core.max_cache_size working correctly? I have a 1280 x 720 video and set the max cache size to 1000. But some random seeks in Virtualdub2 or vseditor2 makes the ram usage jumps over 2 GB.

No script? You make this too easy...

It's only the maximum amount of memory the caches use before aggressively adjusting their sizes. Filter memory usage is not known or included.

Some scripts do weird stuff and keep a lot of frame references.

lansing
6th September 2025, 22:26
No script? You make this too easy...

It's only the maximum amount of memory the caches use before aggressively adjusting their sizes. Filter memory usage is not known or included.

Some scripts do weird stuff and keep a lot of frame references.
It's a script to load a mp4 file.


import vapoursynth as vs
core = vs.core
core.max_cache_size = 1000

file = r'test file.mp4'

clip = core.bs.VideoSource(file)
clip.set_output()

Myrsloik
6th September 2025, 22:29
It's a script to load a mp4 file.


import vapoursynth as vs
core = vs.core
core.max_cache_size = 1000

file = r'test file.mp4'

clip = core.bs.VideoSource(file)
clip.set_output()


maxdecoders: The maximum number of decoder instances kept around, defaults to 4 but when decoding high resolution content it may be beneficial to reduce it to 1 to reduce peak memory usage. For example 4k h264 material will use approximately 250MB of ram in addition to the specified cache size for decoder instance. Passing a number outside the 1-4 range will set it to the biggest number supported.

Default cache size is 100MB. This usually adds up to ~1GB for bestsource. Add another 1GB for the VS cache and you have 2GB.

lansing
7th September 2025, 22:59
How do I retrieve VSPresetVideoFormat like pfRGB24 and pfRGB48 from the API? I couldn't find any updated information about it.

Myrsloik
8th September 2025, 07:58
How do I retrieve VSPresetVideoFormat like pfRGB24 and pfRGB48 from the API? I couldn't find any updated information about it.

queryVideoFormatID(cfRGB, stInteger, 8 or 16, 0, 0)

lansing
8th September 2025, 16:36
queryVideoFormatID(cfRGB, stInteger, 8 or 16, 0, 0)

Thanks, it worked.

Selur
13th September 2025, 14:08
Is there nowadays a way to disable autoloading plugins in VapourSynth on Windows? (Especially when using a portable version.)

Cu Selur

Myrsloik
13th September 2025, 16:35
Is there nowadays a way to disable autoloading plugins in VapourSynth on Windows? (Especially when using a portable version.)

Cu Selur

No? Just don't have plugins in the portable autoloading dir.

Selur
13th September 2025, 16:45
I don't. Sorry, should have been clearer. The problem is when there is also a system-wide version installed and I use my portable version, I would like Vapoursynth to not check <AppData>\VapourSynth\plugins32 or <AppData>\VapourSynth\plugins64.

Myrsloik
13th September 2025, 17:29
I don't. Sorry, should have been clearer. The problem is when there is also a system-wide version installed and I use my portable version, I would like Vapoursynth to not check <AppData>\VapourSynth\plugins32 or <AppData>\VapourSynth\plugins64.

But it doesn't. Potable mode only loads from the portable subdirs.

See: https://github.com/vapoursynth/vapoursynth/blob/master/src/core/vscore.cpp#L1846

Selur
13th September 2025, 18:19
Nice, this must have changed since I last checked. Thanks. :)

_Al_
13th September 2025, 22:10
Potable mode only loads from the portable subdirs.

that's great, thank you.

Myrsloik
27th October 2025, 10:34
I've now got an official timeframe for when windows 7 and 8 support is dropped. It will happen shortly after visual studio 2026 is released due to its compiler no longer being able to target anything older than windows 10.

Also testing. Windows 7 users are getting as rare as windows xp ones were 10 years ago.

Added a week after the initial post:
Cython will probably drop support for python 3.8 within a year as well. See https://github.com/cython/cython/issues/7271

lansing
16th November 2025, 22:37
Does Vapoursynth have a function that can compare planeStats between two frames? I want to check if frame 1 and frame 4 of a clip are duplicates. There is the std.planeState() function but it only takes in videoNode.

Myrsloik
16th November 2025, 23:03
Does Vapoursynth have a function that can compare planeStats between two frames? I want to check if frame 1 and frame 4 of a clip are duplicates. There is the std.planeState() function but it only takes in videoNode.

https://www.vapoursynth.com/doc/functions/video/planestats.html

PlaneStats(clip, clip[3:], plane=0)
PlaneStats(clip, clip[3:], plane=1)
PlaneStats(clip, clip[3:], plane=2)
And then check if all values in the PlaneStatsDiff array is 0 in FrameEval or with get_frame() or whatever.

Or did you mean something else?

lansing
17th November 2025, 06:12
https://www.vapoursynth.com/doc/functions/video/planestats.html

PlaneStats(clip, clip[3:], plane=0)
PlaneStats(clip, clip[3:], plane=1)
PlaneStats(clip, clip[3:], plane=2)
And then check if all values in the PlaneStatsDiff array is 0 in FrameEval or with get_frame() or whatever.

Or did you mean something else?

update:
I have tested on an anime scene where only the mouth part of a character moves. I have tested on multiple duplicate and non duplicated frames, and the PlaneStatsDiff doesn't really correctly identified them, as sometime the non dupe frame has lower PlaneStatsDiff.

frame1 = 776
frame2 = 792
plane0Diff = core.std.PlaneStats(clip[frame1], clip[frame2], plane=0).get_frame(0).props.get("PlaneStatsDiff")
plane1Diff = core.std.PlaneStats(clip[frame1], clip[frame2], plane=1).get_frame(0).props.get("PlaneStatsDiff")
plane2Diff = core.std.PlaneStats(clip[frame1], clip[frame2], plane=2).get_frame(0).props.get("PlaneStatsDiff")

print (f"{plane0Diff} {plane1Diff} {plane2Diff}")



dupe:
0.006336805555555556 0.008689860203340595 0.002074527959331881
0.007430623638344226 0.010009486201888162 0.002679103122730574
0.012313929738562091 0.010722176833696442 0.004285720769789397
0.012649328249818445 0.011406454248366013 0.004285493827160494


not dupe:
0.009854688634713145 0.010607071532316631 0.0031678921568627453
0.008919673656499637 0.010732343863471314 0.0037011165577342047

LightArrowsEXE
17th November 2025, 10:49
Assuming by "dupe" you mean "a frame that looks the same but is not the exact same frame", this may be the result of either dithering or compression.

Myrsloik
17th November 2025, 19:49
update:
I have tested on an anime scene where only the mouth part of a character moves. I have tested on multiple duplicate and non duplicated frames, and the PlaneStatsDiff doesn't really correctly identified them, as sometime the non dupe frame has lower PlaneStatsDiff.

frame1 = 776
frame2 = 792
plane0Diff = core.std.PlaneStats(clip[frame1], clip[frame2], plane=0).get_frame(0).props.get("PlaneStatsDiff")
plane1Diff = core.std.PlaneStats(clip[frame1], clip[frame2], plane=1).get_frame(0).props.get("PlaneStatsDiff")
plane2Diff = core.std.PlaneStats(clip[frame1], clip[frame2], plane=2).get_frame(0).props.get("PlaneStatsDiff")

print (f"{plane0Diff} {plane1Diff} {plane2Diff}")



dupe:
0.006336805555555556 0.008689860203340595 0.002074527959331881
0.007430623638344226 0.010009486201888162 0.002679103122730574
0.012313929738562091 0.010722176833696442 0.004285720769789397
0.012649328249818445 0.011406454248366013 0.004285493827160494


not dupe:
0.009854688634713145 0.010607071532316631 0.0031678921568627453
0.008919673656499637 0.010732343863471314 0.0037011165577342047


What you want is something more like the avisynth filter dup (or its dedup derivative). Using absolute difference over the full image is horrible since mouth movements and noise can't be distinguished. Instead a windowed diff function is much better (but not perfect).

In VapourSynth you can get similar decisions using vivtc.VDecimate(clip, dryrun=True) and thresholding based on the VDecimateMaxBlockDiff property.

lansing
17th November 2025, 21:22
What you want is something more like the avisynth filter dup (or its dedup derivative). Using absolute difference over the full image is horrible since mouth movements and noise can't be distinguished. Instead a windowed diff function is much better (but not perfect).

In VapourSynth you can get similar decisions using vivtc.VDecimate(clip, dryrun=True) and thresholding based on the VDecimateMaxBlockDiff property.

Thanks. I looked it up but the VDecimateMaxBlockDiff property was derived only from consecutive frames, it can't compare frames from far apart.

I asked Grok and it said that the Dupli plugin from feisty2 can do it, but its github page was long gone.

Myrsloik
17th November 2025, 22:01
Reorder your frames. Use multiple clips. Interleve them. There's always a way.

lansing
18th November 2025, 07:44
I ran into an error when calling VideoFrame.get_stride(plane), it said that the attribute doesn't exist. I'm using the latest R72.

update, I got it working. I was calling the function from VideoNode instead of VideoFrame.

lansing
19th November 2025, 16:49
I got the duplicate frame detecting function working, but I don't know how to output the result list from std.FrameEval().


def output_duplicate(clip):

dupe_frame_list = []

def find_duplicated(n, f):
...

is_dup = isDuplicateFrames(curr_frame, future_frame)

if is_dup:
dupe_frame_list.append(n)

...

out = core.std.FrameEval(clip, find_duplicate, prop_src=[clip])
return out, dupe_frame_list

processed_clip, dupe_list = output_duplicate(clip)

processed_clip.set_output()
print(dupe_list)


I want to output the list to png but I couldn't even get the list to print out as a test. The command I use


vspipe test.vpy --

_Al_
20th November 2025, 21:19
is_dup = isDuplicateFrames(curr_frame, future_frame)

not obvious where curr_frame and future_frame came from, also if not having set them as globals or using as a class attributes, locals in a functions are forgotten

lansing
20th November 2025, 23:32
not obvious where curr_frame and future_frame came from, also if not having set them as globals or using as a class attributes, locals in a functions are forgotten

I figured the problem. I shouldn't be using std.FrameEval() for my case, as it is a lazy function. So when I ran the script, the python code will run first before FrameEval. By the time it got to the function, the python codes has already ended.

I switched to a while loop and it worked.

_Al_
21st November 2025, 21:46
ok, also using *.py instead of *.vpy, any calculations, previewing codes, any help routines before encoding to figure out something, could be safely written into a if __name__ == "__main__" block, so it could be run as python first to explore it. Then running it again later for encoding using vspipe would be safe, that block would not run because global __name__ is set as "__vapoursynth__", example:

import vapoursynth as vs
from vapoursynth import core

video = core.std.BlankClip(format=vs.YUV420P8)
audio = core.std.BlankAudio()
video.set_output(0)
audio.set_output(1)

if __name__ == "__main__":
THRESHOLD : float = 0.001
video = core.std.PlaneStats(video, video[0]+video)
dupe_frame_list = []
for n, f in enumerate(video.frames()):
if f.props['PlaneStatsDiff'] < THRESHOLD and n:
dupe_frame_list.append(n)
print(dupe_frame_list)

Myrsloik
23rd November 2025, 15:58
R73-RC1 (https://github.com/vapoursynth/vapoursynth/releases/tag/R73-RC1)

Just bug fixes this time. This is also the last release with windows 7 support. After this I plan to switch to vs2026 and possibly also clang-cl.

If someone wants to keep providing binaries for older windows versions tell me and I'll link to them.

Z2697
23rd November 2025, 17:34
fixed max_cache_size setter (jsaowji)
This is a fix for a regression that does not exist in R72, maybe it's a bit confusing to put it like this?

Myrsloik
23rd November 2025, 20:55
This is a fix for a regression that does not exist in R72, maybe it's a bit confusing to put it like this?

Will remove that line to not confuse anyone

Myrsloik
24th November 2025, 18:39
R73 - The final Windows 7 release (https://github.com/vapoursynth/vapoursynth/releases/tag/R73)
Short blog post here (https://www.vapoursynth.com/2025/11/24/r73-the-last-windows-7-release/)

No code changes from RC1 so no reason to redownload.

Selur
19th December 2025, 00:04
Not sure who's responsible for the homebrew vapoursynth updates, but switching to R73 and not offering a vapoursynth@R72 just broke my setup, since I accidentally updated to R73, but couldn't go back.
=> would be nice if when updating to RXX at least the last two previous versions should still be available. Thanks for considering,...

What I did to get back R72:

downloaded the vapoursynth.rb (https://raw.githubusercontent.com/Homebrew/homebrew-core/81833ca5d7584a939b0227abb4651faabf6e88cc/Formula/v/vapoursynth.rb) file (old version)
created a new brew tab:
brew tap-new selur/vapoursynth
this created:
"/opt/homebrew/Library/Taps/selur/homebrew-vapoursynth"
copied the vapoursynth.rb into the Formula-folder of the new brew-tab:
cp ~/Downloads/vapoursynth.rb /opt/homebrew/Library/Taps/selur/homebrew-vapoursynth/Formula/
uninstalled the current R73 Vapoursynth install
brew uninstall vapoursynth
installed the old R72 using the copied formula:
brew install selur/vapoursynth/vapoursynth

with this, my vsViewer&co worked fine again.
Just wrote this so others that might need R72 know what to do,..

Cu Selur

Z2697
19th December 2025, 06:43
What's broken, exactly?

Selur
19th December 2025, 08:08
i.e. vsViewer (https://github.com/Selur/vsViewer) doesn't work anymore. (it probably needs adjustment, but I have not time for that at the moment)

Myrsloik
19th December 2025, 09:01
i.e. vsViewer (https://github.com/Selur/vsViewer) doesn't work anymore. (it probably needs adjustment, but I have not time for that at the moment)

Old vsscript api support was removed. No matter how many years I give people to upgrade code it never happens until I hit the delete button...

Selur
19th December 2025, 09:55
I agree with that.
I wasn't complaining that the old support was removed, just that forcing homebrew users to R73 is a pain and that there should be a way to install R72.

Is there some overview of what changed from the old to the new api?

Z2697
19th December 2025, 11:16
https://github.com/YomikoR/VapourSynth-Editor/commit/465e9ca0d559fb208f69dc52976579f0297f92a4#diff-a8f025fd6c8566a79185cd369132818e230260b3f3e8bc9fbfc2be1545e521d1

Selur
19th December 2025, 15:31
@Z2697: Thanks, I'll look at it after the holidays, adjusted vsViewer to work with R73, still beeing forced to switch to R73 on homebrew seems like unneeded trouble,..

lansing
30th December 2025, 03:42
I'm having trouble with VIVTC matching. It works fine most of the time but for this one video it doesn't work quite well. I have to set the mi value to very low in order for the combed frame to be detected, but even that, it was still not matching. I have tried all the modes and none work. It worked fine when I use DGSource's force film option.

https://i.imgur.com/QSFcrCP.png


import vapoursynth as vs
core = vs.core

test_file = r'test.mkv'

clip = core.bs.VideoSource(test_file , rff=True)

clip = core.vivtc.VFM(clip, 1, mi=35)
#clip = core.vivtc.VDecimate(clip)
clip = core.text.FrameProps(clip)

clip.set_output()

orchid
30th December 2025, 08:11
I believe there is an issue open for this already:
https://github.com/vapoursynth/vivtc/issues/6

Columbo
30th December 2025, 11:27
DGSource() doesn't do any actual matching. Everything is done via the RFF flags. You can try giving rff=False while omitting the vivtc stuff. I don't know the details of VideoSource(), but here are two things to watch out for:

1. Files with irregular pulldown or with a mix of hard and soft pulldown. For your source here it's likely not an issue, because you say DGSource() handles it fine.

2. The output frame rate may need to be set manually.

Z2697
31st December 2025, 10:49
Clang build is still broken! And it's the only version available from github release R73.
The problem lies in clang itself.

Myrsloik
31st December 2025, 12:02
Clang build is still broken! And it's the only version available from github release R73.
The problem lies in clang itself.

Lolno. Stop making shit up. R73 was compiled with vs2022 toolchain and nothing else.

Z2697
31st December 2025, 18:44
Lolno. Stop making shit up. R73 was compiled with vs2022 toolchain and nothing else.

Well the real story is you updated the release binary and I was using the "old R73", which was basically the same as R73-RC1.
And R73-RC1 was compiled by clang-cl.
I didn't re-download the R73 and confirm the updated release, that's on me, but I'm not making shit up.
Stop gaslighting the user(s) of your software.

R73 - The final Windows 7 release (https://github.com/vapoursynth/vapoursynth/releases/tag/R73)
Short blog post here (https://www.vapoursynth.com/2025/11/24/r73-the-last-windows-7-release/)

No code changes from RC1 so no reason to redownload.

You can see the release files' timestamp is roughly a day after this post.


The "old R73" for comparison.
https://github.com/Mr-Z-2697/vapoursynth/releases/download/R73%2B4/_Broken_VapourSynth64-Portable-R73.zip

videohelp still has the "old R73" as "latest".
https://www.videohelp.com/software/VapourSynth

Myrsloik
2nd January 2026, 09:33
Well the real story is you updated the release binary and I was using the "old R73", which was basically the same as R73-RC1.
And R73-RC1 was compiled by clang-cl.
I didn't re-download the R73 and confirm the updated release, that's on me, but I'm not making shit up.
Stop gaslighting the user(s) of your software.



You can see the release files' timestamp is roughly a day after this post.


The "old R73" for comparison.
https://github.com/Mr-Z-2697/vapoursynth/releases/download/R73%2B4/_Broken_VapourSynth64-Portable-R73.zip

videohelp still has the "old R73" as "latest".
https://www.videohelp.com/software/VapourSynth

Lolwat? So a website I have no affiliation with has mirrored the wrong files and another pre-release was compiled in a different way? Such a "real story", much wow!

I suggest you IMMEDIATELY RETURN DEFECT PIECE OF SOFTWARE FOR A FULL REFUND.

Thundik81
2nd January 2026, 11:38
Lolwat? So a website I have no affiliation with has mirrored the wrong files and another pre-release was compiled in a different way? Such a "real story", much wow!

I suggest you IMMEDIATELY RETURN DEFECT PIECE OF SOFTWARE FOR A FULL REFUND.

https://github.com/vapoursynth/vapoursynth/releases/download/R73/VapourSynth64-Portable-R73.zip
was updated at least one time.
Mine (2025-11-24 17:51:03) has the following hash: 8188466fa353e5596f2a09ae8c42357eb2e02ed5418a1e1da3002c1f30d19a21
but Microsoft Visual Studio(2022, v17.6)

Z2697
3rd January 2026, 11:43
It's more than a month ago it's ok if you forgot you did it :)

Selur
12th February 2026, 19:25
Seeing https://github.com/dubhater/vapoursynth-mvtools/pull/90 I was wondering whether someone has those faster mvtools builds,...?

Z2697
12th February 2026, 21:21
Seeing https://github.com/dubhater/vapoursynth-mvtools/pull/90 I was wondering whether someone has those faster mvtools builds,...?

In my experience, when it comes to mvtools (vs version at least) the main difference here is the compiler, so in theory the releases in my fork will have same level of performance.

Selur
13th February 2026, 09:54
Good to know. Thanks!

Cu Selur

Ps.: that build really is faster :)