Log in

View Full Version : How to load other scripts as sources?


Selur
9th December 2017, 10:45
I got a usage question. :)

I got three script:
1. Script A: (loading a source; A.vpy)
# Imports
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")
# Loading F:\TestClips&Co\Test-AC3-5.1.avi using FFMS2
clip = core.ffms2.Source(source="F:/TESTCL~1/TEST-A~1.AVI",cachefile="H:/Output/avi_54a4199c1a3d3b1476ea1d15dc267332_4827.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg")
# Making sure input color range is set to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# Output
clip.set_output()
2. Script B: (loading another source; output will have same resolution as A; B.vpy)
# Imports
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")
# Loading F:\TestClips&Co\Test-AC3-5.1.avi using FFMS2
clip = core.ffms2.Source(source="F:/TESTCL~1/TEST-A~1.AVI",cachefile="H:/Output/avi_54a4199c1a3d3b1476ea1d15dc267332_4827.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg")
# Making sure input color range is set to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# Color Adjustment
clip = core.std.Levels(clip=clip, gamma=1.50)
# Output
clip.set_output()
3. Script combined (which should combine the two script and do some additional stuff; combined.vpy)
# Imports
import vapoursynth as vs
core = vs.get_core()
original = ... # no idea on how to load A
filtered = ... # no idea on how toload B
# doing something with the two clips,.. for example stacking them
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
I know I could all this inside one script, but the point here is for me to learn how to read external scripts as sources which can not be edited. So content of A.vpy and B.vpy doesn't really matter, since I can't influence them, but I know they got the same resolution.

My problem is I have no idea how to load another vpy script as a video source. :)

-> How does one load another script as a source? (I guess it is probably easy and I simply don't know how to approach the problem.)

Thanks! :)

Cu Selur

DJATOM
9th December 2017, 11:13
The only thing I'm thinking that you can wrap your scripts as functions and import those scripts into combined ->

original = scriptA.function()
filtered = scriptB.function()
...

Something like that.

Selur
9th December 2017, 11:18
@DJTOM: Thanks for that idea, but it would require me to edit scriptA and scriptB, which I want to avoid if possible at all.
-> hoping someone knows a better way or can confirm that this is the only way. :)

Cu Selur

Myrsloik
9th December 2017, 11:38
This is an ugly solution I don't really approve of but you can do something like:

[CODE]import scripta
aclip = vs.get_output() #set when impoting the script

import scriptb
bclip = vs.get_output()

#obviously put your own set_output() last or use a nonzero index

Selur
9th December 2017, 11:58
Okay, struggling with the 'import part', I tried:
# Imports
import os
import sys
import vapoursynth as vs
core = vs.get_core()
scriptPath = 'h:/Output'
sys.path.append(os.path.abspath(scriptPath))
#import script A ('h:/Output/A.vpy')
import A
original = vs.get_output()
#import script B ('h:/Output/B.vpy')
import B
clip = vs.get_output()
# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
-> I'm unclear on how to specify that A.vpy/B.vpy should be imported, appending the path where the two scripts are located to the sys.path didn't work. :)

DJATOM
9th December 2017, 12:04
It should work if all your scripts placed in the same dir. You don't need to adjust "path".
It might refuse to import if scripts named with 1 symbol, try more complex names.

Selur
9th December 2017, 12:12
It should work if all your scripts placed in the same dir. You don't need to adjust "path".
It might refuse to import if scripts named with 1 symbol, try more complex names.
The scripts are all lying inside the same directory. (H:/Output)

I renamed 'A.vpy' to 'scriptA.vpy', 'B.vpy' to 'scriptB.vpy' and adjusted 'combined.vpy' to:
# Imports
import vapoursynth as vs
core = vs.get_core()
#import script A (h:/Output/scriptA.vpy)
import scriptA
original = vs.get_output()
#import script B (h:/Output/scriptB.vpy)
import scriptB
clip = vs.get_output()
# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
Sadly that doesn't work either.
I get:
Failed to evaluate the script:
Python exception: No module named 'scriptA'

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 5, in <module>
import scriptA
ModuleNotFoundError: No module named 'scriptA'

Cu Selur

Myrsloik
9th December 2017, 12:14
Obviously they need to have a .py extension to be found that way

Selur
9th December 2017, 12:18
Obviously they need to have a .py extension to be found that way
Renaming 'scriptA.vpy' to 'scriptA.py', 'scriptB.vpy' to 'scriptB.py' and adjusting 'combined.vpy' to:
# Imports
import vapoursynth as vs
core = vs.get_core()
#import script A (h:/Output/scriptA.py)
import scriptA
original = vs.get_output()
#import script B (h:/Output/scriptB.py)
import scriptB
clip = vs.get_output()
# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
gives me:
Failed to evaluate the script:
Python exception: No module named 'scriptA'

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 5, in <module>
import scriptA
ModuleNotFoundError: No module named 'scriptA'


Cu Selur

AzraelNewtype
9th December 2017, 13:07
Open a python console in that directory and see if you can import the scripts at all, even if you're not actually doing anything with them. PEP-8 very strongly discourages capitals in module names, but I just tested and they're not expressly forbidden. It's possible the context of whatever is running combined.vpy doesn't think the other two scripts are still in the PYTHONPATH? Of course, I see that you were manually adding the path before, but it looks like you stopped doing that shortly before you had the scripts named in such a way that python would ever find them. If they load safely in the command environment, try adding the path manipulation back in. If not, I'll actually be pretty confused.

Selur
9th December 2017, 13:30
I'm using a portable Python. (Sorry, should have mentioned that.)
So setting the script path is probably needed.
Using:
# Imports
import os
import sys
import vapoursynth as vs
core = vs.get_core()

scriptPath = 'h:/Output'
sys.path.append(os.path.abspath(scriptPath))

#import script A (h:/Output/scriptA.py)
import scriptA
original = vs.get_output()
#import script B (h:/Output/scriptB.py)
import scriptB
clip = vs.get_output()
# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
I get:
Failed to evaluate the script:
Python exception: Plugin G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll already loaded (com.vapoursynth.ffms2)

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 14, in <module>
import scriptB
File "h:\Output\scriptB.py", line 5, in <module>
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")
File "src\cython\vapoursynth.pyx", line 1722, in vapoursynth.Function.__call__ (src\cython\vapoursynth.c:35000)
vapoursynth.Error: Plugin G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll already loaded (com.vapoursynth.ffms2)

Seems like the importing itself does work that way. Hurray! :)

Problem now is that both scripts use the same source filter (ffms2.dll) and thus the second script crashes on the LoadPlugin-line, since the Plugin is already loaded.

So:

Is there a way to check whether a plugin is already loaded ? (won't help here since I don't want to edit the two scripts, but it might be helpful when I generate scripts)
Might be a good idea if LoadPlugin would not cause a crash but instead simply ignore the second 'loading'-attempt.


Seems like currently import isn't the right way.

Cu Selur

DJATOM
9th December 2017, 13:48
Is there a way to check whether a plugin is already loaded
Yes, use hasattr().

Selur
9th December 2017, 14:01
Yes, use hasattr().
So like this?

if not hasattr(core,'ffms2')
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")


When I change scriptB to:
# Imports
import sys
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
if not hasattr(core, 'ffms2')
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")

# Loading F:\TestClips&Co\Test-AC3-5.1.avi using FFMS2
clip = core.ffms2.Source(source="F:/TESTCL~1/TEST-A~1.AVI",cachefile="H:/Output/avi_54a4199c1a3d3b1476ea1d15dc267332_4827.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg")
# Making sure input color range is set to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# Color Adjustment
clip = core.std.Levels(clip=clip, gamma=1.50)
# Output
clip.set_output()
combined.vpy:
# Imports
import os
import sys
import vapoursynth as vs
core = vs.get_core()

scriptPath = 'h:/Output'
sys.path.append(os.path.abspath(scriptPath))

#import script A (h:/Output/scriptA.py)
import scriptA
original = vs.get_output()
#import script B (h:/Output/scriptB.py)
import scriptB
clip = vs.get_output()
# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
(still looking for a way to do this without changing scriptA and scriptB, but curious how this works)

fails with:
Failed to evaluate the script:
Python exception: 0

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 12, in <module>
original = vs.get_output()
File "src\cython\vapoursynth.pyx", line 179, in vapoursynth.get_output (src\cython\vapoursynth.c:6257)
KeyError: 0
No clue why this happens. :(

------------------
Correction seems like there was some cache which caused this, it already crashes with:
Failed to evaluate the script:
Python exception: invalid syntax (scriptB.py, line 6)

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 14, in <module>
import scriptB
File "h:\Output\scriptB.py", line 6
if not hasattr(core, 'ffms2')
^
SyntaxError: invalid syntax
, so that call needs to look like another way. :)


Cu Selur

Myrsloik
9th December 2017, 14:12
So like this?

if not hasattr(core,'ffms2')
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")


When I change scriptB to:
# Imports
import sys
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
if not hasattr(core, 'ffms2')
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")

# Loading F:\TestClips&Co\Test-AC3-5.1.avi using FFMS2
clip = core.ffms2.Source(source="F:/TESTCL~1/TEST-A~1.AVI",cachefile="H:/Output/avi_54a4199c1a3d3b1476ea1d15dc267332_4827.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg")
# Making sure input color range is set to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# Color Adjustment
clip = core.std.Levels(clip=clip, gamma=1.50)
# Output
clip.set_output()
combined.vpy:
# Imports
import os
import sys
import vapoursynth as vs
core = vs.get_core()

scriptPath = 'h:/Output'
sys.path.append(os.path.abspath(scriptPath))

#import script A (h:/Output/scriptA.py)
import scriptA
original = vs.get_output()
#import script B (h:/Output/scriptB.py)
import scriptB
clip = vs.get_output()
# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHorizontal([original,clip])
# Output
stacked.set_output()
(still looking for a way to do this without changing scriptA and scriptB, but curious how this works)

fails with:
Failed to evaluate the script:
Python exception: 0

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 12, in <module>
original = vs.get_output()
File "src\cython\vapoursynth.pyx", line 179, in vapoursynth.get_output (src\cython\vapoursynth.c:6257)
KeyError: 0
No clue why this happens. :(

------------------
Correction seems like there was some cache which caused this, it already crashes with:
Failed to evaluate the script:
Python exception: invalid syntax (scriptB.py, line 6)

Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1830, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:36860)
File "H:\Output\combined.vpy", line 14, in <module>
import scriptB
File "h:\Output\scriptB.py", line 6
if not hasattr(core, 'ffms2')
^
SyntaxError: invalid syntax
, so that call needs to look like another way. :)


Cu Selur

1. Just catch the exception ffs
2. It's <current year> so autoload or die

DJATOM
9th December 2017, 14:22
I'm using it to load videos with DGDecodeNV (that's the fastest video decoding method available on my PC), so my example below:
from vapoursynth import core

def DGSource(*args):
if not hasattr(core.avs, 'DGSource'):
core.avs.LoadPlugin(r'D:\VS\AVSPlugins\DGDecodeNV.dll')
return core.avs.DGSource(args)

Selur
9th December 2017, 14:32
Just catch the exception ffs
Changing scriptB to:
# Imports
import sys
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
try:
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")
except: # catch all exceptions
a = 1

# Loading F:\TestClips&Co\Test-AC3-5.1.avi using FFMS2
clip = core.ffms2.Source(source="F:/TESTCL~1/TEST-A~1.AVI",cachefile="H:/Output/avi_54a4199c1a3d3b1476ea1d15dc267332_4827.ffindex",format=vs.YUV420P8,alpha=False)
# making sure input color matrix is set as 470bg
clip = core.resize.Point(clip, matrix_in_s="470bg")
# Making sure input color range is set to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# Color Adjustment
clip = core.std.Levels(clip=clip, gamma=1.50)
# Output
clip.set_output()
Seems to work.
Using 'except ffs:' instead of 'except:' give me 'Python exception: name 'ffs' is not defined', so better catch all exceptions since 'ffs' doesn't seem to be the name of the exception,..

Using:
if not hasattr(core.ffms2, 'Source'):
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")
Also works. :)

-> Thanks for that, but the main problem remains: How to load external scripts as clips without modifying them?

Current solution would require to:
1. copy scripts to a temp-folder and change extension to .py
2. extend path to temp-folder (only needed when using portable Python)
3. adjusting scripts to avoid double plugin loading

Cu Selur

Selur
9th December 2017, 15:56
Okay, the whole copying and renaming is not needed when using SourceFileLoader:
# Imports
import vapoursynth as vs
core = vs.get_core()

from importlib.machinery import SourceFileLoader
#import script A (h:/Output/scriptA.py)
SourceFileLoader('original', 'h:/Output/scriptA.vpy').load_module()
original = vs.get_output()

#import script B (h:/Output/scriptB.vpy)
SourceFileLoader('clip', 'h:/Output/scriptB.vpy').load_module()
clip = vs.get_output()

# processing
if original.format.id != clip.format.id:
original = core.resize.Bicubic(original, format=clip.format.id)
stacked = core.std.StackHoarizontal([original,clip])
# Output
stacked.set_output()

Which I personally prefer over adding random paths to sys.path and having to rename files.

Adjusting the source to avoid double loading is still needed,...
if not hasattr(core, 'ffms2'):
core.std.LoadPlugin(path="G:/Hybrid/vsfilters/SourceFilter/FFMS2/ffms2.dll")
(similar calls for all LoadPlugin-calls since LoadPlugin throws an error when trying to load a previously loaded plugin)

So in case LoadPlugin could be adjusted to not throw an error when trying to load an already loaded plugin my problem would be solved.
Since this is probably not happening any time soon: Is there another way around this?

Cu Selur