wonkey_monkey
27th July 2025, 13:58
OnDemandFilter v0.2 (http://horman.net/avisynth/)
Direct link (http://horman.net/avisynth/download/OnDemandFilter_v0.2.zip)
Documentation (http://horman.net/avisynth/OnDemandFilter.html)
0.2: Possibly safer unloadng
0.1: First release
OnDemandFilter is a wrapper for calls to other filters which defers invoking the filter until it's truly required, reducing initial script loading time. It also only allows a specified number of such filters to be active at any one tme, reducing memory usage.
In testing, a script with peak memory usage of over 10Gb was reduced to using less than 450Mb, while initial loadng time was reduced from 10s to 1s.
As an example, suppose you have (as I do) a script which opens dozens of HD sources using BestSource (https://github.com/vapoursynth/bestsource/) (or FFMpegSource, DirectShowSource, etc). Even with caching turned off, each source will require a few hundred megabytes to keep a GOP's worth of uncompressed frames in RAM for decoding purposes.
Instead of doing this:
a = BSSource("file1.mkv", atrack = 1, cachemode = 4, vcachesize = 0)
b = BSSource("file2.mkv", atrack = 1, cachemode = 4, vcachesize = 0)
c = BSSource("file3.mkv", atrack = 1, cachemode = 4, vcachesize = 0)
[...]
a + b + c + d + e + f + g + h + ...
...you can now do this, passing a filter name, plus its parameters as an array:
a = OnDemandFilter("BSSource", [ "file1.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ])
b = OnDemandFilter("BSSource", [ "file2.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ])
c = OnDemandFilter("BSSource", [ "file3.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ])
[...]
OnDemandFilterLimit(1) # only 1 clip will be loaded at any time
a + b + c + d + e + f + g + h + ...
In the latter case, only one instance of BSSource will be invoked at any time, depending on what frames are being requested. For example, if clip "a" is 100 frames, once playback reaches frame 100, clip "a"'s instance of BSSource will be unloaded to make way for clip "b", releasing any RAM it was using.
OnDemandFilterLimit sets the number of clips allowed to be active at any one time. It defaults to 4 to prevent transitions (dissolves, for example) from thrashing as multiple clips would be repeatedly loaded and unloaded.
vi_clip parameter:
In the above example, the specified filter must be opened on load to get the parameters of the resulting clip (resolution, pixel type, audio parameters etc). To avoid this, and to increase initial loading time, a placeholder clip can be specified which should match the result of the deferred filter, e.g.:
vi_clip = blankclip(length = 1000000, pixel_type = "yv12", width = 1920, height = 1080, fps = 25, audio_rate = 48000, channels = 2)
a = OnDemandFilter("BSSource", [ "file1.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ], vi_clip.trim(0, [length of clip a - 1]))
b = OnDemandFilter("BSSource", [ "file2.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ], vi_clip.trim(0, [length of clip b - 1]))
c = OnDemandFilter("BSSource", [ "file3.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ], vi_clip.trim(0, [length of clip c - 1]))
[...]
OnDemandFilterLimit(1) # only 1 clip will be loaded at any time
a + b + c + d + e + f + g + h + ...
Hopefully this all makes sense. If not, ask away.
Direct link (http://horman.net/avisynth/download/OnDemandFilter_v0.2.zip)
Documentation (http://horman.net/avisynth/OnDemandFilter.html)
0.2: Possibly safer unloadng
0.1: First release
OnDemandFilter is a wrapper for calls to other filters which defers invoking the filter until it's truly required, reducing initial script loading time. It also only allows a specified number of such filters to be active at any one tme, reducing memory usage.
In testing, a script with peak memory usage of over 10Gb was reduced to using less than 450Mb, while initial loadng time was reduced from 10s to 1s.
As an example, suppose you have (as I do) a script which opens dozens of HD sources using BestSource (https://github.com/vapoursynth/bestsource/) (or FFMpegSource, DirectShowSource, etc). Even with caching turned off, each source will require a few hundred megabytes to keep a GOP's worth of uncompressed frames in RAM for decoding purposes.
Instead of doing this:
a = BSSource("file1.mkv", atrack = 1, cachemode = 4, vcachesize = 0)
b = BSSource("file2.mkv", atrack = 1, cachemode = 4, vcachesize = 0)
c = BSSource("file3.mkv", atrack = 1, cachemode = 4, vcachesize = 0)
[...]
a + b + c + d + e + f + g + h + ...
...you can now do this, passing a filter name, plus its parameters as an array:
a = OnDemandFilter("BSSource", [ "file1.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ])
b = OnDemandFilter("BSSource", [ "file2.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ])
c = OnDemandFilter("BSSource", [ "file3.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ])
[...]
OnDemandFilterLimit(1) # only 1 clip will be loaded at any time
a + b + c + d + e + f + g + h + ...
In the latter case, only one instance of BSSource will be invoked at any time, depending on what frames are being requested. For example, if clip "a" is 100 frames, once playback reaches frame 100, clip "a"'s instance of BSSource will be unloaded to make way for clip "b", releasing any RAM it was using.
OnDemandFilterLimit sets the number of clips allowed to be active at any one time. It defaults to 4 to prevent transitions (dissolves, for example) from thrashing as multiple clips would be repeatedly loaded and unloaded.
vi_clip parameter:
In the above example, the specified filter must be opened on load to get the parameters of the resulting clip (resolution, pixel type, audio parameters etc). To avoid this, and to increase initial loading time, a placeholder clip can be specified which should match the result of the deferred filter, e.g.:
vi_clip = blankclip(length = 1000000, pixel_type = "yv12", width = 1920, height = 1080, fps = 25, audio_rate = 48000, channels = 2)
a = OnDemandFilter("BSSource", [ "file1.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ], vi_clip.trim(0, [length of clip a - 1]))
b = OnDemandFilter("BSSource", [ "file2.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ], vi_clip.trim(0, [length of clip b - 1]))
c = OnDemandFilter("BSSource", [ "file3.mkv", [ "atrack", 1 ], [ "cachemode", 4 ], [ "vcachesize", 0 ] ], vi_clip.trim(0, [length of clip c - 1]))
[...]
OnDemandFilterLimit(1) # only 1 clip will be loaded at any time
a + b + c + d + e + f + g + h + ...
Hopefully this all makes sense. If not, ask away.