View Full Version : Vapoursynth
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 :)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.