Skip to content

Instantly share code, notes, and snippets.

@vdcrim
Last active December 19, 2015 03:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vdcrim/5891445 to your computer and use it in GitHub Desktop.
Save vdcrim/5891445 to your computer and use it in GitHub Desktop.
Incomplete and not very well thought out Python 2.7 bindings for the VapourSynth C API, just for playing around
# coding: utf8
# Python 2.7 bindings for the VapourSynth C API
# last updated: VapourSynth R19
from __future__ import print_function
import sys
import os
import os.path
from collections import Iterable
import subprocess
from ctypes import *
# Misc
try:
basestring
except NameError:
basestring = (bytes, str)
def get_python33_directory():
which = 'where' if os.name == 'nt' else 'which'
for name in ('python3', 'python3.3', 'python33', 'python'):
p = subprocess.Popen([which, name], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if not p.wait():
return os.path.dirname(p.stdout.read().decode(sys.stdin.encoding).
splitlines()[0])
''' On Windows the Registry should be used instead
HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.3\InstallPath
HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\3.3\InstallPath
HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Python\PythonCore\3.3\InstallPath
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Python\PythonCore\3.3\InstallPath
'''
class PrintableStructure(Structure):
def __repr__(self):
s = type(self).__name__ + '('
for field in self._fields_:
if 'c_char' in str(field[1]) or 'c_wchar' in str(field[1]):
value = '"{0}"'.format(getattr(self, field[0]))
else:
value = getattr(self, field[0])
s = s + '{0}={1}, '.format(field[0], value)
return s[:-2] + ')'
def __str__(self):
s = ''
for field in self._fields_:
s = s + '{0}={1}\n'.format(field[0], getattr(self, field[0]))
return s
# Load libraries
# Add the site-packages directory to PATH on Windows, or a directory passed
# as a command line argument if the module is called as a script
_vs_dir = None
_python3_dir = get_python33_directory()
if _python3_dir:
print('Python 3 directory:', repr(_python3_dir))
if os.name == 'nt':
_vs_dir = os.path.join(_python3_dir, 'Lib\site-packages')
if __name__ == '__main__':
if len(sys.argv) > 1:
_vs_dir = sys.argv[1]
if sys.version_info[0] >= 3:
_vs_dir = os.fsencode(_vs_dir)
_vs_dir = _vs_dir.decode(sys.stdin.encoding)
if _vs_dir and os.path.isdir(_vs_dir):
os.environ['PATH'] += os.pathsep + _vs_dir
# Awful work-around for a crash with vsscript - sys.path is populated
# from the calling Python version, not from Python 3
if _python3_dir:
os.environ['PYTHONHOME'] = _python3_dir
# Finally load the libraries
if os.name == 'nt':
_vs = windll.vapoursynth
_vsscript = windll.vsscript
_FUNCTYPE = WINFUNCTYPE
else:
_vs = cdll.vapoursynth
_vsscript = cdll.vsscript
_FUNCTYPE = CFUNCTYPE
# VapourSynth.h
API_VERSION = 3
class _API(Structure):
pass
_getVapourSynthAPI = _vs.getVapourSynthAPI
_getVapourSynthAPI.restype = POINTER(_API)
# ColorFamily enum
# all planar formats
cmGray = 1000000
cmRGB = 2000000
cmYUV = 3000000
cmYCoCg = 4000000
# special for compatibility
cmCompat = 9000000
# SampleType enum
stInteger = 0
stFloat = 1
# PresetFormat enum
# The +10 is so people won't be using the constants interchangably "by accident"
pfNone = 0
pfGray8 = cmGray + 10
pfGray16 = pfGray8 + 1
pfGrayH = pfGray16 + 1
pfGrayS = pfGrayH + 1
pfYUV420P8 = cmYUV + 10
pfYUV422P8 = pfYUV420P8 + 1
pfYUV444P8 = pfYUV422P8 + 1
pfYUV410P8 = pfYUV444P8 + 1
pfYUV411P8 = pfYUV410P8 + 1
pfYUV440P8 = pfYUV411P8 + 1
pfYUV420P9 = pfYUV440P8 + 1
pfYUV422P9 = pfYUV420P9 + 1
pfYUV444P9 = pfYUV422P9 + 1
pfYUV420P10 = pfYUV444P9 + 1
pfYUV422P10 = pfYUV420P10 + 1
pfYUV444P10 = pfYUV422P10 + 1
pfYUV420P16 = pfYUV444P10 + 1
pfYUV422P16 = pfYUV420P16 + 1
pfYUV444P16 = pfYUV422P16 + 1
pfYUV444PH = pfYUV444P16 + 1
pfYUV444PS = pfYUV444PH + 1
pfRGB24 = cmRGB + 10
pfRGB27 = pfRGB24 + 1
pfRGB30 = pfRGB27 + 1
pfRGB48 = pfRGB30 + 1
pfRGBH = pfRGB48 + 1
pfRGBS = pfRGBH + 1
# special for compatibility, if you implement these in any filter I'll personally kill you
# I'll also change their ids around to break your stuff regularly
pfCompatBGR32 = cmCompat + 10
pfCompatYUY2 = pfCompatBGR32 + 1
# FilterMode enum
fmParallel = 100 # completely parallel execution
fmParallelRequests = 200 # for filters that are serial in nature but can request one or more frames they need in advance
fmUnordered = 300 # for filters that modify their internal state every request
fmSerial = 400 # for source filters and compatibility with other filtering architectures
class Format(PrintableStructure):
_fields_ = [
("name", c_char * 32),
("id", c_int),
("colorFamily", c_int), # see ColorFamily
("sampleType", c_int), # see SampleType
("bitsPerSample", c_int), # number of significant bits
("bytesPerSample", c_int), # actual storage is always in a power of 2 and the smallest possible that can fit the number of bits used per sample
("subSamplingW", c_int), # log2 subsampling factor, applied to second and third plane
("subSamplingH", c_int),
("numPlanes", c_int), # implicit from colorFamily
]
# NodeFlags enum
nfNoCache = 1
# GetPropErrors enum
peUnset = 1
peType = 2
peIndex = 4
# PropAppendMode enum
paReplace = 0
paAppend = 1
paTouch = 2
class CoreInfo(PrintableStructure):
_fields_ = [
("versionString", c_char_p),
("core", c_int),
("api", c_int),
("numThreads", c_int),
("maxFramebufferSize", c_int64),
("usedFramebufferSize", c_int64),
]
class VideoInfo(PrintableStructure):
_fields_ = [
("format", POINTER(Format)),
("fpsNum", c_int64),
("fpsDen", c_int64),
("width", c_int),
("height", c_int),
("numFrames", c_int),
("flags", c_int),
]
# ActivationReason enum
arInitial = 0
arFrameReady = 1
arAllFramesReady = 2
arError = -1
# MessageType enum
mtDebug = 0
mtWarnin = 1
mtCritical = 2
mtFatal = mtCritical + 1
# core functions
_createCore = _FUNCTYPE(c_void_p, c_int)
_freeCore = _FUNCTYPE(None, c_void_p)
_getCoreInfo = _FUNCTYPE(POINTER(CoreInfo), c_void_p)
# function/filter
_publicFunction = _FUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_void_p, _API)
_freeFuncData = _FUNCTYPE(None, c_void_p)
_filterInit = _FUNCTYPE(None, c_void_p, c_void_p, POINTER(c_void_p), c_void_p, c_void_p, _API)
_filterGetFrame = _FUNCTYPE(c_void_p, c_int, c_int, POINTER(c_void_p), POINTER(c_void_p), c_void_p, c_void_p, _API)
_getOutputIndex = _FUNCTYPE(c_int, c_void_p)
_filterFree = _FUNCTYPE(None, c_void_p, c_void_p, _API)
_registerFunction = _FUNCTYPE(None, c_char_p, c_char_p, _publicFunction, c_void_p, c_void_p)
_createFilter = _FUNCTYPE(None, c_void_p, c_void_p, c_char_p, _filterInit, _filterGetFrame, _filterFree, c_int, c_int, c_void_p, c_void_p)
_invoke = _FUNCTYPE(c_void_p, c_void_p, c_char_p, c_void_p)
_setError = _FUNCTYPE(None, c_void_p, c_char_p)
_getError = _FUNCTYPE(c_char_p, c_void_p)
_setFilterError = _FUNCTYPE(None, c_char_p, c_void_p)
_getFormatPreset = _FUNCTYPE(Format, c_int, c_void_p)
_registerFormat = _FUNCTYPE(Format, c_int, c_int, c_int, c_int, c_int, c_void_p)
# frame and clip handling
_frameDoneCallback = _FUNCTYPE(None, c_void_p, c_void_p, c_int, c_void_p, c_char_p)
_getFrameAsync = _FUNCTYPE(None, c_int, c_void_p, _frameDoneCallback, c_void_p)
_getFrame = _FUNCTYPE(c_void_p, c_int, c_void_p, c_char_p, c_int)
_requestFrameFilter = _FUNCTYPE(None, c_int, c_void_p, c_void_p)
_getFrameFilter = _FUNCTYPE(c_void_p, c_int, c_void_p, c_void_p)
_cloneFrameRef= _FUNCTYPE(c_void_p, c_void_p)
_cloneNodeRef = _FUNCTYPE(c_void_p, c_void_p)
_cloneFuncRef = _FUNCTYPE(c_void_p, c_void_p)
_freeFrame = _FUNCTYPE(None, c_void_p)
_freeNode = _FUNCTYPE(None, c_void_p)
_freeFunc = _FUNCTYPE(None, c_void_p)
_newVideoFrame = _FUNCTYPE(c_void_p, Format, c_int, c_int, c_void_p, c_void_p)
_newVideoFrame2 = _FUNCTYPE(c_void_p, Format, c_int, c_int, c_void_p, POINTER(c_int), c_void_p, c_void_p)
_copyFrame = _FUNCTYPE(c_void_p, c_void_p, c_void_p)
_copyFrameProps = _FUNCTYPE(None, c_void_p, c_void_p, c_void_p)
_getStride = _FUNCTYPE(c_int, c_void_p, c_int)
_getReadPtr = _FUNCTYPE(c_uint8, c_void_p, c_int)
_getWritePtr = _FUNCTYPE(c_uint8, c_void_p, c_int)
# property access
_getVideoInfo = _FUNCTYPE(POINTER(VideoInfo), c_void_p)
_setVideoInfo = _FUNCTYPE(None, VideoInfo, c_int, c_void_p)
_getFrameFormat = _FUNCTYPE(POINTER(Format), c_void_p)
_getFrameWidth = _FUNCTYPE(c_int, c_void_p, c_int)
_getFrameHeight = _FUNCTYPE(c_int, c_void_p, c_int)
_getFramePropsRO = _FUNCTYPE(c_void_p, c_void_p)
_getFramePropsRW = _FUNCTYPE(c_void_p, c_void_p)
_propNumKeys = _FUNCTYPE(c_int, c_void_p)
_propGetKey = _FUNCTYPE(c_char_p, c_void_p, c_int)
_propNumElements = _FUNCTYPE(c_int, c_void_p, c_char_p)
_propGetType = _FUNCTYPE(c_char, c_void_p, c_char_p)
_createMap = _FUNCTYPE(c_void_p)
_freeMap = _FUNCTYPE(None, c_void_p)
_clearMap = _FUNCTYPE(None, c_void_p)
_propGetInt = _FUNCTYPE(c_int64, c_void_p, c_char_p, c_int, POINTER(c_int))
_propGetFloat = _FUNCTYPE(c_double, c_void_p, c_char_p, c_int, POINTER(c_int))
_propGetData = _FUNCTYPE(c_char_p, c_void_p, c_char_p, c_int, POINTER(c_int))
_propGetDataSize = _FUNCTYPE(c_int, c_void_p, c_char_p, c_int, POINTER(c_int))
_propGetNode = _FUNCTYPE(c_void_p, c_void_p, c_char_p, c_int, POINTER(c_int))
_propGetFrame = _FUNCTYPE(c_void_p, c_void_p, c_char_p, c_int, POINTER(c_int))
_propGetFunc = _FUNCTYPE(c_void_p, c_void_p, c_char_p, c_int, POINTER(c_int))
_propDeleteKey = _FUNCTYPE(c_int, c_void_p, c_char_p)
_propSetInt = _FUNCTYPE(c_int, c_void_p, c_char_p, c_int, c_int)
_propSetFloat = _FUNCTYPE(c_int, c_void_p, c_char_p, c_double, c_int)
_propSetData = _FUNCTYPE(c_int, c_void_p, c_char_p, c_char_p, c_int, c_int)
_propSetNode = _FUNCTYPE(c_int, c_void_p, c_char_p, c_void_p, c_int)
_propSetFrame = _FUNCTYPE(c_int, c_void_p, c_char_p, c_void_p, c_int)
_propSetFunc = _FUNCTYPE(c_int, c_void_p, c_char_p, c_void_p, c_int)
# mixed
_configPlugin = _FUNCTYPE(None, c_char_p, c_char_p, c_char_p, c_int, c_int, c_void_p)
_initPlugin = _FUNCTYPE(None, _configPlugin, _registerFunction, c_void_p)
_getPluginId = _FUNCTYPE(c_void_p, c_char_p, c_void_p)
_getPluginNs = _FUNCTYPE(c_void_p, c_char_p, c_void_p)
_getPlugins = _FUNCTYPE(c_void_p, c_void_p)
_getFunctions = _FUNCTYPE(c_void_p, c_void_p)
_callFunc = _FUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_void_p, _API)
_createFunc = _FUNCTYPE(c_void_p, _publicFunction, c_void_p, _freeFuncData)
_queryCompletedFrame = _FUNCTYPE(None, c_void_p, POINTER(c_int), c_void_p)
_releaseFrameEarly = _FUNCTYPE(None, POINTER(c_void_p), c_int, c_void_p)
_setMaxCacheSize = _FUNCTYPE(c_int64, c_int64, c_void_p)
_MessageHandler = _FUNCTYPE(None, c_int, c_char_p)
_setMessageHandler = _FUNCTYPE(None, c_void_p)
_API._fields_ = [
("createCore", _createCore),
("freeCore", _freeCore),
("getCoreInfo", _getCoreInfo),
("cloneFrameRef", _cloneFrameRef),
("cloneNodeRef", _cloneNodeRef),
("cloneFuncRef", _cloneFuncRef),
("freeFrame", _freeFrame),
("freeNode", _freeNode),
("freeFunc", _freeFunc),
("newVideoFrame", _newVideoFrame),
("copyFrame", _copyFrame),
("copyFrameProps", _copyFrameProps),
("registerFunction", _registerFunction),
("getPluginId", _getPluginId),
("getPluginNs", _getPluginNs),
("getPlugins", _getPlugins),
("getFunctions", _getFunctions),
("createFilter", _createFilter), # do never use inside a filter's getframe function
("setError", _setError), # use to signal errors outside filter getframe functions
("getError", _getError), # use to query errors, returns 0 if no error
("setFilterError", _setFilterError), # use to signal errors in the filter getframe function
("invoke", _invoke), # may not be used inside a filter's getframe method
("getFormatPreset", _getFormatPreset), #threadsafe
("registerFormat", _registerFormat), # threadsafe
("getFrame", _getFrame), # do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor
("getFrameAsync", _getFrameAsync), # do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor
("getFrameFilter", _getFrameFilter), # only use inside a filter's getframe function
("requestFrameFilter", _requestFrameFilter), # only use inside a filter's getframe function
("queryCompletedFrame", _queryCompletedFrame), # only use inside a filter's getframe function
("releaseFrameEarly", _releaseFrameEarly), # only use inside a filter's getframe function
("getStride", _getStride),
("getReadPtr", _getReadPtr),
("getWritePtr", _getWritePtr),
("createFunc", _createFunc),
("callFunc", _callFunc),
# property access functions
("createMap", _createMap),
("freeMap", _freeMap),
("clearMap", _clearMap),
("getVideoInfo", _getVideoInfo),
("setVideoInfo", _setVideoInfo),
("getFrameFormat", _getFrameFormat),
("getFrameWidth", _getFrameWidth),
("getFrameHeight", _getFrameHeight),
("getFramePropsRO", _getFramePropsRO),
("getFramePropsRW", _getFramePropsRW),
("propNumKeys", _propNumKeys),
("propGetKey", _propGetKey),
("propNumElements", _propNumElements),
("propGetType", _propGetType),
("propGetInt", _propGetInt),
("propGetFloat", _propGetFloat),
("propGetData", _propGetData),
("propGetDataSize", _propGetDataSize),
("propGetNode", _propGetNode),
("propGetFrame", _propGetFrame),
("propGetFunc", _propGetFunc),
("propDeleteKey", _propDeleteKey),
("propSetInt", _propSetInt),
("propSetFloat", _propSetFloat),
("propSetData", _propSetData),
("propSetNode", _propSetNode),
("propSetFrame", _propSetFrame),
("propSetFunc", _propSetFunc),
("setMaxCacheSize", _setMaxCacheSize),
("getOutputIndex", _getOutputIndex),
("newVideoFrame2", _newVideoFrame2),
("setMessageHandler", _setMessageHandler),
]
class VapourSynthAPI():
def __init__(self, version=None, api=None):
if api is None:
self.api = _getVapourSynthAPI(version)
else:
self.api = api
def create_core(self, threads=0):
return self.api.contents.createCore(threads)
def free_core(self, core):
self.api.contents.freeCore(core)
def get_core_info(self, core):
return self.api.contents.getCoreInfo(core).contents
def create_map(self):
return self.api.contents.createMap()
def prop_num_keys(self, map):
return self.api.contents.propNumKeys(map)
def prop_get_key(self, map, index):
return self.api.contents.propGetKey(map, index)
def prop_num_elements(self, map, key):
return self.api.contents.propNumElements(map, key)
def prop_get_type(self, map, key):
return self.api.contents.propGetType(map, key)
def prop_get_node(self, map, key, index=0):
error = c_int()
node = self.api.contents.propGetNode(map, key, index, byref(error))
return node, error.value
def prop_get_data(self, map, key, index=0):
error = c_int()
string = self.api.contents.propGetData(map, key, index, byref(error))
return string, error.value
def prop_set_int(self, map, key, int, append=False):
return self.api.contents.propSetInt(map, key, int, append)
def prop_set_data(self, map, key, string, append=False):
return self.api.contents.propSetData(map, key, string, len(string), append)
def get_plugins(self, core):
return self.api.contents.getPlugins(core)
def get_plugin_id(self, id, core):
return self.api.contents.getPluginId(id, core)
def get_plugin_ns(self, ns, core):
return self.api.contents.getPluginNs(ns, core)
def get_functions(self, plugin):
return self.api.contents.getFunctions(plugin)
def invoke(self, plugin, function_name, args=None):
if args is None:
args = self.create_map()
return self.api.contents.invoke(plugin, function_name, args)
def get_video_info(self, node):
return self.api.contents.getVideoInfo(node).contents
def get_frame(self, n, node, error_msg=b''):
return self.api.contents.getFrame(n, node, error_msg, len(error_msg))
def get_frame_format(self, frame_ref):
return self.api.contents.getFrameFormat(frame_ref)
def get_stride(self, frame_ref, plane=0):
return self.api.contents.getStride(frame_ref, plane)
def get_frame_width(self, frame_ref, plane=0):
return self.api.contents.getFrameWidth(frame_ref, plane)
def get_frame_height(self, frame_ref, plane=0):
return self.api.contents.getFrameHeight(frame_ref, plane)
def get_read_ptr(self, frame_ref, plane=0):
return self.api.contents.getReadPtr(frame_ref, plane)
def free_frame(self, frame_ref):
self.api.contents.freeFrame(frame_ref)
def free_node(self, node):
self.api.contents.freeNode(node)
def get_error(self, map):
self.api.contents.getError(map)
# VSScript.h
# EvalFlags enum
efSetWorkingDir = 1
# Initialize the available scripting runtimes, returns zero on failure
_vsscript_init = _vsscript.vsscript_init
_vsscript_init.argtypes = None
_vsscript_init.restype = c_int
# Free all scripting runtimes
_vsscript_finalize = _vsscript.vsscript_finalize
_vsscript_finalize.argtypes = None
_vsscript_finalize.restype = c_int
# Pass a pointer to a null handle to create a new one
# The values returned by the query functions are only valid during the lifetime of the VSScript
# scriptFilename is if the error message should reference a certain file, NULL allowed in vsscript_evaluateScript()
# core is to pass in an already created instance so that mixed environments can be used,
# If efSetWorkingDir is passed to flags the current working directory will be changed to the path of the script
# note that if scriptFilename is NULL in vsscript_evaluateScript() then __file__ won't be set and the working directory won't be changed
# Set efSetWorkingDir to get the default behavior
# NULL creates a new core that can be fetched with vsscript_getCore() later OR implicitly uses the one associated with an already existing handle when passed
_vsscript_evaluateScript = _vsscript.vsscript_evaluateScript
_vsscript_evaluateScript.argtypes = [POINTER(c_void_p), c_char_p, c_char_p, c_int]
_vsscript_evaluateScript.restype = c_int
# Convenience version of the above function that loads the script from a file
_vsscript_evaluateFile = _vsscript.vsscript_evaluateFile
_vsscript_evaluateFile.argtypes = [POINTER(c_void_p), c_char_p, c_int]
_vsscript_evaluateFile.restype = c_int
_vsscript_freeScript = _vsscript.vsscript_freeScript
_vsscript_freeScript.argtypes = [c_void_p]
_vsscript_freeScript.restype = None
_vsscript_getError = _vsscript.vsscript_getError
_vsscript_getError.argtypes = [c_void_p]
_vsscript_getError.restype = c_char_p
# The node returned must be freed using freeNode() before calling vsscript_freeScript()
_vsscript_getOutput = _vsscript.vsscript_getOutput
_vsscript_getOutput.argtypes = [c_void_p, c_int]
_vsscript_getOutput.restype = c_void_p
_vsscript_clearOutput = _vsscript.vsscript_clearOutput
_vsscript_clearOutput.argtypes = [c_void_p, c_int]
_vsscript_clearOutput.restype = None
# The core is valid as long as the environment exists
_vsscript_getCore = _vsscript.vsscript_getCore
_vsscript_getCore.argtypes = [c_void_p]
_vsscript_getCore.restype = c_void_p
_vsscript_getVSApi = _vsscript.vsscript_getVSApi
_vsscript_getVSApi.argtypes = None
_vsscript_getVSApi.restype = POINTER(_API)
# Variables names that are not set or not of a convertible type will return an error
_vsscript_getVariable = _vsscript.vsscript_getVariable
_vsscript_getVariable.argtypes = [c_void_p, c_char_p, c_void_p]
_vsscript_getVariable.restype = c_int
_vsscript_setVariable = _vsscript.vsscript_setVariable
_vsscript_setVariable.argtypes = [c_void_p, c_void_p]
_vsscript_setVariable.restype = None
_vsscript_clearVariable = _vsscript.vsscript_clearVariable
_vsscript_clearVariable.argtypes = [c_void_p, c_char_p]
_vsscript_clearVariable.restype = c_int
# Tries to clear everything set in an environment, normally it is better to simply free an environment completely and create a new one
_vsscript_clearEnvironment = _vsscript.vsscript_clearEnvironment
_vsscript_clearEnvironment.argtypes = [c_void_p]
_vsscript_clearEnvironment.restype = None
def init():
"""Initialize the available scripting runtimes
Returns zero on failure"""
return _vsscript_init()
def finalize():
"""Free all scripting runtimes"""
return _vsscript_finalize()
def evaluate_script(script, handle=None, script_filename=None, flags=efSetWorkingDir):
"""Evaluate 'script' string
If 'handle' is None a new one is created
'script_filename' is if the error message should reference a certain file,
None allowed
If efSetWorkingDir is passed to 'flags' the current working directory will
be changed to the path of the script before its evaluation, and changed back
afterwards. This is the default behavior.
Note that if 'script_filename' is None then __file__ won't be set and the
working directory won't be changed
Returns (error code, handle)
"""
if handle is None:
handle = c_void_p()
err = _vsscript_evaluateScript(byref(handle), script, script_filename, flags)
return err, handle
def evaluate_file(script_filename, handle=None, flags=efSetWorkingDir):
"""Convenience version of 'evaluate_script' that loads the script from a file"""
if handle is None:
handle = c_void_p()
err = _vsscript_evaluateFile(byref(handle), script_filename, flags)
return err, handle
def free_script(handle):
"""Free the script associated to 'handle'"""
_vsscript_freeScript(handle)
def get_error(handle):
"""Return the error string, if any"""
return _vsscript_getError(handle)
def get_output(handle, index=0):
"""Returns the output (NodeRef) from 'handle'"""
return _vsscript_getOutput(handle, index)
def clear_output(handle, index):
"""Clear the output 'index' from 'handle'"""
_vsscript_clearOutput(handle, index)
def get_core(handle):
"""Retrieve the Core object from 'handle'"""
return _vsscript_getCore(handle)
def get_VS_API():
"""Retrieve an API object
Must be called after init()
"""
return VapourSynthAPI(api=_vsscript_getVSApi())
def get_variable(handle, name):
"""Retrieve the variable 'name'
Return an error if the variable is not set
"""
map = api.create_map()
err = _vsscript_getVariable(handle, name, map)
return err, map
def set_variable(handle, vars):
"""Set variables from a 'vars' dict"""
_vsscript_setVariable(handle, _VSMap_from_map(vars))
def clear_variable(handle, name):
"""Clear the variable 'name'
Return an error if the variable is not set
"""
return _vsscript_clearVariable(handle, name)
def clear_environment(handle):
"""Clear 'handle's environment"""
_vsscript_clearEnvironment(handle)
def _VSMap_from_map(py_map):
map = api.create_map()
for key, value in py_map.items():
if not isinstance(value, Iterable) or isinstance(value, basestring):
value = value,
for item in value:
api.prop_set_data(map, key, item, append=True)
return map
# VSHelper.h
def is_constant_format(vi):
"""convenience function for checking if the format never changes between frames"""
return vi.height > 0 and vi.width > 0 and vi.format
def is_same_format(v1, v2):
"""convenience function to check for if two clips have the same format(unknown/changeable will be considered the same too)"""
return v1.height == v2.height and v1.width == v2.width and v1.format == v2.format
def muldiv_rational(num, den, mul, div):
"""multiplies and divides a rational number, such as a frame duration, in place and reduces the result"""
num *= mul
den *= div
a = num
b = den
while b != 0:
a, b = b, a % b
if a < 0:
a = -a
return num / a, den / a
def int64_to_ints(i):
"""converts an int64 to int with saturation, useful to silence warnings when reading int properties among other things"""
int_max = sizeof(c_int) * 8 - 1
if(i > int_max):
return int_max
elif(i < 0):
return 0
return i
def vs_bitblt(dstp, dst_stride, srcp, src_stride, row_size, height):
if height > 0:
if src_stride == dst_stride and src_stride == row_size:
memmove(dstp, srcp, row_size * height)
else:
for i in range(height):
memmove(dstp, srcp, row_size)
srcp += src_stride
dstp += dst_stride
def are_valid_dimensions(fi, width, height):
"""check if the frame dimensions are valid for a given format
returns non-zero for valid width and height"""
return not(width % (1 << fi.subSamplingW) or height % (1 << fi.subSamplingH))
if __name__ == '__main__':
# get version and functions, invoke BlankClip and show video info
api = VapourSynthAPI(API_VERSION)
core = api.create_core()
print(repr(api.get_core_info(core)))
plugins = api.get_plugins(core)
for index in range(api.prop_num_keys(plugins)):
plugin_key = api.prop_get_key(plugins, index)
print(plugin_key)
functions = api.get_functions(api.get_plugin_id(plugin_key, core))
for index in range(api.prop_num_keys(functions)):
function_key = api.prop_get_key(functions, index)
for index in range(api.prop_num_elements(functions, function_key)):
print(b' ' + api.prop_get_data(functions, function_key, index)[0][:74])
clip_map = api.invoke(api.get_plugin_ns(b'std', core), b'BlankClip')
node, err = api.prop_get_node(clip_map, b'clip')
print(repr(api.get_video_info(node)))
print(repr(api.get_video_info(node).format.contents))
api.free_node(node)
api.free_core(core)
# evaluate script (BlankClip again)
script_text = br"""
import sys
try: # add the script filename, when passed to evaluate_script
path = sys.path + ['vpy file: ' + __file__]
except NameError:
path = sys.path + ['__file__ not defined']
import vapoursynth as vs
core = vs.get_core()
clip = core.std.BlankClip()
#core.std.LoadPlugin(r'C:\Program Files (x86)\AviSynth 2.5\plugins\ffms2.dll')
#clip = core.ffms2.Source('test.avi') # test relative paths
clip.set_output()
"""
print('\ninit', init())
api = get_VS_API()
if 1:
err, handle = evaluate_script(script_text)
else:
alt_dir = r'' # test relative paths
vpf_path = os.path.join(alt_dir, 'test.vpy')
with open(vpf_path, 'wb') as vpy:
vpy.write(script_text)
err, handle = evaluate_file(vpf_path.encode('utf8'))
if err:
print('error {0} evaluating script'.format(get_error(handle)))
else:
# show video info
node = get_output(handle)
print(repr(api.get_video_info(node)))
print(repr(api.get_video_info(node).format.contents))
# check setting and getting variables. retrieve sys.path
#err = set_variable(handle, {b'path': [b'123', b'678', u'ñ'.encode('utf8')], b'abc': b'cba'})
err, var_map = get_variable(handle, b'path')
if err:
print("error {0} retrieving 'sys.path'".format(err))
else:
for index in range(api.prop_num_keys(var_map)):
var_key = api.prop_get_key(var_map, index)
print("index {0}, key '{1}', type '{2}'".format(
index, var_key, api.prop_get_type(var_map, var_key)))
for index in range(api.prop_num_elements(var_map, var_key)):
print(api.prop_get_data(var_map, var_key, index)[0].
decode('utf8').encode(sys.stdout.encoding))
# get one frame and check again format
frame_ref = api.get_frame(5, node)
print('stride: {0}, width: {1}, height: {2}'.format(
api.get_stride(frame_ref), api.get_frame_width(frame_ref),
api.get_frame_height(frame_ref)))
print(repr(api.get_frame_format(frame_ref).contents))
api.get_read_ptr(frame_ref)
api.free_frame(frame_ref)
api.free_node(node)
free_script(handle)
print('finalize', finalize())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment