View Full Version : Avisynthesizer_Mod 20 Feb 2014
StainlessS
30th December 2012, 11:03
A SendTo App that allows Windows Explorer selection of video files and fills in a user supplied Template with the filenames.
Can concatenate (join/splice) selected files (default as original non mod version) and create a single output AVS file OR,
batch create multiple AVS files, one for each input source file (MOD version only).
Has a GUI to select required template and sort input files if multiple input files selected.
Was not altogether happy with this handy little app so I changed it a little.
Changes made to Avisynthesizer by StainlessS.
Uses "___FILE___" (thats 3 underscore either side) instead of "%f" which can be mistaken for float spec in eg String() function.
Converted to using "++" aligned splice instead of "+" unaligned splice.
Each file command output on it's own line with a line concatenation "\" backslash.
Does NOT auto install, copy dir somewhere and execute "Install_SendTo.Cmd" to install (can then right click files and "sendTo").
"UnInstall_SendTo.Cmd" to uninstall.
------------------
7 Aug 2013, Added ___FILECNT___
___FILECNT___ Replaced with number of filenames given as arg to Avisynthesizer_Mod,
can be used anywhere in file, but there is no further processing of that line, ie
not on same line as ___FILE___ replacement.
------------------
20 Feb 2014, Added Batch AVS creation mode.
If template has a repeating section {enclosed in square brackets eg [AviSource("___FILE___")]} then will
use the standard mode, creating a single file with multiple sources concatenated.
If template DOES NOT have a repeating section {not enclosed in square backets eg AviSource("___FILE___")}
then will create multiple AVS files, one for each source file.
---------------------------------------------------------------------
Author's email: Warren Young <wdyoung@acm.org>
AVISynthesizer home: http://www.cyberport.com/~tangent/video/asynther.html
----------------------------------------------------------------------
------------- STANDARD MODE (multiple files concatenated) ------------
----------------------------------------------------------------------
Here a standard Mode template
>>>>>>>>>>> TEMPLATE START >>>>>>>>>>>>>>>
#ASYNTHER Simple AVISource reader
# Above line (preceded by '#ASYNTHER') shows as "Simple AVISource reader" in the Avisynthesizer_Mod GUI.
FileCount = ___FILECNT___ # FileCount will be set to the number of files given by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
# Below enclosed in square brackets, so is STANDARD Mode, multiple files are concatenated.
[AVISource("___FILE___")]
<<<<<<<<<<< TEMPLATE END <<<<<<<<<<<<<<<<<
Where sending filenames "1.avi", "2.avi", and "3.avi" to above "Simple AVISource reader" Avisynthesizer_Mod template, will generate script like
>>>>>>>>>>> SCRIPT OUTPUT >>>>>>>>>>>>>>>
#ASYNTHER Simple AVISource reader
# Above line (preceded by '#ASYNTHER') shows as "Simple AVISource reader" in the Avisynthesizer_Mod GUI.
FileCount = 3 # FileCount will be set to the number of files supplied by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
# Below enclosed in square brackets, so is STANDARD Mode, multiple files are concatenated.
AVISource("C:\Z\1.avi") ++ \
AVISource("C:\Z\2.avi") ++ \
AVISource("C:\Z\3.avi")
<<<<<<<<<<< END SCRIPT OUTPUT <<<<<<<<<<<
----------------------------------------------------------------------
----------------------------------------------------------------------
Another Standard Mode template
>>>>>>>>>>> TEMPLATE START >>>>>>>>>>>>>>>
#ASYNTHER TEST
# Above line (preceded by '#ASYNTHER') shows as "TEST" in the Avisynthesizer_Mod GUI.
FileCount = ___FILECNT___ # FileCount will be set to the number of files supplied by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
[GetFile("___FILE___")]
Return last
Function GetFile(string s) {
# could do clever stuff in here to decide on which source filter to use and audio stuff
DirectShowSource(s).Trim(0,0) # Trim(0,0), chop/pad audio to same length as video.
BilinearResize(480, 480).ConvertToYUY2.SpatialSoften(5, 2, 3)
}
<<<<<<<<<<< TEMPLATE END <<<<<<<<<<<<<<<<<
Where sending filenames "1.avi", "2.avi", and "3.avi" to above "TEST" Avisynthesizer_Mod template, will generate script like
>>>>>>>>>>> SCRIPT OUTPUT >>>>>>>>>>>>>>>
#ASYNTHER TEST
# Above line (preceded by '#ASYNTHER') shows as "TEST" in the Avisynthesizer_Mod GUI.
FileCount = 3 # FileCount will be set to the number of files supplied by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
GetFile("C:\Z\1.avi") ++ \
GetFile("C:\Z\2.avi") ++ \
GetFile("C:\Z\3.avi")
Return last
Function GetFile(string s) {
# could do clever stuff in here to decide on which source filter to use and audio stuff
DirectShowSource(s).Trim(0,0) # Trim(0,0), chop/pad audio to same length as video.
BilinearResize(480, 480).ConvertToYUY2.SpatialSoften(5, 2, 3)
}
<<<<<<<<<<< END SCRIPT OUTPUT <<<<<<<<<<<
----------------------------------------------------------------------
--------- BATCH MODE TEMPLATE ----------------------------------------
----------------------------------------------------------------------
Here a Batch Mode template (NOT enclosed in square brackets)
A script will be generated for each file SendTo Avisynthesizer_Mod.
>>>>>>>>>>> TEMPLATE START >>>>>>>>>>>>>>>
#ASYNTHER BATCH-AVISOURCE
# Above line (preceded by '#ASYNTHER') shows as "BATCH-AVISOURCE" in the Avisynthesizer_Mod GUI.
FileCount = ___FILECNT___ # Should always be set to 1 in non-repeating Batch template.
# Below not enclosed in square brackets, so is Non-Repeating ie Batch Mode.
# Batch Mode == Multiple AVS files generated, one for each selected file SendTo Avisynthsizer_Mod.
AVISource("___FILE___")
<<<<<<<<<<< TEMPLATE END <<<<<<<<<<<<<<<<<
1--BATCH-AVISOURCE.avs (where 1.avi, 2.avi, and 3.avi sendTo Avisynthesizer_Mod [Only 1st script shown])
>>>>>>>>>>> SCRIPT OUTPUT >>>>>>>>>>>>>>>
#ASYNTHER BATCH-AVISOURCE
# Above line (preceded by '#ASYNTHER') shows as "BATCH-AVISOURCE" in the Avisynthesizer_Mod GUI.
FileCount = 1 # Should always be set to 1 in non-repeating Batch template.
# Below not enclosed in square brackets, so is Non-Repeating ie Batch Mode.
# Batch Mode == Multiple AVS files generated, one for each selected file SendTo Avisynthsizer_Mod.
AVISource("C:\Z\1.avi")
<<<<<<<<<<< END SCRIPT OUTPUT <<<<<<<<<<<
Contains original source and VS Community 2019 compiler files for easy build.
Original Author's site with original usage: http://tangentsoft.net/video/asynther/
EDIT: Above linked page seems to have been removed (but copy of page included in the zip).
Brief description as webpage removed. Can select clips in Windows Explorer and SendTo Avisynthesizer where it will
create an avs script to concatenate (join together) all selected clips. Modified so that it is also possible to create an individual
avs file for all selected clips (batch creation of avs files). You supply templates to get whatever effect is required.
Alternative page about Avisynthesizer (original version):
http://www.digitalfaq.com/forum/video-conversion/2535-avisynthesizer-build-complete.html
See MediaFire in sig. [UTILITY FOLDER]
or here direct link:- https://www.mediafire.com/file/9b7c792pra0xf1s/Avisynthesizer_Mod_20221115.zip/file
EDIT: Avisynthesizer_Mod is an offshoot of the original Avsynthesizer by Warren Young and nothing to do with SwiftAVS
which seems to masquerade itself as the "New Avisynthesizer", and not in any way similar. (SwiftAVS is on sourceforge
as Avisynthesizer for some inexplicable reason, perhaps there was a name conflict and so he just changed it).
EDIT: Here a demo BATCH script template using TWriteAVI to create lossless AVI and call ffmpeg encoder on result. http://forum.doom9.org/showthread.php?p=1750548#post1750548
Here original home page on Archive.org:- https://web.archive.org/web/20140331084148/http://tangentsoft.net/video/asynther/
And the manual (also available via above link):- https://web.archive.org/web/20130318051724/http://tangentsoft.net/video/asynther/manual.html
https://i.postimg.cc/FHTp3KF0/Avisynthesizer-Mod.jpg (https://postimages.org/)
StainlessS
30th December 2012, 11:26
Also, handy link here:-
Customize the Windows 7 “Send To” Menu Option (http://gigaom.com/mobile/customize-the-windows-7-send-to-menu-option/)
Which also applies to XP. Can create SendTo shortcuts for whatever you like.
StainlessS
7th August 2013, 16:14
Avisynthesizer_Mod 7 Aug 2013, update, see 1st post.
Added ___FILECNT___ insertion marker, inserts count of files given.
StainlessS
13th February 2014, 16:50
Scripts posted here because of this post: http://forum.doom9.org/showthread.php?p=1667897#post1667897
Was not really intending to make public, leastwise not yet.
RoboSplice.avsi
Function IsClose(Float a, Float b, Float threshold) {
threshold=Abs(threshold)
return ((abs(a-b)+threshold) <= threshold*2.0)
}
Function ConvRates(clip c,int "num",int "den",int "Channels",int "SampleRate",int "Bits",bool "Norm") {
c
GScript("""
if((!Defined(num) || !Defined(den)) || (num==0 || den==0)) {num = 0 den = 0}
Channels=Default(Channels,AudioChannels)
SampleRate=Default(SampleRate,AudioRate)
Bits=Default(bits,AudioBits)
Norm=Default(Norm,True)
if(num == FrameRateNumerator && den == FrameRateDenominator) {
RT_Debug("Using Original FrameRate ",String(FrameRate,"%.3f"))
} else {
if(num==0 || den == 0) {
FPS = FrameRate
if (isClose(FPS,29.97,0.015)) {num=30000 den = 1001}
else if (isClose(FPS,23.976,0.012)) {num=24000 den = 1001}
else if (isClose(FPS,11.988,0.006)) {num=12000 den = 1001}
else if (isClose(FPS,30.0,0.5)) {num=30 den = 1}
else if (isClose(FPS,25.0,0.5)) {num=25 den = 1}
else if (isClose(FPS,24.0,0.5)) {num=24 den = 1}
else if (isClose(FPS,18.0,0.5)) {num=18 den = 1}
else if (isClose(FPS,15.0,0.5)) {num=15 den = 1}
else if (isClose(FPS,12.5,0.5)) {num=25 den = 2}
else if (isClose(FPS,12.0,0.5)) {num=12 den = 1}
else {num=FrameRateNumerator den = FrameRateDenominator}
}
if(isClose(Float(num) / Float(den),FrameRate,1.0)) {
AssumeFPS(num,den,sync_audio=true)
RT_Debug("Assuming FrameRate ",String(FrameRate,"%.3f"))
} else {
RT_Debug("Converting FrameRate to",String(Float(num) / Float(den),"%.3f"))
if(false) {
super=MSuper(pel=1)
bvec=MAnalyse(super, isb=true, blksize=16)
fvec=MAnalyse(super, isb=false, blksize=16)
MBlockFps(super, bvec, fvec, num=num,den=den, mode=3)
} else {
super=MSuper(pel=1, hpad=0, vpad=0)
backward_1=MAnalyse(super, chroma=false, isb=true, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
forward_1 =MAnalyse(super, chroma=false, isb=false, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
backward_2 = MRecalculate(super, chroma=false, backward_1, blksize=8, blksizev=8, searchparam=0, search=3)
forward_2 = MRecalculate(super, chroma=false, forward_1, blksize=8, blksizev=8, searchparam=0, search=3)
MBlockFps(super, backward_2, forward_2, num=num, den=den, mode=0)
}
}
}
IsSilent=false
if(!HasAudio) {
RT_Debug("Adding Silent Audio")
Aud=Last.Blankclip(audio_rate=SampleRate,channels=Channels)
IsSilent=true
Audiodub(Aud)
}
if(HasAudio) {
if(Channels == 0 && AudioChannels > 0) {
KillAudio()
RT_Debug("Killing Audio")
} else if(Channels == 1 && AudioChannels > 1) {
ConvertToMono()
RT_Debug("Converting To MONO")
} else if(Channels == 2 && AudioChannels ==1) {
AudioDub(Last,MergeChannels(GetChannel(1),GetChannel(1)))
RT_Debug("Converting To STEREO")
}
if(HasAudio() && Bits != AudioBits) {
if(bits==8) { ConvertAudioTo8bit() }
else if(bits==16) { ConvertAudioTo16bit() }
else if(bits==24) { ConvertAudioTo24bit() }
else if(bits==32) { ConvertAudioTo32bit() }
}
if(HasAudio() && SampleRate != AudioRate) {ResampleAudio(SampleRate) }
if(HasAudio() && Norm && !IsSilent) {
Normalize(0.98)
RT_Debug("NORMALIZING AUDIO")
}
}
""")
Return Trim(0,0)
}
Function DoTrim(clip c) {
c
GScript("""
W=Width % 8 H=Height % 8
Addborders(0,0,W==0?0:8-W,H==0?0:8-h).ConvertToYV12()
if(G_DEBLOCK!=0) {
RT_Debug("DEBLOCK("+String(G_DEBLOCK)+")")
Deblock(G_DEBLOCK)
}
if(G_RPOW2 ||((G_DISPWID>0 && G_DISPWID>Int(Width*Sqrt(2.0)))||(G_DISPHIT>0 && G_DISPHIT>Int(Height*Sqrt(2.0))))) {
RT_Debug("RPOW2")
NNedi3_Rpow2(2)
}
if(G_QBC==true || G_SAMPLES!=0 || G_AL_STRENGTH>0.0 || G_AUTOGAIN) {
RT_Debug("Calling RoboLevels")
RoboLevels(Strength=G_AL_STRENGTH,samples=G_SAMPLES,qbc=G_QBC,QBC_Thresh=G_QBC_THRESH,DEBUG=G_DEBUG,Laced=G_INTERLACED,WMod=4,HMod=4)
if(G_AUTOGAIN) {
RT_Debug("AutoGain")
TMPW=Int(Width /4)*4 # Mod 4 for AutoGain
TMPH=Int(Height/4)*4 # Mod 4 for AutoGain
TMP=Crop(0,0,TMPW,TMPH)
AutoGain(Last,TMP)
}
}
if(G_MCD==0) {
if(G_SIGMA!=0.0 || G_SHARPEN!=0.0) {
RT_Debug("FFT3DFilter")
FFT3DFilter(Sigma=G_SIGMA,Sharpen=G_SHARPEN)
}
} else {
RT_Debug("MCDeGrain")
MCDEGRAIN(G_MCD)
}
ConvRates(num=G_FRNUM,den=G_FRDEN,Channels=G_CHANNELS,SampleRate=G_SAMPLERATE,Bits=G_BITS,norm=G_NORMALIZE)
Global G_FRNUM = FrameRateNumerator
Global G_FRDEN = FrameRateDenominator
Global G_CHANNELS = AudioChannels
Global G_SAMPLERATE = AudioRate
Global G_BITS = AudioBits
if(G_DISPWID!=Width || G_DISPHIT != Height) {
if(G_DISPWID==0 || G_DISPHIT == 0) {
WW=(Width + (4-1)) / 4 * 4
HH=(Height + (4-1)) / 4 * 4
Global G_DISPWID = WW
Global G_DISPHIT = HH
if(WW==Width && HH==Height) {
RT_Debug("Using Original SIZE",String(G_DISPWID),String(G_DISPHIT))
} else {
RT_Debug("Resizing MOD 4",String(G_DISPWID),String(G_DISPHIT))
Spline36Resize(G_DISPWID,G_DISPHIT)
}
} else {
RT_Debug("Resizing to match previous clip",String(G_DISPWID),String(G_DISPHIT))
Spline36Resize(G_DISPWID,G_DISPHIT)
}
}
if(G_MCD!=0) {
if(G_SIGMA!=0.0 || G_SHARPEN!=0.0) {
RT_Debug("FFT3DFilter")
FFT3DFilter(Sigma=G_SIGMA,Sharpen=G_SHARPEN)
}
}
""")
ConvertToYV12()
}
Function GetFile(string s) {
GScript("""
c=0
Ext=LCase(RT_GetFileExtension(s))
RT_Debug("Processing " + s,"for Extension",Ext)
if(Ext==".avi") {
c=AVISource(s)
RT_Debug("AVISOURCE")
}
if(!c.IsClip) {
try {
FFIndex(S) c=AudioDub(FFVideoSource(S), FFAudioSource(S))
RT_Debug("FFMSSOURCE")
} catch(msg) {
try {
c=AudioDub(DSS2(s),DirectshowSource(s).KillVideo)
RT_Debug("DSSSOURCE")
} catch(msg) {
c=DirectShowSource(s)
RT_Debug("DirectShowSource")
}
}
}
W=c.Width % 8 H=c.Height % 8
c=c.Addborders(0,0,W==0?0:8-W,H==0?0:8-h).ConvertToYV12()
""")
return c
}
Function GetTrim(string s) {
Return GetFile(s).DoTrim()
}
RoboLevels.avsi (A hack of a different script)
Function RoboLevels(clip c,float "Strength",int "Samples",float "Ignore",Bool "ALQBC",Bool "QBC",Float "QBC_Thresh",int "X",int "Y",int "W",int "H", \
int "Matrix",bool "PC",bool "DEBUG",bool "Laced", Int "WMod",Int "HMod",bool "Show") {
# Samples a number of frames from source clip and using minimum and maximum luma levels from those samples, auto levels clip.
# Default temporarily auto crop borders and samples the area remaining, or if both ALQBC and QBC == false then samples X,Y,W,H coords instead.
# Can optionally return border cropped clip when QBC==true.
#
# Args:
# Strength, default 0.95 (0.0 -> 1.0). Auto levelling strength.
# Samples, default 32. Number of frames sampled from source clip c.
# Ignore, default 0.2 (0.0 -> 100%). Percentage of dark pixels to ignore when ascertaining YPlaneMin, YPlaneMax (noise).
# ALQBC, default=true. Use temp auto cropped clip coords for auto levels sampling.
# QBC, default false. If true then returns border cropped clip else non cropped.
# QBC_Thresh, default -32.0. Threshold used for border detection. See RT_QueryBorderCrop.
# NOTE, RT_QueryBorderCrop 'massages' DEFAULT THRESH (exactly -32.0) if low samples count or if short clip. Reason being to avoid
# overcropping when insufficient data available for reliable cropping. It is considered better to not crop enough or at all, than
# to overcrop. You can override by simply setting an explicit threshold (+ve) of eg 40.0, or setting a NON-DEFAULT auto thresh (-ve)
# eg -16.0 or -32.1, where YPlaneMin is established for the sampled frames and then abs(thresh) is added to that value which is
# then used as an explicit thresh.
# X,Y,W,H. All default 0, ie full frame. Coords for luma sampling, only used if both ALQBC and QBC are both false.
# Matrix default= 2(PC601) if clip width<720 else 3(PC709).
# Conversion matrix for conversion of RGB to YUV-Y Luma. 0=REC601 : 1=REC709 : 2 = PC601 : 3 = PC709: YUV not used
# DO NOT USE Matrix of 0 or 1.
# PC default = false. If YUV and PC == true then auto level PC Levels 0->255 instead of TV levels 16->235. RGB always 0->255
# Debug default false. If true then send info the DebugView.
# Recommended, DebugView: http://technet.microsoft.com/en-gb/sysinternals/bb545027
# Laced, default = true. Alters Interlaced default for HMod, HMod doubled if true.
# WMod, default = the natural cropping WMod for clip c colorspace (eg 2 for YV12 and YUY2, 1 for RGB).
# HMod, default = the natural cropping HMod for clip c colorspace (eg 2 for YV12 and 1 for YUY2 and RGB), but doubled if Laced==true.
# NOTE, WMod, HMod, If overridden must all be multiples of natural cropping WMod and HMod for clip c colorspace.
# NOTE, VirtualDubMod and some players, may not like any colorspace WMOD less than 4 (Vdub latest, OK).
# NOTE, If eg VDMod show blank frame, OR eg player halts saying eg "No combination of filters cound be found to render frame"
# then set WMod to a multiple of 4. We do not do this by default as Current VDub and some player/encoders may work just fine.
# If you dont care about possibility of losing a couple of pixels then always supply WMod=4 to avoid display problems.
# Show, default false. If true, shows Levels() used on frame.
#
myName="RoboLevels: "
c
Frames=FrameCount
Strength=Float(Default(Strength,0.95))
Samples=(!Defined(Samples)) ? 32 : (Samples > Frames) ? Frames : (Samples < 1) ? 1 : Samples
Ignore=Float(Default(Ignore,0.2))
ALQBC=Default(ALQBC,True)
QBC=Default(QBC,False)
QBC_Thresh=Float(Default(QBC_Thresh,-32.0))
Matrix = Default(Matrix,(width <= 720) ? 2 : 3)
PC=Default(PC,False)
DEBUG=Default(DEBUG,False)
SHOW=Default(Show,false)
QBCropXP = Default(X,0) QBCropYP = Default(Y,0) QBCropWP = Default(W,0) QBCropHP = Default(H,0) # prep
Assert(Strength>=0.0 && Strength <=1.0, myName + "0.0 <= Strength <= 1.0")
GScript("""
if(ALQBC || QBC) {
QBCS=RT_QueryBorderCrop(samples=Samples,thresh=QBC_Thresh,debug=DEBUG,ignore=Ignore,matrix=Matrix,laced=laced,wmod=WMod,hmod=HMod)
Eval(QBCS)
}
QLMMS=RT_QueryLumaMinMax(c,samples=Samples,ignore=Ignore,x=QBCropXP,y=QBCropYP,W=QBCropWP,H=QBCropHP,debug=DEBUG,matrix=Matrix)
Eval(QLMMS)
if(IsRGB() || PC) {
CSMin = 0
CSMax = 255
} else {
CSMin = 16
CSMax = 235
}
ALMin = Int(CSMin - ((CSMin - QLMMMin) * Strength) + 0.5) # Round Up
ALMax = Int(CSMax - ((CSMax - QLMMMax) * Strength)) # Round down
if(QBC) {
CropS="Crop("+String(QBCropXM)+","+String(QBCropYM)+","+String(QBCropWM)+","+String(QBCropHM)+")"
(DEBUG)?RT_Debug(MyName,CropS,false):NOP
Crop(QBCropXM,QBCropYM,QBCropWM,QBCropHM)
(SHOW) ?RT_SubTitle(CropS,y=20):NOP # NOTE, After Cropping
}
LevelsS="Levels("+String(ALMin)+",1.0,"+String(AlMax)+","+String(CSMin)+","+String(CSMax)+",Coring=False)"
(DEBUG)? RT_Debug(MyName,LevelsS,false):NOP
(SHOW) ? RT_Subtitle(LevelsS,y=0):NOP
Levels(ALMin,1.0,ALMax,CSMin,CSMax,Coring=False) # DO NOT use Coring
""")
return Last
}
Anything in comments can be taken with a pinch of salt.
EDIT: Will probably crash if more than about 28 clip names supplied (seems to be general sourcefilter problem).
EDIT: And current BASE template as it stands
#ASYNTHER RoboSplice
Global G_FILECOUNT=___FILECNT___
Global G_DEBUG=True
Global G_QBC=True Global G_SAMPLES=32 Global G_QBC_THRESH=-32.0 Global G_INTERLACED=False
Global G_AL_STRENGTH=0.95 Global G_AUTOGAIN=False
Global G_DEBLOCK=22
Global G_RPOW2=false
Global G_DISPWID=0 Global G_DISPHIT=0 Global G_FRNUM=0 Global G_FRDEN=0
Global G_MCD=0 Global G_SIGMA=1.6 Global G_SHARPEN=0.01
Global G_CHANNELS=2 Global G_SAMPLERATE=44100 Global G_BITS=16 Global G_NORMALIZE=(G_FILECOUNT>1)
[GetTrim("___FILE___")]
StainlessS
20th February 2014, 18:34
Avisynthesizer_Mod Update, see 1st post.
20 Feb 2014, Added Batch AVS creation mode.
If template has a repeating section {enclosed in square brackets eg [AviSource("___FILE___")]} then will
use the standard mode, creating a single file with multiple sources concatenated.
If template DOES NOT have a repeating section {not enclosed in square backets eg AviSource("___FILE___")}
then will create multiple AVS files, one for each source file.
StainlessS
15th December 2014, 01:18
Post #1 of 2.
Updates to a few scripts in-progress. Also uses MCDegrain.avsi and FavC.avsi. (+ a number of plugins).
RoboSplice.Avst (Avisynthesizer_Mod template)
#ASYNTHER RoboSplice
Global G_FILECOUNT=___FILECNT___
Global G_DEBUG=True
Global G_QBC=True Global G_SAMPLES=32 Global G_QBC_THRESH=-32.0 Global G_INTERLACED=False
Global G_AL_STRENGTH=0.95 Global G_GAMMA=1.0 Global G_AUTOGAIN=False
Global G_DEBLOCK=20
Global G_RPOW2=false
Global G_DISPWID=0 Global G_DISPHIT=0
Global G_FRNUM=0 Global G_FRDEN=0
Global G_USE_INTERFRAME=False
Global G_ASPECT_DARX=0 Global G_ASPECT_DARY=0
Global G_MCD=0 Global G_SIGMA=1.65 Global G_SHARPEN=0.0
Global G_CHANNELS=2 Global G_SAMPLERATE=44100 Global G_BITS=16 Global G_NORMALIZE=(G_FILECOUNT>1)
[GetTrim("___FILE___")]
GetFile.avsi
Function GetFile(string vFN,string "aFN",Int "Prefer",Float "AudioDelay") {
myName="GetFile: "
START=RT_TimerHP
Assert(vFN!="",myName+"Empty VideofileName")
vFN = LCase(vFN)
aFN = LCase(Default(aFN,""))
Prefer=Default(Prefer,0) # Default 0=Avi if "AVI", 1, 1 = L-SMASH, 2 = FFMPegSource
Prefer = (Prefer<0 || Prefer>2) ? 0 : Prefer
AudioDelay=Float(Default(AudioDelay,0.0))
SepAud = (aFN!="" && aFN!=vFN)
Ext=RT_GetFileExtension(vFN)
Function IsISOFileName(String s) {
s=Lcase(RT_GetFileExtension(s)) Return(s==".mov"||s==".mp4"||s==".3gp"||s==".3g2"||s==".mj2"||s==".dvb"||s==".dcf"||s==".m21")}
GScript("""
c = 0
FLGS = 0
RT_DebugF("\nOpening Video %s for Extension %s",vFN,Ext,name=myName)
try {
# Attempt open for some formats by extension, NOT AVISource as could be non seekable, Allow AVI Indexing via later Source Plugs.
if(Ext == ".d2v") {c = MPEG2Source(vFN,UPCONV=1) RT_DebugF("MPEG2Source Succeeds:",name=myName)}
Else if(Prefer==0 && Ext == ".avi") {
c = AviSource(vFN)
try {c=AviSource(vFN) RT_DebugF("AVISource Video Succeeds:",name=myName) }
catch (msg) {RT_DebugF("AVISource Video Fails:- '%s'",msg,name=myName) }
}
if(!c.IsClip) {
if(Prefer<=1) {
If(IsISOFileName(Ext)) {
FLGS=RT_BitSet(FLGS,0)
c = LSMASHVideoSource(vFN) RT_DebugF("LSMASHVideoSource Video Succeeds:",name=myName)
if(!SepAud) {FLGS=RT_BitSet(FLGS,1) try{c=AudioDubEx(c,LSMASHAudioSource(vFN)) } catch(msg){} }
}
if(!c.IsClip) {
try {FLGS=RT_BitSet(FLGS,2) c=LWLibavVideoSource(vFN) RT_DebugF("LWLibavVideoSource Video Succeeds:",name=myName)
if(!SepAud) {FLGS=RT_BitSet(FLGS,3) try{c=AudioDubEx(c,LWLibavAudioSource(vFN)) } catch(msg){} }
} catch (msg) {RT_DebugF("LWLibavVideoSource Video Fails:- '%s'",msg,name=myName) }
}
} Else {
try {FLGS=RT_BitSet(FLGS,4) FFIndex(vFN) c=FFVideoSource(vFN) RT_DebugF("FFMSSource Video Succeeds:",name=myName)
if(!SepAud) {FLGS=RT_BitSet(FLGS,5) try{c=AudioDubEx(c,FFAudioSource(vFN)) } catch(msg){} }
} catch(msg) {RT_DebugF("FFMSSource Video Fails:- '%s'",msg,name=myName)}
}
}
} catch (msg) {c=0 RT_DebugF("Open Video by Extension Fails:- '%s'",msg,name=myName)}
if(!c.IsClip) {
if(!RT_BitTst(FLGS,4)) {
try {FLGS=RT_BitSet(FLGS,4) FFIndex(vFN) c=FFVideoSource(vFN) RT_DebugF("FFMSSource Video Succeeds:",name=myName)
if(!SepAud) {FLGS=RT_BitSet(FLGS,5) try{c=AudioDubEx(c,FFAudioSource(vFN)) } catch(msg){} }
} catch(msg) {RT_DebugF("FFMSSource Video Fails:- '%s'",msg,name=myName)}
}
if(!c.IsClip) {
if(!RT_BitTst(FLGS,2)) {
try {FLGS=RT_BitSet(FLGS,2) c=LWLibavVideoSource(vFN) RT_DebugF("LWLibavVideoSource Video Succeeds:",name=myName)
if(!SepAud) {FLGS=RT_BitSet(FLGS,3) try{c=AudioDubEx(c,LWLibavAudioSource(vFN)) } catch(msg){} }
} catch (msg) {RT_DebugF("LWLibavVideoSource Video Fails:- '%s'",msg,name=myName) }
}
if(!c.IsClip) {
if(!RT_BitTst(FLGS,0)) { # Not tried LSmash Video yet
FLGS=RT_BitSet(FLGS,0)
try {c = LSMASHVideoSource(vFN) RT_DebugF("LSMASHVideoSource Video Succeeds:",name=myName)
if(!SepAud) {FLGS=RT_BitSet(FLGS,1) try{c=AudioDubEx(c,LSMASHAudioSource(vFN)) } catch(msg){} }
} catch (msg) {RT_DebugF("LSMASHVideoSource Video Fails:- '%s'",msg,name=myName) }
}
if(!c.IsClip) {
try {c = DSS2(vFN) RT_DebugF("DSS2Source Video Succeeds:",name=myName) }
catch(msg) {RT_DebugF("DSS2Source Video Fails:- '%s'",msg,name=myName)
if(Ext==".avi") { # One last go before DirectShowSource
try {c=AviSource(vFN) RT_DebugF("AVISource Video Succeeds:",name=myName) }
catch (msg) {RT_DebugF("AVISource Video Fails:- '%s'",msg,name=myName) }
}
if(!c.IsClip) {
try {c=DirectShowSource(vFN,pixel_type="YV12") RT_DebugF("DirectShowSource(YV12) Video Succeeds:",name=myName) }
catch(msg) {RT_DebugF("DirectShowSource(YV12) Video Fails:- '%s'",msg,name=myName)
try {c=DirectShowSource(vFN,pixel_type="YUY2") RT_DebugF("DirectShowSource(YUY2) Video Succeeds:",name=myName) }
catch(msg) {RT_DebugF("DirectShowSource(YUY2) Video Fails:- '%s'",msg,name=myName)
try {c=DirectShowSource(vFN,pixel_type="RGB") RT_DebugF("DirectShowSource(RGB) Video Succeeds:",name=myName) }
catch(msg) {Assert(False,myName+"DirectShowSource(RGB) Video Fails: "+Chr(10)+msg)}
}
}
}
}
if(!c.HasAudio && !SepAud) {try{c=AudioDubEx(c,DirectShowSource(vFN,video=false) ) } catch(msg){} }
}
}
}
}
if((!c.HasAudio&&Ext!=".d2v") || SepAud){
RT_DebugF("Attempting Get Audio")
a = 0
aFN = (aFN=="") ? vFN : aFN
Ext=RT_GetFileExtension(aFN)
if(SepAud) {
RT_DebugF("Opening Audio %s for Extension %s",aFN,Ext,name=myName)
try {
if(Ext==".ac3") {a=NICAC3Source(aFN,channels=2,DRC=0) RT_DebugF("NICAC3Source Succeeds:",name=myName) }
Else if(Ext==".mpa"||Ext==".mp1"||Ext==".mp2"||Ext==".mp3") {
a=NicMPG123Source(aFN,Normalize=False) RT_DebugF("NicMPG123Source Succeeds:",name=myName) }
Else if(Ext==".wav") {a=RaWavSource(afN) RT_DebugF("RaWavSource Succeeds:",name=myName) }
Else if(Ext==".dts") {a=NicDTSSource(aFN) RT_DebugF("NicDTSSource Succeeds:",name=myName)}
} catch (msg) {a=0 RT_DebugF("Extension based Audio Fails:- '%s'",msg,name=myName) }
}
if(!a.IsClip) {
if(SepAud || !RT_BitTst(FLGS,5)) {
try {
if(SepAud || !RT_BitTst(FLGS,4)) {FFIndex(aFN)}
a = FFAudioSource(aFN) RT_DebugF("FFAudioSource Succeeds:",name=myName)
} catch(msg) {RT_DebugF("FFAudioSource Fails:- '%s'",msg,name=myName)}
}
if(!a.IsClip) {
if((SepAud || !RT_BitTst(FLGS,3))) {
try {a=LWLibavAudioSource(aFN) RT_DebugF("LWLibavAudioSource Succeeds:",name=myName) }
catch (msg) {RT_DebugF("LWLibavAudioSource Fails:- '%s'",msg,name=myName) }
}
if(!a.IsClip) {
if((SepAud || !RT_BitTst(FLGS,1))) {
try {a=LSMASHAudioSource(aFN) RT_DebugF("LSMASHAudioSource Succeeds:",name=myName) }
catch (msg) {RT_DebugF("LSMASHAudioSource Fails:- '%s'",msg,name=myName) }
}
if(!a.IsClip && SepAud) {
try {a=DirectShowSource(s,video=false) RT_DebugF("DirectShowSource Succeeds:",name=myName) }
catch (msg) {a=0 Assert(aFN!=vFN,myName+"Audio Fails: "+Chr(10)+msg)}
}
}
}
}
c = (a.IsClip) ? AudioDubEx(c,a) : c
c = (c.HasAudio) ? DelayAudio(c,AudioDelay).Trim(0,0) : c
}
RT_DebugF("Checking dimensions")
W=c.Width % 8 H=c.Height % 8
if(W > 0 || H > 0) {
W=(W==0)?0:8-W H=(H==0)?0:8-H
if(c.IsRGB()) {
yMin=c.RT_YPlaneMin(n=0,threshold=0.2) # Default matrix @ PC levels
Col = (yMin * 256 + yMin) * 256 + yMin
RT_DebugF("RGB Adding Borders %dx%d, Y=$%06X",W,H,Col,name=myName)
c=c.Addborders(0,0,W,H,Col)
} Else {
yMin=c.RT_YPlaneMin(n=0,threshold=0.2)
Col = (yMin * 256 + $80) * 256 + $80
RT_DebugF("YUV Adding Borders %dx%d, Y=$%06X",W,H,Col,name=myName)
if(W>0) {c=c.StackHorizontal(c.Blankclip(color_yuv=Col,Width=W))}
if(H>0) {c=c.StackVertical(c.Blankclip(color_yuv=Col,Height=H))}
}
}
RT_DebugF("ConvertYV12")
c = c.ConvertToYV12()
RT_DebugF("Convert Stereo")
c = FAVCStereo(c,c) # Output is YV12 + Stereo, Width & Height Mod 8
""")
T=RT_TimerHP - START
RT_DebugF("Total File Open Time = %.2fsecs",T,name=myName)
return c
}
StainlessS
15th December 2014, 01:19
Post #2 of 2.
RoboLevels.avsi
Function RoboLevels(clip c,float "Strength",int "Samples",float "Ignore",Bool "ALQBC",Bool "QBC",Float "QBC_Thresh",int "X",int "Y",int "W",int "H", \
int "Matrix",bool "PC",bool "DEBUG",bool "Laced", Int "WMod",Int "HMod",bool "Show") {
# Samples a number of frames from source clip and using minimum and maximum luma levels from those samples, auto levels clip.
# Default temporarily auto crop borders and samples the area remaining, or if both ALQBC and QBC == false then samples X,Y,W,H coords instead.
# Can optionally return border cropped clip when QBC==true.
#
# Args:
# Strength, default 0.95 (0.0 -> 1.0). Auto levelling strength.
# Samples, default 32. Number of frames sampled from source clip c.
# Ignore, default 0.2 (0.0 -> 100%). Percentage of dark pixels to ignore when ascertaining YPlaneMin, YPlaneMax (noise).
# ALQBC, default=true. Use temp auto cropped clip coords for auto levels sampling.
# QBC, default false. If true then returns border cropped clip else non cropped.
# QBC_Thresh, default -32.0. Threshold used for border detection. See RT_QueryBorderCrop.
# NOTE, RT_QueryBorderCrop 'massages' DEFAULT THRESH (exactly -32.0) if low samples count or if short clip. Reason being to avoid
# overcropping when insufficient data available for reliable cropping. It is considered better to not crop enough or at all, than
# to overcrop. You can override by simply setting an explicit threshold (+ve) of eg 40.0, or setting a NON-DEFAULT auto thresh (-ve)
# eg -16.0 or -32.1, where YPlaneMin is established for the sampled frames and then abs(thresh) is added to that value which is
# then used as an explicit thresh.
# X,Y,W,H. All default 0, ie full frame. Coords for luma sampling, only used if both ALQBC and QBC are both false.
# Matrix default= 2(PC601) if clip width<720 else 3(PC709).
# Conversion matrix for conversion of RGB to YUV-Y Luma. 0=REC601 : 1=REC709 : 2 = PC601 : 3 = PC709: YUV not used
# DO NOT USE Matrix of 0 or 1.
# PC default = false. If YUV and PC == true then auto level PC Levels 0->255 instead of TV levels 16->235. RGB always 0->255
# Debug default false. If true then send info the DebugView.
# Recommended, DebugView: http://technet.microsoft.com/en-gb/sysinternals/bb545027
# Laced, default = true. Alters Interlaced default for HMod, HMod doubled if true.
# WMod, default = the natural cropping WMod for clip c colorspace (eg 2 for YV12 and YUY2, 1 for RGB).
# HMod, default = the natural cropping HMod for clip c colorspace (eg 2 for YV12 and 1 for YUY2 and RGB), but doubled if Laced==true.
# NOTE, WMod, HMod, If overridden must all be multiples of natural cropping WMod and HMod for clip c colorspace.
# NOTE, VirtualDubMod and some players, may not like any colorspace WMOD less than 4 (Vdub latest, OK).
# NOTE, If eg VDMod show blank frame, OR eg player halts saying eg "No combination of filters cound be found to render frame"
# then set WMod to a multiple of 4. We do not do this by default as Current VDub and some player/encoders may work just fine.
# If you dont care about possibility of losing a couple of pixels then always supply WMod=4 to avoid display problems.
# Show, default false. If true, shows Levels() used on frame.
#
myName="RoboLevels: "
c
Frames=FrameCount
Strength=Float(Default(Strength,0.95))
Samples=(!Defined(Samples)) ? 32 : (Samples > Frames) ? Frames : (Samples < 1) ? 1 : Samples
Ignore=Float(Default(Ignore,0.2))
ALQBC=Default(ALQBC,True)
QBC=Default(QBC,False)
QBC_Thresh=Float(Default(QBC_Thresh,-32.0))
Default(Matrix,(width > 1100 || height > 600) ? 3 : 2) # Default to PC levels
PC=Default(PC,False)
DEBUG=Default(DEBUG,False)
SHOW=Default(Show,false)
QBCropXP = Default(X,0) QBCropYP = Default(Y,0) QBCropWP = Default(W,0) QBCropHP = Default(H,0) # prep
Assert(Strength>=0.0 && Strength <=1.0, myName + "0.0 <= Strength <= 1.0")
GScript("""
if(ALQBC || QBC) {
QBCS=RT_QueryBorderCrop(samples=Samples,thresh=QBC_Thresh,debug=DEBUG,ignore=Ignore,matrix=Matrix,laced=laced,wmod=WMod,hmod=HMod)
Eval(QBCS)
}
QLMMS=RT_QueryLumaMinMax(c,samples=Samples,ignore=Ignore,x=QBCropXP,y=QBCropYP,W=QBCropWP,H=QBCropHP,debug=DEBUG,matrix=Matrix)
Eval(QLMMS)
if(IsRGB() || PC) {
CSMin = 0
CSMax = 255
} else {
CSMin = 16
CSMax = 235
}
ALMin = Int(CSMin - ((CSMin - QLMMMin) * Strength) + 0.5) # Round Up
ALMax = Int(CSMax - ((CSMax - QLMMMax) * Strength)) # Round down
if(QBC) {
CropS="Crop("+String(QBCropXM)+","+String(QBCropYM)+","+String(QBCropWM)+","+String(QBCropHM)+")"
(DEBUG)?RT_DebugF(CropS,name=myName):NOP
Crop(QBCropXM,QBCropYM,QBCropWM,QBCropHM)
(SHOW) ?RT_SubTitle(CropS,y=20):NOP # NOTE, After Cropping
}
LevelsS=RT_String("Levels(%d,%f,%d,%d,%d,coring=false)",ALMin,G_GAMMA,AlMax,CSMin,CSMax)
(DEBUG)? RT_DebugF(LevelsS,name=myName):NOP
(SHOW) ? RT_Subtitle(LevelsS,y=0):NOP
Levels(ALMin,G_GAMMA,ALMax,CSMin,CSMax,Coring=False) # DO NOT use Coring
""")
return Last
}
RoboSplice.avsi
Function IsClose(Float a, Float b, Float threshold) {
threshold=Abs(threshold)
return ((abs(a-b)+threshold) <= threshold*2.0)
}
Function ConvRates(clip c,int "num",int "den",Bool "InterFrame",int "Channels",int "SampleRate",int "Bits",bool "Norm") {
myName="ConvRates: "
c
GScript("""
if((!Defined(num) || !Defined(den)) || (num==0 || den==0)) {num = 0 den = 0}
InterFrame=Default(Interframe,false)
Channels=Default(Channels,AudioChannels)
SampleRate=Default(SampleRate,AudioRate)
Bits=Default(bits,AudioBits)
Norm=Default(Norm,True)
if(num == FrameRateNumerator && den == FrameRateDenominator) {
RT_DebugF("Using Original FrameRate %.3f",FrameRate,name=myName)
} else {
if(num==0 || den == 0) {
FPS = FrameRate
if (isClose(FPS,29.97,0.015)) {num=30000 den = 1001}
else if (isClose(FPS,23.976,0.012)) {num=24000 den = 1001}
else if (isClose(FPS,11.988,0.006)) {num=12000 den = 1001}
else if (isClose(FPS,30.0,0.5)) {num=30 den = 1}
else if (isClose(FPS,25.0,0.5)) {num=25 den = 1}
else if (isClose(FPS,24.0,0.5)) {num=24 den = 1}
else if (isClose(FPS,18.0,0.5)) {num=18 den = 1}
else if (isClose(FPS,15.0,0.5)) {num=15 den = 1}
else if (isClose(FPS,12.5,0.5)) {num=25 den = 2}
else if (isClose(FPS,12.0,0.5)) {num=12 den = 1}
else {num=FrameRateNumerator den = FrameRateDenominator}
}
if(isClose(Float(num) / Float(den),FrameRate,1.0)) {
AssumeFPS(num,den,sync_audio=true)
RT_DebugF("Assuming FrameRate %.3f",FrameRate,name=myName)
} else {
if(Interframe) {
RT_DebugF("Interframe: Converting FrameRate to %.3f",Float(num) / Float(den),name=myName)
Interframe(NewNum=num,NewDen=den,cores=1)
} Else {
RT_DebugF("MVTools: Converting FrameRate to %.3f",Float(num) / Float(den),name=myName)
if(False) {
super=MSuper(pel=1)
bvec=MAnalyse(super, isb=true, blksize=16)
fvec=MAnalyse(super, isb=false, blksize=16)
MBlockFps(super, bvec, fvec, num=num,den=den, mode=3)
} else {
super=MSuper(pel=1, hpad=0, vpad=0)
backward_1=MAnalyse(super, chroma=false, isb=true, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
forward_1 =MAnalyse(super, chroma=false, isb=false, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
backward_2 = MRecalculate(super, chroma=false, backward_1, blksize=8, blksizev=8, searchparam=0, search=3)
forward_2 = MRecalculate(super, chroma=false, forward_1, blksize=8, blksizev=8, searchparam=0, search=3)
MBlockFps(super, backward_2, forward_2, num=num, den=den, mode=0)
}
}
}
}
IsSilent=false
if(!HasAudio) {
RT_DebugF("Adding Silent Audio",name=myName)
Aud=Last.Blankclip(audio_rate=SampleRate,channels=Channels)
IsSilent=true
Audiodub(Aud)
}
if(HasAudio) {
if(Channels == 0 && AudioChannels > 0) {
KillAudio()
RT_DebugF("Killing Audio",name=myName)
} else if(Channels == 1 && AudioChannels > 1) {
ConvertToMono()
RT_DebugF("Converting To MONO",name=myName)
} else if(Channels == 2 && AudioChannels ==1) {
AudioDub(Last,MergeChannels(GetChannel(1),GetChannel(1)))
RT_DebugF("Converting To DUEL Channel MONO",name=myName)
}
if(HasAudio() && Bits != AudioBits) {
if(bits==8) { ConvertAudioTo8bit() }
else if(bits==16) { ConvertAudioTo16bit() }
else if(bits==24) { ConvertAudioTo24bit() }
else if(bits==32) { ConvertAudioTo32bit() }
}
if(HasAudio() && SampleRate != AudioRate) {ResampleAudio(SampleRate) }
if(HasAudio() && Norm && !IsSilent) {
Normalize(0.98)
RT_DebugF("NORMALIZING AUDIO",name=myName)
}
}
""")
Return Trim(0,0)
}
Function DoTrim(clip c) {
myName="DoTrim: "
c
GScript("""
W=Width % 8 H=Height % 8
Addborders(0,0,W==0?0:8-W,H==0?0:8-h).ConvertToYV12()
if(G_DEBLOCK!=0) {
RT_DebugF("DEBLOCK(%d)",G_DEBLOCK,name=myName)
Deblock(G_DEBLOCK)
}
if(G_RPOW2 ||((G_DISPWID>0 && G_DISPWID>Int(Width*Sqrt(2.0))) || (G_DISPHIT>0 && G_DISPHIT>Int(Height*Sqrt(2.0))))) {
RT_DebugF("RPOW2",name=myName)
NNedi3_Rpow2(2)
}
if(G_QBC==true || G_SAMPLES!=0 || G_AL_STRENGTH>0.0 || G_AUTOGAIN) {
RT_DebugF("Calling RoboLevels",name=myName)
RoboLevels(Strength=G_AL_STRENGTH,samples=G_SAMPLES,qbc=G_QBC,QBC_Thresh=G_QBC_THRESH,DEBUG=G_DEBUG,Laced=G_INTERLACED,WMod=4,HMod=4)
if(G_AUTOGAIN) {
RT_DebugF("AutoGain",name=myName)
TMPW=Int(Width /4)*4 # Mod 4 for AutoGain
TMPH=Int(Height/4)*4 # Mod 4 for AutoGain
TMP=Crop(0,0,TMPW,TMPH,align=True)
AutoGain(Last,TMP)
}
}
if(G_MCD==0) {
if(G_SIGMA!=0.0 || G_SHARPEN!=0.0) {
RT_DebugF("FFT3DFilter(Sigma=%f,Sharpen=%f)",G_SIGMA,G_SHARPEN,name=myName)
FFT3DFilter(Sigma=G_SIGMA,Sharpen=G_SHARPEN)
}
} else {
RT_DebugF("MCDeGrain(%d)",G_MCD,name=myName)
MCDEGRAIN(G_MCD)
}
if(G_DISPWID!=Width || G_DISPHIT != Height) {
if(G_DISPWID==0 || G_DISPHIT == 0) {
WW=(Width + (4-1)) / 4 * 4
HH=(Height + (4-1)) / 4 * 4
Global G_DISPWID = WW
Global G_DISPHIT = HH
if(WW==Width && HH==Height) {
RT_DebugF("Using Original SIZE %d %d",G_DISPWID,G_DISPHIT,name=myName)
} else {
RT_DebugF("Resizing MOD 4, %dx%d",G_DISPWID,G_DISPHIT)
Spline36Resize(G_DISPWID,G_DISPHIT)
}
} else {
RT_DebugF("Resizing to match previous clip %dx%d",G_DISPWID,G_DISPHIT)
Spline36Resize(G_DISPWID,G_DISPHIT)
}
}
ConvRates(num=G_FRNUM,den=G_FRDEN,Interframe=G_USE_INTERFRAME,Channels=G_CHANNELS,SampleRate=G_SAMPLERATE,Bits=G_BITS,norm=G_NORMALIZE)
Global G_FRNUM = FrameRateNumerator
Global G_FRDEN = FrameRateDenominator
Global G_CHANNELS = AudioChannels
Global G_SAMPLERATE = AudioRate
Global G_BITS = AudioBits
if(G_MCD!=0) {
if(G_SIGMA!=0.0 || G_SHARPEN!=0.0) {
RT_DebugF("FFT3DFilter(Sigma=%f,Sharpen=%f)",G_SIGMA,G_SHARPEN,name=myName)
FFT3DFilter(Sigma=G_SIGMA,Sharpen=G_SHARPEN)
}
}
if(G_ASPECT_DARX>0 && G_ASPECT_DARY>0) {
RT_DebugF("SignalDAR2(%d,%d)",G_ASPECT_DARX,G_ASPECT_DARY,name=myName)
RT_SignalDar2(G_ASPECT_DARX,G_ASPECT_DARY)
}
""")
ConvertToYV12()
}
Function GetTrim(string s) {
Return GetFile(s).DoTrim()
}
Template given can be used on lone source or for concatenating multiple sources.
StainlessS
19th December 2014, 00:47
Here another multi-sourcefilter loader script by MpegAutoSource Vampiredom+
http://forum.doom9.org/showthread.php?t=162930
StainlessS
13th February 2019, 18:22
I have located original AviSynthesizer home page on Archive.org, below, [I guess the original author may have gotten tired of questions about the Mod version, so page deleted].
Here original home page on Archive.org:- https://web.archive.org/web/20140331084148/http://tangentsoft.net/video/asynther/
And the manual (also available via above link):- https://web.archive.org/web/20130318051724/http://tangentsoft.net/video/asynther/manual.html
NOTE, changed a little since above manual (uses ___FILE___ instead of %f as filename insert marker), and does not support BATCH mode available in AviSynthesizer_Mod.
StainlessS
10th May 2019, 03:52
A Pretty reasonable simple multi-source filter template script for splicing multiple source files (of similar characteristics).
Remove the square brackets around filename to make a Batch template (where makes one script for each selected source script).
ie make [GetSeq("___FILE___")] >>>======>>> GetSeq("___FILE___")
Can also extract and use the GetSeq() function in your scripts.
Does not use any fancy FFMS2 or LSMash args (just defaults).
Simple_AVI_LSmash_FFMS_Reader.avst [EDIT: The Name shown in template selector dialog box is in first line below, followinging "#ASYNTHER ".
#ASYNTHER Simple_AVI_LSmash_FFMS_Reader
# Requires RT_Stats
###########################
Function GetSeq(String vFn,String "aFn") {
Function IsISOFileName(String s) {s=RT_GetFileExtension(s) Return(s==".mov"||s==".mp4"||s==".m4v"||s==".3gp"||s==".3g2"||s==".mj2"||s==".dvb"||s==".dcf"||s==".m21")}
Function IsRiffFileName(String s) {s=RT_GetFileExtension(s) Return(s==".avi"||s==".wav")}
myName="GetSeq: " aFn = Default(aFn,"") aFn = (aFn=="") ? vFn : aFn
Assert(vFn!="",RT_String("%sVFn Cannot be ''",myName)) vFn = vFn.RT_GetFullPathName IsRiffV = vFn.IsRiffFileName IsIsoV = vFn.IsISOFileName
Assert(aFn!="",RT_String("%saFn Cannot be ''",myName)) aFn = aFn.RT_GetFullPathName IsRiffA = aFn.IsRiffFileName IsIsoA = aFn.IsISOFileName
c=0 a=0
Try { # 1st Try specialized AVI
c = (IsRiffV) ? vFn.AviSource : NOP
(c.IsClip) ? RT_DebugF("AviSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
a = (c.IsClip && c.HasAudio && aFn==vFn) ? c : (IsRiffA) ? aFn.WavSource : NOP
(a.IsClip && a.HasAudio) ? RT_DebugF("%s opened Audio\n '%s'",(c.IsClip && c.HasAudio && aFn==vFn)?"AviSource":"WavSource",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
# Next try specialized ISO LSMash
Try {
IsOpenV=(c.IsClip && c.HasVideo)
c = (IsIsoV) ? LSMASHVideoSource(vFn) : c
(IsIsoV) ? RT_DebugF("LSMASHVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a = (IsIsoA) ? LSMASHAudioSource(aFn) : a
(IsIsoA) ? RT_DebugF("LSMASHAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
# Next try FFMS2
Try {
IsOpenV=(c.IsClip && c.HasVideo)
(!IsOpenV) ? FFIndex(vFn) : NOP
c=(!IsOpenV) ? FFVideoSource(vFn) : c
(!IsOpenV) ? RT_DebugF("FFVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a=(!IsOpenA) ? FFAudioSource(aFn) : a
(!IsOpenA) ? RT_DebugF("FFAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
# Next try LSmash non ISO Video
Try {
IsOpenV=(c.IsClip && c.HasVideo)
c = (!IsOpenV && !IsIsoV) ? LWLibavVideoSource(vFn) : c
(!IsOpenV && !IsIsoV) ? RT_DebugF("LWLibavVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a = (!IsOpenA && !IsIsoA) ? LWLibavAudioSource(aFn) : a
(!IsOpenA && !IsIsoA) ? RT_DebugF("LWLibavAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Assert(c.IsClip, RT_String("%s failed open on\n '%s'",myName,vFn))
(!c.HasAudio && a.IsClip && a.HasAudio) ? AudioDubEx(c,a) : c
(!HasAudio) ? RT_DebugF("Audio failed Open on\n '%s",aFn,name=myName) : NOP
return Last
}
[GetSeq("___FILE___")]
Return last
EDIT: You could put GetSeq() function (excluding client call code) into and avsi file in plugins, and just use this as template NON batch mode template)
#ASYNTHER Simple_AVI_LSmash_FFMS_Reader
[GetSeq("___FILE___")]
return last
EDIT: OR batch mode template
#ASYNTHER BATCH-Simple_AVI_LSmash_FFMS_Reader
FN = "___FILE___"
GetSeq(FN)
return last
StainlessS
13th June 2019, 23:24
Batch mode template, Perhaps of use, not for MT nor x64 [TWriteAVI does not support].
Requires prev post script function [minus any calling code, as GetSeq.avsi in plugins], RT_Stats, TWriteAVI.
Load src, do some processing, write to AVI lossless file, make an awful noise when completed.
#ASYNTHER BATCH-AVI_WRITER
FN="___FILE___" # AvisynthesizerMod BATCH mode usage.
####################
OUTPATH = "D:\OUTPUT\" # Must exist, include Trailing backslash
FOURCC = "ULY0" # Ut_Video, YUV 420 TV Levels I think
###
FN=RT_GetFullPathName(FN)
OUTFN = OUTPATH + RT_FilenameSplit(FN,4) + ".AVI" # 4 = Name node only (no drive/path/extension)
###
GetSeq(FN) # source
########## DO PROCESSING Of SOME SORT ###
# Import("D:\MYSTUFF\GENERIC_PROC_1.avs") # Generic pre-process script (Affect all template expanded scripts [even already existing ones] with single GENERIC_PROC script edit)
#Sharpen(0.3) # Whatever
# Import("D:\MYSTUFF\GENERIC_PROC_2.avs") # generic post-process script
########## END OF PROCESSING ############
#return last # Comment OUT for final
#########################################
TWriteAVI(OUTFN,Overwrite=true,fourcc=FOURCC) # Write Sharp AVI whilst clip is played
#return Last # Write File as you play
ForceProcessAVI() # Force Write above TWriteAVI file without playing clip.
Return Colorbars.Subtitle("ALL DONE\nWritten:- "+RT_FilenameSplit(OUTFN,12),size=48,align=5,lsp=0) # Complete with nice TONE as user attention getter. (12=Name + extension)
##################################
### TWRITEAVI - NOT FOR MT USE ###
### x86 ONLY ###
### x64 Requires Asm progger ###
##################################
GillesH
25th July 2019, 14:46
Hello StainlessS,
I use GetSeq and it works fine. Thank you for this very effective function.
But, for FFMS2, I would like to put the .ffindex file in a directory other than that of the Clip.
Is it possible to modify GetSeq to have this possibility ?
StainlessS
25th July 2019, 16:18
Wanna try this [Can add Global string def to some avsi to auto set to temp directory, or whatever].
LSMash and AVI sources do not support Cachefile thing.
# GetSeq.avsi
#Global GLB_FFMS_CACHE_DIR = ".\OUT"
#Global GLB_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Write FFMS index's to User's Temp directory
Function GetSeq(String vFn,String "aFn",Val "fpsNum",Val "fpsDen") {
/*
Req:- RT_Stats, FFMS, LSmash.
Specify FrameRate using fpsnum (Numerator) and fpsden (Denominator) # *** INGNORED if AVI ***
num only, eg fpsnum=25.0, FrameRate = 25.0 FPS
num & den, eg fpsnum=24000 fpsden=1001, FrameRate = 23.976 FPS (Both should be type Int).
neither specified FrameRate = UnDefined, ie whatever source filter thinks it is.
ALWAYS:- use named args if using fpsnum/fpsden, argument order may change.
FFMS Cachefile (used for .ffindex file) directory can be set using global variable GLB_FFMS_CACHE_DIR, NO trailing backslash.
eg, Global GLB_FFMS_CACHE_DIR = "Z:\MyFFMSCacheDir".
*/
Function IsISOFileName(String s) {s=RT_GetFileExtension(s) Return(s==".mov"||s==".mp4"||s==".m4v"||s==".3gp"||s==".3g2"||s==".mj2"||s==".dvb"||s==".dcf"||s==".m21")}
Function IsRiffFileName(String s) {s=RT_GetFileExtension(s) Return(s==".avi"||s==".wav")}
myName="GetSeq: " aFn = Default(aFn,"") aFn = (aFn=="") ? vFn : aFn
Assert(vFn!="",RT_String("%svFn Cannot be ''",myName)) vFn = vFn.RT_GetFullPathName IsRiffV = vFn.IsRiffFileName IsIsoV = vFn.IsISOFileName
Assert(aFn!="",RT_String("%saFn Cannot be ''",myName)) aFn = aFn.RT_GetFullPathName IsRiffA = aFn.IsRiffFileName IsIsoA = aFn.IsISOFileName
c=0 a=0
def = fpsnum.Defined ? (fpsden.Defined ?1:0) : (!fpsden.Defined) ? 2 : -1 # 0=NumOnlyDef, 1=BothDef, 2=NoneDef, -1=DenOnlyError
Assert(0<=def,myName+"Cannot specify framerate using fpsden only")
# Rate=num : Rate=num/den : Rate=Undefined
num=(def==0) ? Round(fpsnum * 1000): (def==1) ? Int(fpsnum) : RT_Undefined
den=(def==0) ? 1000 : (def==1) ? fpsden : RT_Undefined
#
Try { # 1st Try specialized AVI
c = (IsRiffV) ? vFn.AviSource : NOP
(c.IsClip) ? RT_DebugF("AviSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
a = (c.IsClip && c.HasAudio && aFn==vFn) ? c : (IsRiffA) ? aFn.WavSource : NOP
(a.IsClip && a.HasAudio) ? RT_DebugF("%s opened Audio\n '%s'",(c.IsClip && c.HasAudio && aFn==vFn)?"AviSource":"WavSource",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
# Next try specialized ISO LSMash
Try {
IsOpenV=(c.IsClip && c.HasVideo)
c = (IsIsoV) ? LSMASHVideoSource(vFn,fpsnum=num,fpsden=den) : c
(IsIsoV) ? RT_DebugF("LSMASHVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a = (IsIsoA) ? LSMASHAudioSource(aFn) : a
(IsIsoA) ? RT_DebugF("LSMASHAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
# Next try FFMS2
CacheFile = RT_Undefined
Try {
IsOpenV=(c.IsClip && c.HasVideo) IsOpenA=(a.IsClip && a.HasAudio)
if(RT_VarExist("GLB_FFMS_CACHE_DIR") && GLB_FFMS_CACHE_DIR.IsString && Exist(GLB_FFMS_CACHE_DIR) && vFn==aFn && !IsOpenV && !IsOpenA) {
Cachefile = RT_GetFullPathName(GLB_FFMS_CACHE_DIR + "\" + RT_FilenameSplit(vFn,12) + ".ffindex")
RT_DebugF("Set FFMS CacheFile = %s",CacheFile,name=myName)
}
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenV=(c.IsClip && c.HasVideo)
(!IsOpenV) ? FFIndex(vFn,cachefile=CacheFile) : NOP
c=(!IsOpenV) ? FFVideoSource(vFn,fpsnum=num,fpsden=den,cachefile=CacheFile) : c
(!IsOpenV) ? RT_DebugF("FFVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a=(!IsOpenA) ? FFAudioSource(aFn,cachefile=CacheFile) : a
(!IsOpenA) ? RT_DebugF("FFAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
# Next try LSmash non ISO Video
Try {
IsOpenV=(c.IsClip && c.HasVideo)
c = (!IsOpenV && !IsIsoV) ? LWLibavVideoSource(vFn,fpsnum=num,fpsden=den) : c
(!IsOpenV && !IsIsoV) ? RT_DebugF("LWLibavVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a = (!IsOpenA && !IsIsoA) ? LWLibavAudioSource(aFn) : a
(!IsOpenA && !IsIsoA) ? RT_DebugF("LWLibavAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("Catch: %s",msg,name=myName) }
Assert(c.IsClip, RT_String("%s failed open on\n '%s'",myName,vFn))
(!c.HasAudio && a.IsClip && a.HasAudio) ? AudioDubEx(c,a) : c
(!HasAudio) ? RT_DebugF("Audio failed Open on\n '%s",aFn,name=myName) : NOP
return Last
}
# End of GetSeq.avsi
######
#GetSeq_Test.avs
######
Global GLB_FFMS_CACHE_DIR = ".\OUT"
FN="10Bit_Standard8_Scan_16FPS.avi" # This 10 bit dont load with Avisource(), [and no audio]
#FN="ALTEST2.mp4"
#FN="heima_720p_500.mp4"
#FN="tears_of_steel_1080pwebm.webm"
FN=RT_GetFullPathName(FN)
Getseq(FN,fpsnum=33000,fpsden=1001) # Test 33000/1001
Info
EDIT: Will only work where Video filename same as audio filename (which it usually would be [EDIT: When not supplied, is coerced to same as video filename]).
EDIT: Changed name a bit, to GLB_FFMS_CACHE_DIR due to lousy speelin.
16:29:54.129 InitExternalPlugins:
00000328 16:29:54.129 InitExternalPlugins: Auto load plugins script ENTRY
00000329 16:29:54.129 InitExternalPlugins:
00000330 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo:
00000331 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: VersionString = 'AviSynth+ 0.1 (r2900, MT, i386)'
00000332 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Avisynth Bitness = 32
00000333 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: ProcessName = 'C:\Program Files (x86)\DAUM\PotPlayer\PotPlayerMini.exe'
00000334 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: OSVersionString = 'Windows 7 (x64) Service Pack 1.0 (Build 7601)'
00000335 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: OSVersionNumber = 6.100000
00000336 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: CPUName = 'Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz / Yorkfield (Core 2 Quad) 6M'
00000337 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Cores = 04:04 (Phy:Log)
00000338 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: CPU Extensions = 'MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1'
00000339 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Total Memory = 12221MB
00000340 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Avail Memory = 9837MB'
00000341 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Screen Res = 1920x1080
00000342 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Screen BitPerPixel = 32
00000343 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo: Time = 'Thursday 25 July 2019 16:29:54[GMT Daylight Time]'
00000344 16:29:54.129 InitExternalPlugins:ShowAvsInitInfo:
00000345 16:29:54.129 InitExternalPlugins:AvsInit_Load_CPP_Plugin: DGDecode.DLL LOADED OK
00000346 16:29:54.129 InitExternalPlugins:AvsInit_Load_C_Plugin: ffms2.dll LOADED OK
00000347 16:29:54.129 InitExternalPlugins:AvsInit_Import_Avsi: ffms2.avsi IMPORTED OK
00000348 16:29:54.129 InitExternalPlugins:AvsInit_Load_CPP_Plugin: LSMASHSource.dll LOADED OK
00000349 16:29:54.269 GetSeq: Catch: AVISource: couldn't locate a decompressor for fourcc v210
00000350 16:29:54.269 GetSeq: (D:\GetSeq_Test\GetSeq_Test.avs, line 30)
00000351 16:29:54.472 GetSeq: Set FFMS CacheFile = D:\GetSeq_Test\OUT\10Bit_Standard8_Scan_16FPS.avi.ffindex
00000352 16:29:54.535 GetSeq: FFVideoSource opened Video
00000353 16:29:54.535 GetSeq: 'D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi'
00000354 16:29:54.550 GetSeq: Catch: FFAudioSource: No audio track found
00000355 16:29:54.550 GetSeq: (D:\GetSeq_Test\GetSeq_Test.avs, line 67)
00000356 16:29:54.550 GetSeq: Catch: LWLibavAudioSource: failed to get the audio track.
00000357 16:29:54.550 GetSeq: (D:\GetSeq_Test\GetSeq_Test.avs, line 79)
00000358 16:29:54.550 GetSeq: Audio failed Open on
00000359 16:29:54.550 GetSeq: 'D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi
Above file has no audio.
EDIT: Oops, had left "String CacheDir" as an arg to function, removed.
GillesH
25th July 2019, 17:07
Great, StainlessS.
It works very well. The ffindex file is well transmitted in the directory that we wish.
This allows to have the clean video library.
You are a champion of reactivity and efficiency.
:thanks:
StainlessS
25th July 2019, 17:16
See 1st bit in blue.
Could use Stickboy GetSystemEnv to get user specific TEMP directory, and set it to that.
Dont seem to be x64 version of GetSystemEnv, I do one.
EDIT:
# GetSeq.avsi
#Global GLB_FFMS_CACHE_DIR = ".\OUT" # Would require current directory relative folder called OUT, useful only really in avs not avsi
#Global GLB_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Write FFMS index's to User's Temp directory
00000049 17:55:46.582 GetSeq: Catch: AVISource: couldn't locate a decompressor for fourcc v210
00000050 17:55:46.582 GetSeq: (C:/VideoTools/AvisynthRepository/AVSPLUS_x86/plugins/GetSeq.avsi, line 34)
00000051 17:55:46.629 GetSeq: Set FFMS CacheFile = C:\Users\root\AppData\Local\Temp\10Bit_Standard8_Scan_16FPS.avi.ffindex
00000052 17:55:51.028 GetSeq: FFVideoSource opened Video
00000053 17:55:51.028 GetSeq: 'D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi'
00000054 17:55:51.044 GetSeq: Catch: FFAudioSource: No audio track found
00000055 17:55:51.044 GetSeq: (C:/VideoTools/AvisynthRepository/AVSPLUS_x86/plugins/GetSeq.avsi, line 71)
00000056 17:55:51.044 GetSeq: Catch: LWLibavAudioSource: failed to get the audio track.
00000057 17:55:51.044 GetSeq: (C:/VideoTools/AvisynthRepository/AVSPLUS_x86/plugins/GetSeq.avsi, line 83)
00000058 17:55:51.044 GetSeq: Audio failed Open on
00000059 17:55:51.044 GetSeq: 'D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi
EDIT: I forgot, RT_Stats has already RT_GetSystemEnv().
StainlessS
26th July 2019, 00:14
Update to GetSeq(), Needs a good tester :)
# GetSeq.avsi
#Global GLB_GETSEQ_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Set to the Current User's Temp directory.
#Global GLB_GETSEQ_DEL_INDEX_ON_CLOSE = True # If CallCmd() available, then auto delete index's on clip closure. [FFMS or LSMASH]
Function GetSeq(String vFn,String "aFn",Val "fpsNum",Val "fpsDen") {
/*
Req:- RT_Stats, FFMS, LSmash. [Also CallCmd if auto delete of FFMS and LSMash indexes required]
Specify FrameRate using fpsnum (Numerator) and fpsden (Denominator) # *** INGNORED if AVI ***
num only, eg fpsnum=25.0, FrameRate = 25.0 FPS
num & den, eg fpsnum=24000 fpsden=1001, FrameRate = 23.976 FPS (Both should be type Int).
neither specified FrameRate = UnDefined, ie whatever source filter thinks it is.
ALWAYS:- use named args if using fpsnum/fpsden, argument order may change.
FFMS Cachefile (used for .ffindex file) directory can be set using global variable GLB_GETSEQ_FFMS_CACHE_DIR, NO trailing backslash.
Global GLB_GETSEQ_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Set to the Current User's Temp directory.
If CallCmd() dll is avalable, and Global variable GLB_GETSEQ_DEL_INDEX_ON_CLOSE is True, then will auto Delete both FFMS and LSMash indexes on clip closure.
Global GLB_GETSEQ_DEL_INDEX_ON_CLOSE = True # If CallCmd available then Auto delete indexes on clip closure. # Could create stub which sets True/False depending upon your own arg.
*/
Function IsISOFileName(String s) {s=RT_GetFileExtension(s) Return(s==".mov"||s==".mp4"||s==".m4v"||s==".3gp"||s==".3g2"||s==".mj2"||s==".dvb"||s==".dcf"||s==".m21")}
Function IsRiffFileName(String s) {s=RT_GetFileExtension(s) Return(s==".avi"||s==".wav")}
myName="GetSeq: " aFn = Default(aFn,"") aFn = (aFn=="") ? vFn : aFn
Assert(vFn!="",RT_String("%svFn Cannot be ''",myName)) vFn = vFn.RT_GetFullPathName IsRiffV = vFn.IsRiffFileName IsIsoV = vFn.IsISOFileName
Assert(aFn!="",RT_String("%saFn Cannot be ''",myName)) aFn = aFn.RT_GetFullPathName IsRiffA = aFn.IsRiffFileName IsIsoA = aFn.IsISOFileName
HasCallCmd = RT_FunctionExist("CallCmd")
c=0 a=0
def = fpsnum.Defined ? (fpsden.Defined ?1:0) : (!fpsden.Defined) ? 2 : -1 # 0=NumOnlyDef, 1=BothDef, 2=NoneDef, -1=DenOnlyError
Assert(0<=def,myName+"Cannot specify framerate using fpsden only")
# Rate=num : Rate=num/den : Rate=Undefined
num=(def==0) ? Round(fpsnum * 1000): (def==1) ? Int(fpsnum) : RT_Undefined
den=(def==0) ? 1000 : (def==1) ? fpsden : RT_Undefined
CacheFile = "" FFMS_Index_file = "" LSMASH_Index_file=""
msgNL = Chr(10)+" "
#
Try { # 1st Try specialized AVI
c = (IsRiffV) ? vFn.AviSource : NOP
(c.IsClip) ? RT_DebugF("OK ... AviSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
a = (c.IsClip && c.HasAudio && aFn==vFn) ? c : (IsRiffA) ? aFn.WavSource : NOP
(a.IsClip && a.HasAudio) ? RT_DebugF("OK ... %s opened Audio\n '%s'",(c.IsClip && c.HasAudio && aFn==vFn)?"AviSource":"WavSource",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
# Next try specialized ISO LSMash
Try {
IsOpenV=(c.IsClip && c.HasVideo)
c = (IsIsoV) ? LSMASHVideoSource(vFn,fpsnum=num,fpsden=den) : c
(IsIsoV) ? RT_DebugF("OK ... LSMASHVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
a = (IsIsoA) ? LSMASHAudioSource(aFn) : a
(IsIsoA) ? RT_DebugF("OK ... LSMASHAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
# Next try FFMS2
Try {
IsOpenV=(c.IsClip && c.HasVideo) IsOpenA=(a.IsClip && a.HasAudio)
IsSetCache = (!IsOpenV && !IsOpenA && vFn==aFn && RT_VarExist("GLB_GETSEQ_FFMS_CACHE_DIR") && GLB_GETSEQ_FFMS_CACHE_DIR.IsString && Exist(GLB_GETSEQ_FFMS_CACHE_DIR))
Cachefile = (IsSetCache) ? RT_GetFullPathName(GLB_GETSEQ_FFMS_CACHE_DIR + "\" + RT_FilenameSplit(vFn,12) + ".ffindex") : Cachefile
(IsSetCache) ? RT_DebugF("!!! Set !!! ... FFMS CacheFile = %s",CacheFile,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
IsOpenV=(c.IsClip && c.HasVideo)
FFMS_Index_file = (!IsOpenV && CacheFile=="") ? vFn + ".ffindex" : CacheFile # May create Index on fail (so rem before we try)
(!IsOpenV) ? FFIndex(vFn,cachefile=CacheFile==""?RT_Undefined:CacheFile) : NOP
c=(!IsOpenV) ? FFVideoSource(vFn,fpsnum=num,fpsden=den,cachefile=CacheFile==""?RT_Undefined:CacheFile) : c
(!IsOpenV) ? RT_DebugF("OK ... FFVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
FFMS_Index_file = (FFMS_Index_file!="") ? FFMS_Index_file : (!IsOpenA && CacheFile=="") ? aFn + ".ffindex" : CacheFile # May create Index on fail (so rem before we try)
a=(!IsOpenA) ? FFAudioSource(aFn,cachefile=CacheFile==""?RT_Undefined:CacheFile) : a
(!IsOpenA) ? RT_DebugF("OK ... FFAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
# Next try LSmash non ISO Video : Try even if have tried ISO Open
Try {
IsOpenV=(c.IsClip && c.HasVideo)
LSMASH_Index_file = (!IsOpenV) ? vFn + ".lwi" : LSMASH_Index_file # May create Index on fail (so rem before we try)
c = (!IsOpenV) ? LWLibavVideoSource(vFn,fpsnum=num,fpsden=den) : c
(!IsOpenV) ? RT_DebugF("OK ... LWLibavVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
IsOpenA=(a.IsClip && a.HasAudio)
LSMASH_Index_file = (LSMASH_Index_file!="") ? LSMASH_Index_file : (!IsOpenA) ? aFn + ".lwi" : "" # May create Index on fail (so rem before we try)
a = (!IsOpenA) ? LWLibavAudioSource(aFn) : a
(!IsOpenA) ? RT_DebugF("OK ... LWLibavAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Assert(c.IsClip, RT_String("!!! %s failed open on\n '%s'",myName,vFn))
(!c.HasAudio && a.IsClip && a.HasAudio) ? AudioDubEx(c,a) : c
(!HasAudio) ? RT_DebugF("!!! Audio failed Open on\n '%s",aFn,name=myName) : NOP
AutoDEL = (HasCallCmd && RT_VarExist("GLB_GETSEQ_DEL_INDEX_ON_CLOSE") && GLB_GETSEQ_DEL_INDEX_ON_CLOSE)
Try {
(AutoDEL && FFMS_Index_file!="" && Exist(FFMS_Index_file))
\ ? CallCmd(close="CMD /C chcp 1252 && del " + RT_QuoteStr(FFMS_Index_file), hide=true, debug=true, Synchronous=7)
\ : last
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
(AutoDEL && LSMASH_Index_file!="" && Exist(LSMASH_Index_file))
\ ? CallCmd(close="CMD /C chcp 1252 && del " + RT_QuoteStr(LSMASH_Index_file), hide=true, debug=true, Synchronous=7)
\ : last
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
return Last
}
# END OF GetSeq.avsi
Global GLB_GETSEQ_FFMS_CACHE_DIR = ".\OUT OUT" # Where FFMS index are written (Test SPACE in filename, and current path relative)
Global GLB_GETSEQ_DEL_INDEX_ON_CLOSE = True # Auto Delete indexes where CallCmd() is available. [FFMS or LSMASH]
#FN="D:\Parade.avi"
#FN="10Bit_Standard8_Scan_16FPS.avi" # This 10 bit dont load with Avisource(), [and no audio]
#FN="ALTEST2.mp4"
#FN="heima_720p_500.mp4"
FN="tears_of_steel_1080pwebm.webm"
Getseq(FN,fpsnum=33000,fpsden=1001) # Test 33000/1001
Info
From DebugView [google]
00000062 23:53:27.307 GetSeq: !!! Set !!! ... FFMS CacheFile = D:\GetSeq_Test\OUT OUT\tears_of_steel_1080pwebm.webm.ffindex
00000063 23:53:30.442 GetSeq: OK ... FFVideoSource opened Video
00000064 23:53:30.442 GetSeq: 'D:\GetSeq_Test\tears_of_steel_1080pwebm.webm'
00000065 23:53:30.630 GetSeq: OK ... FFAudioSource opened Audio
00000066 23:53:30.630 GetSeq: 'D:\GetSeq_Test\tears_of_steel_1080pwebm.webm'
00000067 23:53:30.630 CallCmd: Constructor IN
00000068 23:53:30.630 CallCmd: CallCmd: v1.04 - 04 Apr 2018 - by StainlessS
00000069 23:53:30.630 CallCmd: Command for Frames = ''
00000070 23:53:30.630 CallCmd: Close Command (Destructor) = 'CMD /C chcp 1252 && del "D:\GetSeq_Test\OUT OUT\tears_of_steel_1080pwebm.webm.ffindex"'
00000071 23:53:30.630 CallCmd: FRAMES: About to Parse Frames String
00000072 23:53:30.630 CallCmd: Doing command on 0 Frames
00000073 23:53:30.630 CallCmd: Constructor OUT
00000074 23:53:33.192 CallCmd: Destructor IN
00000075 23:53:33.192 CallCmd: Close (Destructor) on command 'CMD /C chcp 1252 && del "D:\GetSeq_Test\OUT OUT\tears_of_steel_1080pwebm.webm.ffindex"'
00000076 23:53:33.259 CallCmd: SUCCESS Creating Process (WAIT)
00000077 23:53:33.259 CallCmd: WAIT, Process returned 0 (0x00000000)
00000078 23:53:33.259 CallCmd: Destructor OUT
EDIT: And on AVI where no decompressor available [on my system] and without audio. [both FFMS and LSMASH indexes created, and deleted {FFMS index re-directed to ".\OUT OUT"}]
00000016 00:38:13.788 GetSeq: *** Catch *** AVISource: couldn't locate a decompressor for fourcc v210
00000017 00:38:13.788 GetSeq: (D:\GetSeq_Test\GetSeq_Test.avs, line 42)
00000018 00:38:13.834 GetSeq: !!! Set !!! ... FFMS CacheFile = D:\GetSeq_Test\OUT OUT\10Bit_Standard8_Scan_16FPS.avi.ffindex
00000019 00:38:18.000 GetSeq: OK ... FFVideoSource opened Video
00000020 00:38:18.000 GetSeq: 'D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi'
00000021 00:38:18.015 GetSeq: *** Catch *** : FFAudioSource: No audio track found
00000022 00:38:18.015 GetSeq: (D:\GetSeq_Test\GetSeq_Test.avs, line 79)
00000023 00:38:18.889 GetSeq: *** Catch *** : LWLibavAudioSource: failed to get the audio track.
00000024 00:38:18.889 GetSeq: (D:\GetSeq_Test\GetSeq_Test.avs, line 93)
00000025 00:38:18.889 GetSeq: !!! Audio failed Open on
00000026 00:38:18.889 GetSeq: 'D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi
00000027 00:38:18.889 CallCmd: Constructor IN
00000028 00:38:18.889 CallCmd: CallCmd: v1.04 - 04 Apr 2018 - by StainlessS
00000029 00:38:18.889 CallCmd: Command for Frames = ''
00000030 00:38:18.889 CallCmd: Close Command (Destructor) = 'CMD /C chcp 1252 && del "D:\GetSeq_Test\OUT OUT\10Bit_Standard8_Scan_16FPS.avi.ffindex"'
00000031 00:38:18.889 CallCmd: FRAMES: About to Parse Frames String
00000032 00:38:18.889 CallCmd: Doing command on 0 Frames
00000033 00:38:18.889 CallCmd: Constructor OUT
00000034 00:38:18.904 CallCmd: Constructor IN
00000035 00:38:18.904 CallCmd: CallCmd: v1.04 - 04 Apr 2018 - by StainlessS
00000036 00:38:18.904 CallCmd: Command for Frames = ''
00000037 00:38:18.904 CallCmd: Close Command (Destructor) = 'CMD /C chcp 1252 && del "D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi.lwi"'
00000038 00:38:18.904 CallCmd: FRAMES: About to Parse Frames String
00000039 00:38:18.904 CallCmd: Doing command on 0 Frames
00000040 00:38:18.904 CallCmd: Constructor OUT
00000041 00:38:21.042 CallCmd: Destructor IN
00000042 00:38:21.042 CallCmd: Close (Destructor) on command 'CMD /C chcp 1252 && del "D:\GetSeq_Test\10Bit_Standard8_Scan_16FPS.avi.lwi"'
00000043 00:38:21.111 CallCmd: SUCCESS Creating Process (WAIT)
00000044 00:38:21.111 CallCmd: WAIT, Process returned 0 (0x00000000)
00000045 00:38:21.111 CallCmd: Destructor OUT
00000046 00:38:21.111 CallCmd: Destructor IN
00000047 00:38:21.111 CallCmd: Close (Destructor) on command 'CMD /C chcp 1252 && del "D:\GetSeq_Test\OUT OUT\10Bit_Standard8_Scan_16FPS.avi.ffindex"'
00000048 00:38:21.178 CallCmd: SUCCESS Creating Process (WAIT)
00000049 00:38:21.178 CallCmd: WAIT, Process returned 0 (0x00000000)
00000050 00:38:21.178 CallCmd: Destructor OUT
GillesH
26th July 2019, 08:49
Tester, yes. Good : I do not know!
Your latest version of GetSeq works very well.
I tested, too, with CallCmd. And the index file is deleted when closing the Clip.
Tip: Provide an additional note in the script ---> # CallCmd.dll needed
I had never used this DLL and looked for what CallCmd() meant.
But the search gave me the solution.
Conclusion: I am not a good tester !:)
hello_hello
26th July 2019, 11:51
A minor thought.... ffms2 and lsmash have a cache option. When set to false, no index file is written and I assume there'd be no need to check for one to delete. If the index file is being deleted automatically when the script closes anyway, it might be a good idea to include "cache" in GetSeq.
StainlessS
26th July 2019, 13:48
Tip: Provide an additional note in the script ---> # CallCmd.dll needed
Already added.
Function GetSeq(String vFn,String "aFn",Val "fpsNum",Val "fpsDen") {
/*
Req:- RT_Stats, FFMS, LSmash. [Also CallCmd if auto delete of FFMS and LSMash indexes required]
Unfortunately, in case where video opens in AVI, but no audio, will try open audio and index in both FFMS and LSmash (Non ISO) and so scan entire clip twice
only to find that it aint got no audio. [took a long long time on audioless Starwars PAL DVD in UT_Video avi].
HH,
Does the Cache=False option [for both] avoid creation of index AND curtail scanning, ie halt immediately where clip has no audio ?
Also, without index, are both flavours just as frame accurate (as with index) ?
Me knew this was gonna balloon in size.
StainlessS
28th July 2019, 02:56
From prev post.
Unfortunately, in case where video opens in AVI, but no audio, will try open audio and index in both FFMS and LSmash (Non ISO) and so scan entire clip twice
only to find that it aint got no audio. [took a long long time on audioless Starwars PAL DVD in UT_Video avi].
Added Mifo_Library (Included in 7z). Avoids unnecessary (perhaps multiple) scans for non existing audio.
Here:- http://www.mediafire.com/file/xrf6rdjxre6tmq4/GetSeq_20190728.7z/file
Now Require, RT_Stats, FFMS, LSmash, CallCmd, MediaInfo CLI, (tested only with v0.7.83, probably ok with later).
EDIT: Hard to tell exactly how long it took without timer (Media player start up etc, I'll add one) but above mentioned StarWars took ~= 2 seconds with Mifo_Library,
whereas was more like half an hour or more without it (so a bit faster, sometimes).
EDIT: MIFO_Library(slight mod included in GetSeq zip):- https://forum.doom9.org/showthread.php?t=173268&highlight=library
EDIT: I suspect that giving a cachefile="whatever" type thing may have produced a full scan even when it was unnecessary, maybe.
EDIT: Non AVS+ guys will have to GImport() [gimport from GScript] the AVSI's, either from an avsi in plugins, or from the client script.
EDIT: Looks like this now (NOW requires either AVS+, or GSCript which must GImport the .avsi files GetSeq.avsi, and MIFO_Library.avsi. [STUFF added since zip upload in RED]
# GetSeq.avsi
Global GLB_GETSEQ_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Set to the Current User's Temp directory.
Global GLB_GETSEQ_DEL_INDEX_ON_CLOSE = True # If True then auto delete index's on clip closure. [FFMS or LSMASH]
Function GetSeq(String vFn,String "aFn",Val "fpsNum",Val "fpsDen") {
/*
Req:- RT_Stats, FFMS, LSmash. CallCmd, MediaInfo CLI v0.7.83+ (may work with later versions)
Specify FrameRate using fpsnum (Numerator) and fpsden (Denominator) # *** INGNORED if AVI ***
num only, eg fpsnum=25.0, FrameRate = 25.0 FPS
num & den, eg fpsnum=24000 fpsden=1001, FrameRate = 23.976 FPS (Both should be type Int).
neither specified FrameRate = UnDefined, ie whatever source filter thinks it is.
ALWAYS:- use named args if using fpsnum/fpsden, argument order may change.
FFMS Cachefile (used for .ffindex file) directory can be set using global variable GLB_GETSEQ_FFMS_CACHE_DIR, NO trailing backslash.
Global GLB_GETSEQ_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Set to the Current User's Temp directory.
If Global variable GLB_GETSEQ_DEL_INDEX_ON_CLOSE is True, then will auto Delete both FFMS and LSMash indexes on clip closure.
Global GLB_GETSEQ_DEL_INDEX_ON_CLOSE = True # If true, Auto delete indexes on clip closure. # Could create stub which sets True/False depending upon your own arg.
*/
Function IsISOFileName(String s) {s=RT_GetFileExtension(s) Return(s==".mov"||s==".mp4"||s==".m4v"||s==".3gp"||s==".3g2"||s==".mj2"||s==".dvb"||s==".dcf"||s==".m21")}
Function IsRiffFileName(String s) {s=RT_GetFileExtension(s) Return(s==".avi"||s==".wav")}
myName="GetSeq: " aFn = Default(aFn,"") aFn = (aFn=="") ? vFn : aFn
Assert(RT_FunctionExist("MIFO_Version"),RT_String("%sWe require MIFO_Library",myName))
Assert(vFn!="",RT_String("%svFn Cannot be ''",myName)) vFn = vFn.RT_GetFullPathName IsRiffV = vFn.IsRiffFileName IsIsoV = vFn.IsISOFileName
Assert(aFn!="",RT_String("%saFn Cannot be ''",myName)) aFn = aFn.RT_GetFullPathName IsRiffA = aFn.IsRiffFileName IsIsoA = aFn.IsISOFileName
Assert(RT_FunctionExist("CallCmd"),RT_String("%sCallCmd essential",myName))
Start_T = RT_TimerHP()
c=0 a=0
def = fpsnum.Defined ? (fpsden.Defined ?1:0) : (!fpsden.Defined) ? 2 : -1 # 0=NumOnlyDef, 1=BothDef, 2=NoneDef, -1=DenOnlyError
Assert(0<=def,myName+"Cannot specify framerate using fpsden only")
# Rate=num : Rate=num/den : Rate=Undefined
num=(def==0) ? Round(fpsnum * 1000): (def==1) ? Int(fpsnum) : RT_Undefined
den=(def==0) ? 1000 : (def==1) ? fpsden : RT_Undefined
CacheFile = "" FFMS_Index_file = "" LSMASH_Index_file=""
msgNL = Chr(10)+" "
VideoCount = MI_VideoCount(vFn,Debug=true) # Number of Video Streams in vFn
RT_DebugF("File has %d Video streams. '%s'",VideoCount,vFn,name=myName)
Assert(VideoCount>0,myName+"File has no video\n'vFN'")
AudioCount = MI_AudioCount(aFn,Debug=true) # Number of Audio Streams in aFn
RT_DebugF("File has %d Audio streams. '%s'",AudioCount,aFn,name=myName)
#
Try { # 1st Try specialized AVI
c = (IsRiffV) ? vFn.AviSource : NOP
(c.IsClip) ? RT_DebugF("OK ... AviSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
if(AudioCount>0) {
a = (c.IsClip && c.HasAudio && aFn==vFn) ? c : (IsRiffA) ? aFn.WavSource : NOP
(a.IsClip && a.HasAudio) ? RT_DebugF("OK ... %s opened Audio\n '%s'",(c.IsClip && c.HasAudio && aFn==vFn)?"AviSource":"WavSource",aFn,name=myName) : NOP
}
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
# Next try specialized ISO LSMash
Try {
IsOpenV=(c.IsClip && c.HasVideo)
c = (IsIsoV) ? LSMASHVideoSource(vFn,fpsnum=num,fpsden=den) : c
(IsIsoV) ? RT_DebugF("OK ... LSMASHVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
if(AudioCount>0) {
IsOpenA=(a.IsClip && a.HasAudio)
a = (IsIsoA) ? LSMASHAudioSource(aFn) : a
(IsIsoA) ? RT_DebugF("OK ... LSMASHAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
}
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
# Next try FFMS2
Try {
IsOpenV=(c.IsClip && c.HasVideo) IsOpenA=(a.IsClip && a.HasAudio)
IsSetCache = (!IsOpenV && !IsOpenA && vFn==aFn && RT_VarExist("GLB_GETSEQ_FFMS_CACHE_DIR") && GLB_GETSEQ_FFMS_CACHE_DIR.IsString && Exist(GLB_GETSEQ_FFMS_CACHE_DIR))
Cachefile = (IsSetCache) ? RT_GetFullPathName(GLB_GETSEQ_FFMS_CACHE_DIR + "\" + RT_FilenameSplit(vFn,12) + ".ffindex") : Cachefile
(IsSetCache) ? RT_DebugF("!!! Set !!! ... FFMS CacheFile = %s",CacheFile,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
IsOpenV=(c.IsClip && c.HasVideo)
FFMS_Index_file = (!IsOpenV && CacheFile=="") ? vFn + ".ffindex" : CacheFile # May create Index on fail (so rem before we try)
(!IsOpenV) ? FFIndex(vFn,cachefile=CacheFile==""?RT_Undefined:CacheFile) : NOP
c=(!IsOpenV) ? FFVideoSource(vFn,fpsnum=num,fpsden=den,cachefile=CacheFile==""?RT_Undefined:CacheFile) : c
(!IsOpenV) ? RT_DebugF("OK ... FFVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
if(AudioCount>0) {
IsOpenA=(a.IsClip && a.HasAudio)
FFMS_Index_file = (FFMS_Index_file!="") ? FFMS_Index_file : (!IsOpenA && CacheFile=="") ? aFn + ".ffindex" : CacheFile # May create Index on fail (so rem before we try)
a=(!IsOpenA) ? FFAudioSource(aFn,cachefile=CacheFile==""?RT_Undefined:CacheFile) : a
(!IsOpenA) ? RT_DebugF("OK ... FFAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
}
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
# Next try LSmash non ISO Video : Try even if have tried ISO Open
Try {
IsOpenV=(c.IsClip && c.HasVideo)
LSMASH_Index_file = (!IsOpenV) ? vFn + ".lwi" : LSMASH_Index_file # May create Index on fail (so rem before we try)
c = (!IsOpenV) ? LWLibavVideoSource(vFn,fpsnum=num,fpsden=den) : c
(!IsOpenV) ? RT_DebugF("OK ... LWLibavVideoSource opened Video\n '%s'",vFn,name=myName) : NOP
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
if(AudioCount>0) {
IsOpenA=(a.IsClip && a.HasAudio)
LSMASH_Index_file = (LSMASH_Index_file!="") ? LSMASH_Index_file : (!IsOpenA) ? aFn + ".lwi" : "" # May create Index on fail (so rem before we try)
a = (!IsOpenA) ? LWLibavAudioSource(aFn) : a
(!IsOpenA) ? RT_DebugF("OK ... LWLibavAudioSource opened Audio\n '%s'",aFn,name=myName) : NOP
}
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Assert(c.IsClip, RT_String("!!! %s failed open on\n '%s'",myName,vFn))
if(AudioCount>0) {
c = (!c.HasAudio && a.IsClip && a.HasAudio) ? AudioDubEx(c,a) : c
Assert(c.HasAudio,RT_String("%s!!! Audio failed Open on '%s'",myName,aFn))
}
AutoDEL = (RT_VarExist("GLB_GETSEQ_DEL_INDEX_ON_CLOSE") && GLB_GETSEQ_DEL_INDEX_ON_CLOSE)
Try {
c = (AutoDEL && FFMS_Index_file!="" && Exist(FFMS_Index_file))
\ ? c.CallCmd(close="CMD /C chcp 1252 && del " + RT_QuoteStr(FFMS_Index_file), hide=true, debug=true, Synchronous=7)
\ : c
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
Try {
c = (AutoDEL && LSMASH_Index_file!="" && Exist(LSMASH_Index_file))
\ ? c.CallCmd(close="CMD /C chcp 1252 && del " + RT_QuoteStr(LSMASH_Index_file), hide=true, debug=true, Synchronous=7)
\ : c
} catch (msg) { RT_DebugF("*** Catch *** : %s",RT_StrReplace(msg,Chr(10),msgNL),name=myName) }
T = RT_TimerHP() - Start_T
RT_DebugF("Time taken to Open clip = %.6f Seconds(%.6f Mins)\n '%s'",T,T/60.0,vFN,name=myName)
return c
}
# END OF GetSeq.avsi
StainlessS
28th July 2019, 16:48
Debug log from above posted, slight mods (only added stuff to show time taken to open clip)
00000363 16:45:30.843 MIFO_GeneralItem: Calling MIFO_StreamCount
00000364 16:45:30.858 MIFO_GeneralItem: Calling MIFO_CallMediaInfo
00000365 16:45:30.858 MIFO_GeneralItem: Calling CallCmd
00000366 16:45:30.858 CallCmd: Constructor IN
00000367 16:45:30.858 CallCmd: CallCmd: v1.04 - 04 Apr 2018 - by StainlessS
00000368 16:45:30.858 CallCmd: Command for Frames = ''
00000369 16:45:30.858 CallCmd: Open Command (Constructor) = '"MediaInfo.Exe" --Language=raw --LogFile="D:\GetSeq_Test\MediaInfo_20190728_164530_858.txt" --Inform=General;%VideoCount% "E:\Starwars\SW.avi" '
00000370 16:45:30.858 CallCmd: FRAMES: About to Parse Frames String
00000371 16:45:30.858 CallCmd: Doing command on 0 Frames
00000372 16:45:30.858 CallCmd: Open (Constructor) on command '"MediaInfo.Exe" --Language=raw --LogFile="D:\GetSeq_Test\MediaInfo_20190728_164530_858.txt" --Inform=General;%VideoCount% "E:\Starwars\SW.avi" '
00000373 16:45:31.170 CallCmd: SUCCESS Creating Process (WAIT)
00000374 16:45:31.170 CallCmd: WAIT, Process returned 0 (0x00000000)
00000375 16:45:31.170 CallCmd: Constructor OUT
00000376 16:45:31.170 CallCmd: Destructor IN
00000377 16:45:31.170 CallCmd: Destructor OUT
00000378 16:45:31.170 MIFO_GeneralItem: MediaInfo: on Section 'General'
00000379 16:45:31.170 MIFO_GeneralItem: 1
00000380 16:45:31.170 GetSeq: File has 1 Video streams. 'E:\Starwars\SW.avi'
00000381 16:45:31.170 MIFO_GeneralItem: Calling MIFO_StreamCount
00000382 16:45:31.186 MIFO_GeneralItem: Calling MIFO_CallMediaInfo
00000383 16:45:31.186 MIFO_GeneralItem: Calling CallCmd
00000384 16:45:31.186 CallCmd: Constructor IN
00000385 16:45:31.186 CallCmd: CallCmd: v1.04 - 04 Apr 2018 - by StainlessS
00000386 16:45:31.186 CallCmd: Command for Frames = ''
00000387 16:45:31.186 CallCmd: Open Command (Constructor) = '"MediaInfo.Exe" --Language=raw --LogFile="D:\GetSeq_Test\MediaInfo_20190728_164531_186.txt" --Inform=General;%AudioCount% "E:\Starwars\SW.avi" '
00000388 16:45:31.186 CallCmd: FRAMES: About to Parse Frames String
00000389 16:45:31.186 CallCmd: Doing command on 0 Frames
00000390 16:45:31.186 CallCmd: Open (Constructor) on command '"MediaInfo.Exe" --Language=raw --LogFile="D:\GetSeq_Test\MediaInfo_20190728_164531_186.txt" --Inform=General;%AudioCount% "E:\Starwars\SW.avi" '
00000391 16:45:31.248 CallCmd: SUCCESS Creating Process (WAIT)
00000392 16:45:31.248 CallCmd: WAIT, Process returned 0 (0x00000000)
00000393 16:45:31.248 CallCmd: Constructor OUT
00000394 16:45:31.248 CallCmd: Destructor IN
00000395 16:45:31.248 CallCmd: Destructor OUT
00000396 16:45:31.248 MIFO_GeneralItem: MediaInfo: on Section 'General'
00000397 16:45:31.248 MIFO_GeneralItem:
00000398 16:45:31.248 GetSeq: File has 0 Audio streams. 'E:\Starwars\SW.avi'
00000399 16:45:31.279 GetSeq: OK ... AviSource opened Video
00000400 16:45:31.279 GetSeq: 'E:\Starwars\SW.avi'
00000401 16:45:31.279 GetSeq: Time taken to Open clip = 0.435468 Seconds(0.007258 Mins)
00000402 16:45:31.279 GetSeq: 'E:\Starwars\SW.avi'
So is a bit faster than the ~= half hour it took when double indexing Starwars without audio[once in FFMS, and again in LSMash].
EDIT: These are the demo functions supplied as is with MIFO_LIB, very easy to add your own using below examples
####################################
########## DEMO FUNCTIONS ##########
####################################
###### # Demo individual purpose functions (in this case for stream in Section 'General') Below all returning Type Int.
Function MI_VideoCount(String Fn,Bool "Debug") {Return RT_NumberValue(MIFO_GeneralItem(Fn,0,"VideoCount",Debug=Debug))}
Function MI_AudioCount(String Fn,Bool "Debug") {Return RT_NumberValue(MIFO_GeneralItem(Fn,0,"AudioCount",Debug=Debug))}
Function MI_TextCount(String Fn,Bool "Debug") {Return RT_NumberValue(MIFO_GeneralItem(Fn,0,"TextCount",Debug=Debug))}
Function MI_ImageCount(String Fn,Bool "Debug") {Return RT_NumberValue(MIFO_GeneralItem(Fn,0,"ImageCount",Debug=Debug))}
Function MI_MenuCount(String Fn,Bool "Debug") {Return RT_NumberValue(MIFO_GeneralItem(Fn,0,"MenuCount",Debug=Debug))}
###### Demo individual purpose funcs (in this case for stream in Section 'Video')
###### Below return type string to differentiate between "" & 0.
###### Below default to Raw mode, (for some things Raw and Cooked may be same)
Function MI_Video_DAR(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg '1.778'
{Return MIFO_VideoItem(Fn,Stream,"DisplayAspectRatio",Raw,Debug)}
Function MI_Video_CompressionMode(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "Lossless"/"Lossy"
{Return MIFO_VideoItem(Fn,Stream,"Compression_Mode",Raw,Debug)}
Function MI_Video_ColorSpace(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "YUV"
{Return MIFO_VideoItem(Fn,Stream,"ColorSpace",Raw,Debug)}
Function MI_Video_Width(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "720"
{Return MIFO_VideoItem(Fn,Stream,"Width",Raw,Debug)}
Function MI_Video_Height(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "576"
{Return MIFO_VideoItem(Fn,Stream,"Height",Raw,Debug)}
Function MI_Video_FrameRate(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "25.000"
{Return MIFO_VideoItem(Fn,Stream,"FrameRate",Raw,Debug)}
Function MI_Video_BitDepth(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "8"
{Return MIFO_VideoItem(Fn,Stream,"BitDepth",Raw,Debug)}
Function MI_Video_ScanType(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "Progressive"
{Return MIFO_VideoItem(Fn,Stream,"ScanType",Raw,Debug)}
Function MI_Video_ScanOrder(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "TFF"
{Return MIFO_VideoItem(Fn,Stream,"ScanOrder",Raw,Debug)}
Function MI_Video_CodecID(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg "ULY0"
{Return MIFO_VideoItem(Fn,Stream,"CodecID",Raw,Debug)}
eg
DAR = MI_Video_DAR("D:\StarWards.avi") # Might return "1.778"
EDIT: Mifo_Client.avs included in zip, MIFO lib usage examples.
#Import("MIFO_Library.avsi") # If not in Plugins Dir # EDIT: GImport() if not AVS+ and GScript
###
# GET DEBUGVIEW to see output, here:- https://technet.microsoft.com/en-us/sysinternals/debugview.aspx
###
Fn="D:\Parade.AVI"
#FN=".\I.AVI"
#FN=".\I.FLV"
#FN=".\VTS_01_1.VOB"
#FN=".\VTS_01_0.IFO"
DEBUG=False # False show results only : True = FULL DEBUG
TEMPLATESTRING=
\ "Codec ID = ............. : %CodecID%\r\n" +
\ "Pixel Aspect Ratio = ... : %PixelAspectRatio%\r\n" +
\ "Display Aspect Ratio = . : %DisplayAspectRatio%\r\n" +
\ "BitDepth = ............. : %BitDepth%\r\n" +
\ "ScanType = ............. : %ScanType%\r\n" +
\ "ScanOrder = ............ : %ScanOrder%\r\n" +
\ "Compression Mode = ..... : %Compression_Mode%\r\n" +
\ "Delay = ................ : %Delay%\r\n"
TEMPLATEFILE ="Example_TemplateFile.txt"
########
# Uncomment something below (ONLY 1)
########
# S = MIFO_Version(Debug=DEBUG) # MediaInfo Version Number
# S = MIFO_StreamCount(Fn,"Audio",Debug=DEBUG) # Query number of Audio Streams
# S = MIFO_VideoItem(Fn,1,Parameter="DisplayAspectRatio",Debug=DEBUG) # Display Aspect Ratio of first Video stream
# S = MIFO_Item(Fn,"Video",1,Parameter="DisplayAspectRatio",Debug=DEBUG) # Display Aspect Ratio of first Video stream
# S = MIFO_TemplateString(Fn,"Video",Template=TEMPLATESTRING,Debug=DEBUG) # TemplateString Search Cooked
# S = MIFO_TemplateFile(Fn,Template=TEMPLATEFILE,Debug=DEBUG) # TemplateFile Search Cooked
# S = MIFO_General(Fn,Full=True,Raw=True,Debug=DEBUG) # Extract Full General Section Raw Parameters
# S = MIFO_Video(Fn,Full=False,Raw=False,Debug=DEBUG) # Extract Normal Video Section Cooked Parameters
# S = MIFO_Video(Fn,Full=True,Raw=False,Debug=DEBUG) # Extract Full Video Section Cooked Parameters
# S = MIFO_Video(Fn,Full=False,Raw=True,Debug=DEBUG) # Extract Normal Video Section Raw Parameters
# S = MIFO_Video(Fn,Full=True,Raw=True,Debug=DEBUG) # Extract Full Video Section Raw Parameters
# S = MIFO_Audio(Fn,Full=True,Raw=True,Debug=DEBUG) # Extract Full Audio Section Raw Parameters
# S = MIFO_Text(Fn,Full=True,Raw=True,Debug=DEBUG) # Extract Full Text Section Raw Parameters
# S = MIFO_Image(Fn,Full=True,Raw=True,Debug=DEBUG) # Extract Full Image Section Raw Parameters
# S = MIFO_Meu(Fn,Full=True,Raw=True,Debug=DEBUG) # Extract Full Menu Section Raw Parameters
#######################
## Uncomment Below 4 lines TOGETHER. Extract Multiple items from full search Raw Info
## [We only extract one item below: MIFO_Video(Fn) could replace lines 2 & 3].
##
#ITEM_1 = "Format_Settings_Matrix_Data" # Item to find in full search info, Video Section of eg VOB.
#ALLINFO = MIFO_Get(Fn,"",Full=True,Raw=True,Debug=DEBUG) # Extract FULL RAW Info [MIFO_Video(Fn) would be simpler]
#VIDINFO = MIFO_ExtractSection(ALLINFO,"Video",Debug=DEBUG) # Extract Video Info [Same as MIFO_Video(Fn) or MIFO_Section(Fn,"Video")]
#S = MIFO_ExtractSectionItem(VIDINFO,ITEM_1,Pair=True,Debug=Debug) # Extract ITEM_1 as string Pair (Pair=False for data alone)
#######################
### Demo Functions
# S = MI_VideoCount(Fn,Debug=DEBUG) # These return Type Int.
# S = MI_AudioCount(Fn,Debug=DEBUG)
# S = MI_TextCount(Fn,Debug=DEBUG)
# S = MI_ImageCount(Fn,Debug=DEBUG)
# S = MI_MenuCount(Fn,Debug=DEBUG)
# S = MI_Video_DAR(FN,Debug=DEBUG) # These return Type String.
# S = MI_Video_CompressionMode(FN,Debug=DEBUG)
# S = MI_Video_Width(FN,Debug=DEBUG)
# S = MI_Video_Height(FN,Debug=DEBUG)
# S = MI_Video_FrameRate(FN,Debug=DEBUG)
# S = MI_Video_BitDepth(FN,Debug=DEBUG)
# S = MI_Video_ScanType(FN,Debug=DEBUG)
# S = MI_Video_ScanOrder(FN,Debug=DEBUG)
# S = MI_Video_CodecID(FN,Debug=DEBUG)
S = MIFO_Get(Fn,"",Full=True,Raw=True,Debug=DEBUG)SCROLL=True # Extract Entire Info, Full Raw info (*** EVERYTHING ***)
#######
#######
#######
RT_DebugF("%s",String(S),name="TEST_RESULT: ") # See Results in DebugView
#######
(!RT_VarExist("SCROLL"))
\ ? Messageclip("DONE ")
\ :BlankClip(Length=RT_TxtQueryLines(S)*20).ScriptClip("""RT_Subtitle("%s",S,align=1,y=height-current_frame,expx=true,expy=true)""")
Extract all Video section for 10 bit v210 avi without audio
Fn="..\..\10Bit_Standard8_Scan_16FPS.avi"
S=MIFO_Section(Fn,"Video",Stream=1,Full=true,Raw=true)
RT_WriteFile(".\TEMP.TXT","%s",S)
Result text file [The strings on left are raw parameter strings, can be used as args to extract individual item data, eg 'CodeID' to extract item "v210", or DisplayAspectRatio extracts "1.778"].
Video
Count : 334
StreamCount : 1
StreamKind : Video
StreamKind/String : Video
StreamKindID : 0
ID : 0
ID/String : 0
Format : YUV
Format_Commercial : YUV
CodecID : v210
CodecID/Hint : AJA Video Systems Xena
Codec : v210
Codec/String : v210
Codec/CC : v210
Duration : 10000
Duration/String : 10s 0ms
Duration/String1 : 10s 0ms
Duration/String2 : 10s 0ms
Duration/String3 : 00:00:10.000
Duration/String4 : 00:00:10:00
Duration/String5 : 00:00:10.000 (00:00:10:00)
BitRate : 707788800
BitRate/String : 708 Mbps
Width : 1920
Width/String : 1920 pixel3
Height : 1080
Height/String : 1080 pixel3
PixelAspectRatio : 1.000
DisplayAspectRatio : 1.778
DisplayAspectRatio/String : 16:9
FrameRate : 16.000
FrameRate/String : 16.000 fps3
FrameCount : 160
Resolution : 10
Resolution/String : 10 bit3
ColorSpace : YUV
ChromaSubsampling : 4:2:2
ChromaSubsampling/String : 4:2:2
BitDepth : 10
BitDepth/String : 10 bit3
Compression_Mode : Lossless
Compression_Mode/String : Lossless
Bits-(Pixel*Frame) : 21.333
StreamSize : 884736000
StreamSize/String : 844 MiB (100%)
StreamSize/String1 : 844 MiB
StreamSize/String2 : 844 MiB
StreamSize/String3 : 844 MiB
StreamSize/String4 : 843.8 MiB
StreamSize/String5 : 844 MiB (100%)
StreamSize_Proportion : 0.99999
From the example funcs, to extract DAR, from Video section of file FN, stream number STREAM.
Function MI_Video_DAR(String Fn,Int "Stream",Bool "Raw",Bool "Debug") # eg '1.778'
{Return MIFO_VideoItem(Fn,Stream,"DisplayAspectRatio",Raw,Debug)}
hello_hello
30th July 2019, 17:05
HH,
Does the Cache=False option [for both] avoid creation of index AND curtail scanning, ie halt immediately where clip has no audio ?
Also, without index, are both flavours just as frame accurate (as with index) ?
I'm a bit late returning, but it occurred to me disabling the cache might be a bad idea. Assuming the same index is written to RAM, I'm not sure xxxAudioSource and xxxVideoSource could share the same index, given it's not being written to a file, so it might result in double indexing. I haven't tested it to see if it takes longer though.
Another thought, if I understand the relevant part of your function correctly, is ffms2 can be told to only index the video, so if you already have audio at the ffms2 stage you could include indexmask=0 as an ffindex argument to prevent it indexing the audio while it's indexing the video.
Or if you do the audio check first and don't use ffindex, that'd happen automatically because ffaudiosource indexes everything, whereas ffvideosouce only indexes video tracks, so if you do ffvideosouce before ffaudiosource it has to index twice.
Not that it's as fancy as what you've done, but you inspired me to iron out the bugs, so here's my FFLMash function if it's of any use to anyone. It (effectively) combines LSmashSource2, LibavSource2 & FFmpegSource2 in a single function, attempting to open files in that order, or there's an option to change the order and try FFmpegSource2, then LibavSource2.
# ===============================================================================
# ========== FFLMash 2019-07-30 =================================================
# ===============================================================================
# FFLMash first attempts to open a source with the equivalent of LSmashSource2, LibavSource2
# and then FFMS2/FFmpegSource2. Or it can be done in the reverse order.
# Sources containing only video or only audio can be opened without having to disable the video
# or audio to prevent an error.
#
# VTrack. Default: -1 (auto)
# Video track number. If -2, disable video.
#
# ATrack. Default: -1 (auto)
# Audio track number. If -2, disable audio.
#
# Cache. Default: true
# False disables the writing of an index file.
# LWLibavSource2 & FFMS2 only. LSmashSource2 doesn't write an index file.
#
# Cachefile. Default: not specified
# The location of the index file (FFMS2 only).
#
# FPSNum & FPSDen. Defaults: 0 & 1
# Framerate for VFR->CFR conversion. No VFR->CFR conversion with defaults.
#
# Threads. Default: 0 (auto)
# The number of threads for LSmashSource2 / LWLibavSource2 / FFMS2 to use.
#
# RFFMode. Default: 0
# Honour repeat field flags. LWLibavSource2 & FFMS2 only.
# FFMS2: 0=false, 1=true, 2=force film.
# LWLibavSource2: 0=false, 1=true, 2=false.
#
# Order. Default: 1
# A value of 2 attempts to open a source with FFMS2 first, in which case only
# LWLibavSource2 will be tried next. Useful for large files containing audio that need indexing,
# but where the audio is not required. FFMS2 will index only the video when audio is disabled.
# ===============================================================================
function FFLMash(string Source, \
int "VTrack", int "ATrack", bool "Cache", string "Cachefile", \
int "FPSNum", int "FPSDen", int "Threads", int "RFFMode", int "Order") {
VTrack = default(VTrack, -1)
VTrackLS = (VTrack == -1) ? VTrack + 1 : VTrack
ATrack = default(ATrack, -1)
ATrackLS = (ATrack == -1) ? ATrack + 1 : ATrack
Cache = default(Cache, true)
FPSNum = default(FPSNum, 0)
FPSDen = default(FPSDen, 1)
Threads = default(Threads, 0)
RFFMode = default(RFFMode, 0)
Repeat = (RFFMode == 1)
Order = default(Order, 1)
VideoEnabled = (VTrack > -2)
AudioEnabled = (ATrack > -2)
IsLSMASHVideo = false
IsLSMASHAudio = false
LSMASHVideoNotFound = false
LSMASHAudioNotFound = false
IsLWLibavVideo = false
IsLWLibavAudio = false
LWLibavVideoNotFound = false
LWLibavAudioNotFound = false
IsFFMSVideo = false
IsFFMSAudio = false
FFMSVideoNotFound = false
FFMSAudioNotFound = false
err_msg = ""
assert(0 <= RFFMode <= 2, " FFLMash " + chr(10) + " RFFMode can only be 0, 1 or 2 " + chr(10))
assert(1 <= Order <= 2, " FFLMash " + chr(10) + " Order can only be 1 or 2 " + chr(10))
assert(VideoEnabled || AudioEnabled, " FFLMash " + chr(10) + " Both video & audio are disabled " + chr(10))
# ========== Order 1 - LSMASHAudioSource & LSMASHVideoSource ====================
(Order == 1) && AudioEnabled ? Eval("""
try{
A = LSMASHAudioSource(Source, track=ATrackLS)
IsLSMASHAudio = true
}
catch(err_msg){
LSMASHAudioNotFound = (leftstr(err_msg, 46) == "LSMASHAudioSource: failed to find audio track.")
NoLSMASHAudio = (leftstr(err_msg, 32) == "LSMASHAudioSource: Not an audio track")
assert(!NoLSMASHAudio, " FFLMash " + chr(10) + \
" LSMASHAudioSource says the specified audio track " + chr(10) + " is not an audio track " + chr(10))
}
""") : nop()
(Order == 1) && VideoEnabled && \
(!AudioEnabled || (AudioEnabled && (IsLSMASHAudio || LSMASHAudioNotFound))) ? Eval("""
try{
V = LSMASHVideoSource(Source, track=VTrackLS, threads=Threads, fpsnum=FPSNum, fpsden=FPSDen)
IsLSMASHVideo = true
}
catch(err_msg){
LSMASHVideoNotFound = (leftstr(err_msg, 46) == "LSMASHVideoSource: failed to find video track.")
NoLSMASHVideo = (leftstr(err_msg, 32) == "LSMASHVideoSource: Not a video track")
assert(!NoLSMASHVideo, " FFLMash " + chr(10) + \
" LSMASHVideoSource says the specified video track " + chr(10) + " is not a video track " + chr(10))
}
""") : nop()
StopAfterLSMASH = IsLSMASHAudio || IsLSMASHVideo || LSMASHAudioNotFound || LSMASHVideoNotFound
# ========== Order 1 - LWLibavAudioSource & LWLibavVideoSource ==================
!StopAfterLSMASH && (Order == 1) && AudioEnabled ? Eval("""
try{
A = LWLibavAudioSource(Source, stream_index=ATrack, cache=Cache)
IsLWLibavAudio = true
}
catch(err_msg){
LWLibavAudioNotFound = (leftstr(err_msg, 50) == "LWLibavAudioSource: failed to get the audio track.")
NoLWLibavAudio = (leftstr(err_msg, 33) == "LWLibavAudioSource: Not an audio track")
assert(!NoLWLibavAudio, " FFLMash " + chr(10) + \
" LWLibavAudioSource says the specified audio track " + chr(10) + " is not an audio track " + chr(10))
}
""") : nop()
!StopAfterLSMASH && (Order == 1) && VideoEnabled && \
(!AudioEnabled || (AudioEnabled && (IsLWLibavAudio || LWLibavAudioNotFound))) ? Eval("""
try{
V = LWLibavVideoSource(Source, stream_index=VTrack, cache=Cache, fpsnum=FPSNum, fpsden=FPSDen, \
threads=Threads, repeat=Repeat)
IsLWLibavVideo = true
}
catch(err_msg){
LWLibavVideoNotFound = (leftstr(err_msg, 50) == "LWLibavVideoSource: failed to get the video track.")
NoLWLibavVideo = (leftstr(err_msg, 32) == "LWLibavVideoSource: Not a video track")
assert(!NoLWLibavVideo, " FFLMash " + chr(10) + \
" LWLibavVideoSource says the specified video track " + chr(10) + " is not a video track " + chr(10))
}
""") : nop()
StopAfterLWLibav = IsLWLibavAudio || IsLWLibavVideo || LWLibavAudioNotFound || LWLibavVideoNotFound
# ========== Order 1 - FFAudioSource & FFVideoSource ============================
!StopAfterLSMASH && !StopAfterLWLibav && (Order == 1) && AudioEnabled ? Eval("""
try{
A = FFAudioSource(Source, track=ATrack, cache=Cache, cachefile=Cachefile)
IsFFMSAudio = true
}
catch(err_msg){
FFMSAudioNotFound = (leftstr(err_msg, 35) == "FFAudioSource: No audio track found")
NoFFMSAudio = (leftstr(err_msg, 33) == "FFAudioSource: Not an audio track")
assert(!NoFFMSAudio, " FFLMash " + chr(10) + \
" FFAudioSource says the specified audio track " + chr(10) + " is not an audio track " + chr(10))
}
""") : nop()
!StopAfterLSMASH && !StopAfterLWLibav && (Order == 1) && VideoEnabled && \
(!AudioEnabled || (AudioEnabled && (IsFFMSAudio || FFMSAudioNotFound))) ? Eval("""
try{
V = FFVideoSource(Source, track=VTrack, cache=Cache, cachefile=Cachefile, \
fpsnum=FPSNum, fpsden=FPSDen, threads=Threads, rffmode=RFFMode)
IsFFMSVideo = true
}
catch(err_msg){
FFMSVideoNotFound = (leftstr(err_msg, 35) == "FFVideoSource: No video track found")
NoFFMSVideo = (leftstr(err_msg, 32) == "FFVideoSource: Not a video track")
assert(!NoFFMSVideo, " FFLMash " + chr(10) + \
" FFVideoSource says the specified video track " + chr(10) + " is not a video track " + chr(10))
}
""") : nop()
# ========== Order 2 - FFAudioSource & FFVideoSource ============================
(Order == 2) && AudioEnabled ? Eval("""
try{
A = FFAudioSource(Source, track=ATrack, cache=Cache, cachefile=Cachefile)
IsFFMSAudio = true
}
catch(err_msg){
FFMSAudioNotFound = (leftstr(err_msg, 35) == "FFAudioSource: No audio track found")
NoFFMSAudio = (leftstr(err_msg, 33) == "FFAudioSource: Not an audio track")
assert(!NoFFMSAudio, " FFLMash " + chr(10) + \
" FFAudioSource says the specified audio track " + chr(10) + " is not an audio track " + chr(10))
}
""") : nop()
(Order == 2) && VideoEnabled && \
(!AudioEnabled || (AudioEnabled && (IsFFMSAudio || FFMSAudioNotFound))) ? Eval("""
try{
V = FFVideoSource(Source, track=VTrack, cache=Cache, cachefile=Cachefile, \
fpsnum=FPSNum, fpsden=FPSDen, threads=Threads, rffmode=RFFMode)
IsFFMSVideo = true
}
catch(err_msg){
FFMSVideoNotFound = (leftstr(err_msg, 35) == "FFVideoSource: No video track found")
NoFFMSVideo = (leftstr(err_msg, 32) == "FFVideoSource: Not a video track")
assert(!NoFFMSVideo, " FFLMash " + chr(10) + \
" FFVideoSource says the specified video track " + chr(10) + " is not a video track " + chr(10))
}
""") : nop()
StopAfterFFMS = IsFFMSAudio || IsFFMSVideo || FFMSAudioNotFound || FFMSVideoNotFound
# ========== Order 2 - LWLibavAudioSource & LWLibavVideoSource ==================
!StopAfterFFMS && (Order == 2) && AudioEnabled ? Eval("""
try{
A = LWLibavAudioSource(Source, stream_index=ATrack, cache=Cache)
IsLWLibavAudio = true
}
catch(err_msg){
LWLibavAudioNotFound = (leftstr(err_msg, 50) == "LWLibavAudioSource: failed to get the audio track.")
NoLWLibavAudio = (leftstr(err_msg, 33) == "LWLibavAudioSource: Not an audio track")
assert(!NoLWLibavAudio, " FFLMash " + chr(10) + \
" LWLibavAudioSource says the specified audio track " + chr(10) + " is not an audio track " + chr(10))
}
""") : nop()
!StopAfterFFMS && (Order == 2) && VideoEnabled && \
(!AudioEnabled || (AudioEnabled && (IsLWLibavAudio || LWLibavAudioNotFound))) ? Eval("""
try{
V = LWLibavVideoSource(Source, stream_index=VTrack, cache=Cache, fpsnum=FPSNum, fpsden=FPSDen, \
threads=Threads, repeat=Repeat)
IsLWLibavVideo = true
}
catch(err_msg){
LWLibavVideoNotFound = (leftstr(err_msg, 50) == "LWLibavVideoSource: failed to get the video track.")
NoLWLibavVideo = (leftstr(err_msg, 32) == "LWLibavVideoSource: Not a video track")
assert(!NoLWLibavVideo, " FFLMash " + chr(10) + \
" LWLibavVideoSource says the specified video track " + chr(10) + " is not a video track " + chr(10))
}
""") : nop()
# ========== Output =============================================================
(Order == 1) && StopAfterLSMASH ? Eval("""
assert(!LSMASHVideoNotFound || AudioEnabled, \
" FFLMash " + chr(10) + " No video found & audio is disabled " + chr(10))
assert(!LSMASHAudioNotFound || VideoEnabled, \
" FFLMash " + chr(10) + " No audio found & video is disabled " + chr(10))
Output = \
LSMASHAudioNotFound || !AudioEnabled ? V : LSMASHVideoNotFound || !VideoEnabled ? A : audiodub(V, A)
""") : (Order == 1) && StopAfterLWLibav ? Eval("""
assert(!LWLibavVideoNotFound || AudioEnabled, \
" FFLMash " + chr(10) + " No video found & audio is disabled " + chr(10))
assert(!LWLibavAudioNotFound || VideoEnabled, \
" FFLMash " + chr(10) + " No audio found & video is disabled " + chr(10))
Output = \
LWLibavAudioNotFound || !AudioEnabled ? V : LWLibavVideoNotFound || !VideoEnabled ? A : audiodub(V, A)
""") : (Order == 1) ? Eval("""
assert(IsFFMSAudio || FFMSAudioNotFound || !AudioEnabled, \
" FFLMash: Failed to open audio " + chr(10) + err_msg + chr(10))
assert(IsFFMSVideo || FFMSVideoNotFound || !VideoEnabled, \
" FFLMash: Failed to open video " + chr(10) + err_msg + chr(10))
assert(!FFMSVideoNotFound || AudioEnabled, \
" FFLMash " + chr(10) + " No video found & audio is disabled " + chr(10))
assert(!FFMSAudioNotFound || VideoEnabled, \
" FFLMash " + chr(10) + " No audio found & video is disabled " + chr(10))
Output = \
FFMSAudioNotFound || !AudioEnabled ? V : FFMSVideoNotFound || !VideoEnabled ? A : audiodub(V, A)
""") : (Order == 2) && StopAfterFFMS ? Eval("""
assert(!FFMSVideoNotFound || AudioEnabled, \
" FFLMash " + chr(10) + " No video found & audio is disabled " + chr(10))
assert(!FFMSAudioNotFound || VideoEnabled, \
" FFLMash " + chr(10) + " No audio found & video is disabled " + chr(10))
Output = \
FFMSAudioNotFound || !AudioEnabled ? V : FFMSVideoNotFound || !VideoEnabled ? A : audiodub(V, A)
""") : Eval("""
assert(IsLWLibavAudio || LWLibavAudioNotFound || !AudioEnabled, \
" FFLMash: Failed to open audio " + chr(10) + err_msg + chr(10))
assert(IsLWLibavVideo || LWLibavVideoNotFound || !VideoEnabled, \
" FFLMash: Failed to open video " + chr(10) + err_msg + chr(10))
assert(!LWLibavVideoNotFound || AudioEnabled, \
" FFLMash " + chr(10) + " No video found & audio is disabled " + chr(10))
assert(!LWLibavAudioNotFound || VideoEnabled, \
" FFLMash " + chr(10) + " No audio found & video is disabled " + chr(10))
Output = \
LWLibavAudioNotFound || !AudioEnabled ? V : LWLibavVideoNotFound || !VideoEnabled ? A : audiodub(V, A)
""")
return Output }
# ===============================================================================
Edit: Changed a few assert lines. Changes in blue.
StainlessS
30th July 2019, 17:19
Thanks HH, might nick some of that.
currently got mine loading using something like this
/*
Req:- RT_Stats, FFMS, LSmash. CallCmd, MediaInfo CLI v0.7.83+ (may work with later versions)
Function GetSeq(String "vFn",String "aFn",String "Pref"="",Val "fpsNum",Val "fpsDen",bool "Debug",Bool "Verbose")
Specify FrameRate using fpsnum (Numerator) and fpsden (Denominator) # *** INGNORED if AVI ***
num only, eg fpsnum=25.0, FrameRate = 25.0 FPS
num & den, eg fpsnum=24000 fpsden=1001, FrameRate = 23.976 FPS (Both should be type Int).
neither specified FrameRate = UnDefined, ie whatever source filter thinks it is.
ALWAYS:- use named args if using fpsnum/fpsden, argument order may change.
Pref, Default "" {Same as "AIFLDR"). Order in which source filters are tried.
"A" = AviSource() (Only if extension is *.AVI).
"I" = LSmashVideoSource() (Only if extension is an ISO type file, ie mov, mp4, m4v, 3gp, 3g2, mj2, dvb, dcf, m21.).
"F" = FFVideoSource().
"L" = LWLibavVideoSource(), from LSMash.
"D" = DSS2()
"R" = RawSourcePlus().
FFMS Cachefile (used for .ffindex file) directory can be set using global variable GLB_GETSEQ_FFMS_CACHE_DIR, NO trailing backslash.
Global GLB_GETSEQ_FFMS_CACHE_DIR = RT_GetSystemEnv("TEMP") # Set to the Current User's Temp directory.
If Global variable GLB_GETSEQ_DEL_INDEX_ON_CLOSE is True, then will auto Delete both FFMS and LSMash indexes on clip closure.
Global GLB_GETSEQ_DEL_INDEX_ON_CLOSE = True # If true, Auto delete indexes on clip closure. # Could create stub which sets True/False depending upon your own arg.
*/
hello_hello
31st July 2019, 06:48
Thanks HH, might nick some of that.
currently got mine loading using something like this
What I understand of it looks quite clever, although it probably exceeds my needs.
PS. I noticed a silly in my little function which I've edited and hopefully fixed. Changes in blue.
StainlessS
31st July 2019, 07:21
although it probably exceeds my needs.
Well sometimes a source filter dont work proper, and is good to have an alternative, and way to force that alternative. [and 5 is better than 2 # EDIT: Actually 6 is better than 2]
Currently lookin' summick like this
Req:- RT_Stats, CallCmd, MIFO_Lib(MediaInfo script lib), MediaInfo CLI v0.7.83+ (may work with later versions)
Also, FFMS, LSmash, RawSourcePlus or RawSource (one of them), DSS2.
Function GetSeq(String "vFn",String "aFn"="",String "Pref"="",Int "VTrack"=-1,Int "ATrack"=-1,Val "fpsNum"=Undefined,Val "fpsDen"=Undefined,
\ Bool "Cache"=True,String "CacheDir"="",Bool "CacheDel"=False,Int "Threads"=0,Int "RFFMode"=0,String "TimeCodes"="",Int "AdjustDelay"=-1,String "VarPrefix"="",
vFn, Default "", default is NO video file. Can also use VTrack=-2 for no video. If "" and Vtrack != -2, then returns a single frame BlankClip, YV12 640x480, subtitle "No Video File".
aFn, Default "". Where "", will use audio from vFn. Can use ATrack=-2 for no audio.
Pref, Default "" {Same as "AIRFLD"). Order in which source filters are tried.
"A" = AviSource() (Only if extension is *.AVI, WavSource if Audio is WAV).
"I" = LSmashVideoSource() (Only if extension is an ISO type file, ie mov, mp4, m4v, 3gp, 3g2, mj2, dvb, dcf, m21.).
"R" = RawSourcePlus() (Only if extension is ".y4m".) RawSourcePlus if Avs+ and RawSource if Not Avs+.
"F" = FFVideoSource().
"L" = LWLibavVideoSource(), from LSMash.
"D" = DSS2()
VTrack, Default: -1 (auto. Video track number. If -2, disable video.
ATrack, Default: -1 (auto). Audio track number. If -2, disable audio.
Cache, Default True. False disables the writing of an index file (LWLibavSource and FFMS2 only).
CacheDir, Default Undefined. The directory location of the index file written by FFMS2 only. NOTE Directory NOT filename, No backslash at end of folder name.
If cache==true and CacheDir = "%TEMP%" then will be set to system environment user TEMP folder.
CacheDel, Default False [forced False if Cache=false] . If true, then auto delete FFMS[.ffindex] & LWLibavSource[.lwi] index files on clip closure.
Threads, Default 0(auto). The number of threads for LSMASH / FFMS4 to use.
RFFMode, Default 0. Honour repeat field flags (LWLibavSource & FFMS2 only).
FFMS2: 0=false, 1=true, 2=force film.
LWLibavSource: 0=false, 1=true, 2=false.
fpsnum,
fpsden, Defaults Undefined. Framerate for VFR->CFR conversion. # *** INGNORED if AVI ***
Specify FrameRate using fpsnum (Numerator) and fpsden (Denominator)
num only, eg fpsnum=25.0, FrameRate = 25.0 FPS
num & den, eg fpsnum=24000 fpsden=1001, FrameRate = 23.976 FPS (Both should be type Int).
neither specified FrameRate = UnDefined, ie whatever source filter thinks it is. (no VFR->CFR conversion)
Timecodes, Default "". FFMS only, write Matroska Timecodes to filename Timecodes.
AdjustDelay, Default -1. FFMS Only.
VarPrefix, Default "". FFMS only, Variable for FFInfo().
GillesH
31st July 2019, 08:31
Well sometimes a source filter dont work proper, and is good to have an alternative, and way to force that alternative. [and 5 is better than 2]
Totally agree that nothing is perfect and increasing the choice of source filters is a very good solution.
FFMS2 has qualities, but sometimes images are deleted on some more or less clean clips (mainly in H264).
If you use DSS2 on these "dirty" clips (instead of FFMS2), the playback is normal.
I know that DSS2 also have flaws. And it's not always easy to choose between FFMS2 or DSS2.
In fact, the alternative of preferences lies mainly between FFMS2 and DSS2. What do you think ?
"A", "I", "R" could remain a priority. Then, "F" OR "D" in Pref = "". And "L" last.
But I let you choose. It's just a suggestion about the efficiency of the source filters.
When you have time, thank you for publishing the latest script GetSeq with embedded DSS2.
StainlessS
31st July 2019, 15:26
[and 5 is better than 2]
I told you my maths was rubbish [is 6].
EDIT: For the Pref thing, I just envisage people using eg Pref="R" to force a specific source filter, just because the default produces rubbish.
Also, I could probably add a number of audio source filters, eg NicAudio.
EDIT: If you supply eg Pref="R", then if "R" fails, will do remaining Pref options in standard order.
I guess that I could have used something a little more compact than the MIFO_LIB (about 5 pages of script), as we only want VideoCount and AudioCount,
but it does mean that user has available any of the MediaInfo stuff, not such a bad thing, so I'm leaving it as it is.
StainlessS
15th November 2022, 21:45
Avisynthsizer_Mod update see first post.
BugFix update, could get confused by '[' ... ']' which did not enclose "___FILE___" filename.
Can somebody check if OK on XP.
Changes made to Avisynthesizer by StainlessS.
Uses "___FILE___" (thats 3 underscore either side) instead of "%f" which can be mistaken for float spec in eg String() function.
Converted to using "++" aligned splice instead of "+" unaligned splice.
Each file command output on it's own line with a line concatenation "\" backslash.
Does NOT auto install, copy dir somewhere and execute "Install_SendTo.Cmd" to install (can then right click files and "sendTo").
"UnInstall_SendTo.Cmd" to uninstall.
------------------
7 Aug 2013, Added ___FILECNT___
___FILECNT___ Replaced with number of filenames given as arg to Avisynthesizer_Mod,
can be used anywhere in file, but there is no further processing of that line, ie
not on same line as ___FILE___ replacement.
------------------
20 Feb 2014, Added Batch AVS creation mode.
If template has a repeating section {enclosed in square brackets eg [AviSource("___FILE___")]} then will
use the standard mode, creating a single file with multiple sources concatenated.
If template DOES NOT have a repeating section {not enclosed in square backets eg AviSource("___FILE___")}
then will create multiple AVS files, one for each source file.
---------------------------------------------------------------------
Author's email: Warren Young <wdyoung@acm.org>
AVISynthesizer home: http://www.cyberport.com/~tangent/video/asynther.html
----------------------------------------------------------------------
------------- STANDARD MODE (multiple files concatenated) ----
----------------------------------------------------------------------
Here a standard Mode template
#ASYNTHER Simple AVISource reader
# Above line (preceded by '#ASYNTHER') shows as "Simple AVISource reader" in the Avisynthesizer_Mod GUI.
FileCount = ___FILECNT___ # FileCount will be set to the number of files given by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
# Below enclosed in square brackets, so is STANDARD Mode, multiple files are concatenated.
[AVISource("___FILE___")]
Where sending filenames "1.avi", "2.avi", and "3.avi" to above "Simple AVISource reader" Avisynthesizer_Mod template, will generate script like
script
#ASYNTHER Simple AVISource reader
# Above line (preceded by '#ASYNTHER') shows as "Simple AVISource reader" in the Avisynthesizer_Mod GUI.
FileCount = 3 # FileCount will be set to the number of files supplied by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
# Below enclosed in square brackets, so is STANDARD Mode, multiple files are concatenated.
AVISource("C:\Z\1.avi") ++ \
AVISource("C:\Z\2.avi") ++ \
AVISource("C:\Z\3.avi")
----------------------------------------------------------------------
----------------------------------------------------------------------
Another Standard Mode template
#ASYNTHER TEST
# Above line (preceded by '#ASYNTHER') shows as "TEST" in the Avisynthesizer_Mod GUI.
FileCount = ___FILECNT___ # FileCount will be set to the number of files supplied by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
[GetFile("___FILE___")]
Return last
Function GetFile(string s) {
# could do clever stuff in here to decide on which source filter to use and audio stuff
DirectShowSource(s).Trim(0,0) # Trim(0,0), chop/pad audio to same length as video.
BilinearResize(480, 480).ConvertToYUY2.SpatialSoften(5, 2, 3)
}
Where sending filenames "1.avi", "2.avi", and "3.avi" to above "TEST" Avisynthesizer_Mod template, will generate script like
Script
#ASYNTHER TEST
# Above line (preceded by '#ASYNTHER') shows as "TEST" in the Avisynthesizer_Mod GUI.
FileCount = 3 # FileCount will be set to the number of files supplied by SendTo Avisynthesizer_Mod.
# For whatever reason you might want it.
GetFile("C:\Z\1.avi") ++ \
GetFile("C:\Z\2.avi") ++ \
GetFile("C:\Z\3.avi")
Return last
Function GetFile(string s) {
# could do clever stuff in here to decide on which source filter to use and audio stuff
DirectShowSource(s).Trim(0,0) # Trim(0,0), chop/pad audio to same length as video.
BilinearResize(480, 480).ConvertToYUY2.SpatialSoften(5, 2, 3)
}
----------------------------------------------------------------------
--------- BATCH MODE TEMPLATE ---------------------------------
----------------------------------------------------------------------
Here a Batch Mode template (NOT enclosed in square brackets)
A script will be generated for each file SendTo Avisynthesizer_Mod.
#ASYNTHER BATCH-AVISOURCE
# Above line (preceded by '#ASYNTHER') shows as "BATCH-AVISOURCE" in the Avisynthesizer_Mod GUI.
FileCount = ___FILECNT___ # Should always be set to 1 in non-repeating Batch template.
# Below not enclosed in square brackets, so is Non-Repeating ie Batch Mode.
# Batch Mode == Multiple AVS files generated, one for each selected file SendTo Avisynthsizer_Mod.
AVISource("___FILE___")
1--BATCH-AVISOURCE.avs (where 1.avi, 2.avi, and 3.avi sendTo Avisynthesizer_Mod [Only 1st script shown])
#ASYNTHER BATCH-AVISOURCE
# Above line (preceded by '#ASYNTHER') shows as "BATCH-AVISOURCE" in the Avisynthesizer_Mod GUI.
FileCount = 1 # Should always be set to 1 in non-repeating Batch template.
# Below not enclosed in square brackets, so is Non-Repeating ie Batch Mode.
# Batch Mode == Multiple AVS files generated, one for each selected file SendTo Avisynthsizer_Mod.
AVISource("C:\Z\1.avi")
Of course, you can add more script, but where using standard mode where clips are concatenated,
best call some function which ensures that all clips are same size before concatenation.
After concatenation of similar size / colorspace etc, then can apply additional processing to the entire joined clip.
EDIT:
Can somebody check if OK on XP.
First time I've used Visual Studio Community 2019, just wanna make sure it works OK on XP ( dumped my last XP machine recently :( ).
EDIT: What it looks like
https://i.postimg.cc/FHTp3KF0/Avisynthesizer-Mod.jpg (https://postimages.org/)
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.