Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
26th April 2017, 22:55 | #1 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
ScriptClip With Multiple Clips
How can I accomplish this:
I want to display AverageLuma of ClipB onto ClipA. Similar to this, but the output needs to overlay on top of ClipA. Code:
ClipB = ClipB.ScriptClip("Subtitle(string(AverageLuma)))" |
26th April 2017, 22:59 | #2 | Link |
Retried Guesser
Join Date: Jun 2012
Posts: 1,373
|
global variables.
EDIT I made a monstrous ScriptClip suite once that animated multiple sprites on screen based on reading a CSV data file. It had a half-dozen global video clips and several dozen nonclip globals. It worked, but was too slow (ahead of its time?) Last edited by raffriff42; 26th April 2017 at 23:08. |
26th April 2017, 23:59 | #4 | Link |
Retried Guesser
Join Date: Jun 2012
Posts: 1,373
|
My 'monstrous' example is a little hard to post, as it stretches across multiple files.
StainlessS has got an example of the concept in his overlay markers thread. https://forum.doom9.org/showthread.php?t=174527 TCmullet posted one a couple of years ago here: https://forum.doom9.org/showthread.p...43#post1751443 I forgot to mention GScript, which is like an advanced ScriptClip (it's got looping!). Native support in AVS+. Here's an example from me that I think is applicable to your question; it does process multiple clips: https://forum.doom9.org/showthread.php?t=172930 I'm not explaining myself clearly, because I'm rusty on the topic and also, I'm pooped right now. Hopefully Gavino will come along and... hey! Last edited by raffriff42; 27th April 2017 at 00:05. |
26th April 2017, 23:59 | #5 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Code:
ClipA = ClipA.ScriptClip("Subtitle(string(ClipB.AverageLuma))") If inside a function, use GRunT: Code:
ClipA = ClipA.GScriptClip("Subtitle(string(ClipB.AverageLuma))", args="ClipB") Last edited by Gavino; 27th April 2017 at 00:01. |
|
27th April 2017, 00:14 | #6 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
I want to add debug code within a function, so I don't want to add a library dependency for a debug option.
That being said, GRunT looks interesting. If we get conditional functions working in AVS+, how about integrating GRunT into AVS+ core? I'm still confused with too much code. I just want something very basic. |
27th April 2017, 00:52 | #7 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
You have only 3 alternatives,
1 ) Clip variable ClipB at main level and scriptclip also at main level. 2 ) Global clip variable ClipB. 3 ) Script Function with Grunt. All have already been suggested.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
27th April 2017, 01:12 | #9 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Code:
ClipB = AviSource("F:\v\StarWars.avi") ClipA = AviSource("F:\v\XMen2.avi") Function Fn(clip ClipA,clip ClipB) {Return ClipA.GScriptClip("Subtitle(string(ClipB.AverageLuma))", args="ClipB")} Fn(ClipA,ClipB) Code:
Global ClipB = AviSource("F:\v\StarWars.avi") ClipA = AviSource("F:\v\XMen2.avi") ClipA.ScriptClip("Subtitle(string(ClipB.AverageLuma))") EDIT: Or Code:
Global ClipB = AviSource("F:\v\StarWars.avi") ClipA = AviSource("F:\v\XMen2.avi") Function Fn(clip ClipA) {Return ClipA.ScriptClip("Subtitle(string(ClipB.AverageLuma))")} Fn(ClipA)
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 27th April 2017 at 01:29. |
27th April 2017, 10:52 | #10 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
StainlessS has correctly described the available solutions.
You might think that this would also work: Code:
Clip1 = ... # whatever Clip2 = ... # whatever Function Fn(clip ClipA, ClipB) { global GClipB = ClipB Return ClipA.ScriptClip("Subtitle(string(GClipB.AverageLuma))") } Fn(Clip1, Clip2) as soon as you call the function more than once with different clips for ClipB, it goes badly wrong: Code:
Clip1 = ... # whatever Clip2 = ... # whatever Clip3 = ... # whatever ... Fn(Clip1, Clip2) ... Fn(Clip1, Clip3) The reason is that the second global assignment to GClipB happens at compile-time, before either of the two run-time scripts ("Subtitle(...)") are evaluated. Hence in both cases they see GClipB identified with Clip3. Even without functions, you can get the following problem: Code:
ClipA = ... # whatever ClipB = ... # whatever ClipA.ScriptClip("Subtitle(string(ClipB.AverageLuma))") ... ClipB = ... # something else ... These are both examples of what I call the 'variable binding problem' and what led me to produce GRunT (which solves it). |
27th April 2017, 14:07 | #11 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Here a quick Multi-Instance hack-up from code developed by Gavino and Martin53
Req RT_Stats, Gscript, Grunt. Code:
Function MysteryX_MI(clip c1,clip c2,Bool "Show") { myName="MysteryX_MI: " Assert(RT_FunctionExist("GScriptClip"),myName+"Essential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337") Assert(RT_FunctionExist("GScript"),myName+"Essential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846") Show=Default(Show,False) Fmt = "%d ] c1AveLum=%6.2f : c2AveLum=%6.2f" # Make format string only once, not at every frame FuncS=""" Function Fn@@@(clip c1,clip c2,Bool Show,String Fmt) { c1 n = current_frame If(Prev@@@ == n) { # Cache failure, requested same frame again. RT_DebugF("%d ] Cache Failure",n,name="Fn@@@_DBUG: ") } Else If(Prev@@@ + 1 != n) { # Init OR Rewind OR User jumped about, dont you just hate users! if(n == 0) { if(Prev@@@ == -666) { RT_DebugF("%d ] Initialized to frame 0",n,name="Fn@@@_DBUG: ") } else { RT_DebugF("%d ] Rewind to frame 0",n,name="Fn@@@_DBUG: ") } } else { RT_DebugF("%d ] User Jumped About",n,name="Fn@@@_DBUG: ") } } if(Show) { RT_Subtitle(Fmt,n, c1.RT_AverageLuma(n=n), c2.RT_AverageLuma(n=n)) } Global Prev@@@=current_Frame # Previous frame (For next interation jump about detect) Return Last } ####################################### # Unique Global Variables Initialization ####################################### Global Prev@@@= -666 # Init vars, Prev = -666 forces initalize ####################################### # Unique Runtime Call, GScriptClip must be a one-liner: ####################################### ARGS = "c2,Show,Fmt" c1.GScriptClip("Fn@@@(last, "+ARGS+")", local=true, args=ARGS) """ ####################################### # Unique Identifier Definition ####################################### GIFunc ="MX" # Function Name, Supply unique name for your multi-instance function. GIName =GIFunc+"_InstanceNumber" # Name of the Instance number Global RT_IncrGlobal(GIName) # Increment Instance Global (init to 1 if not already exists) GID = GIFunc + "_" + String(Eval(GIName)) InstS = RT_StrReplace(FuncS,"@@@","_"+GID) # RT_WriteFile("DEBUG_"+GID+".TXT","%s",InstS) # UnComment to write each unique script function instance to log file Return GScript(InstS) } c1=Avisource("F:\V\StarWars.avi") c2=Avisource("F:\V\XMen2.avi") SHOW=True # Multi-instance with diffent args, compare results a = MysteryX_MI(c1,c2,Show=SHOW) b = MysteryX_MI(c1.Trim(1,0),c2.Trim(1,0),Show=SHOW) StackVertical(a,b) # Bottom clip is 1 frame ahead of top clip (metrics) due to trim Only a bit of testing. EDIT: All Global Variables MUST be Assigned with preceding "Global" or will only be Local, EDIT: Global SomeVar =42 SomeVar = SomeVar + 1 # Local variable Somevar is assigned from Global variable SomeVar and Global variable now hidden by local Specific to the Multi-Instance script above: Each Global should be named and assigned like eg "Global SomeVar@@@ = 42". EDIT: Only use above if many Global variables used. I've posted in the other thread a fix using Grunt for single instance Global.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 27th April 2017 at 16:46. |
27th April 2017, 16:53 | #12 | Link |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,695
|
I get my wrist slapped by Gavino every time I use global variables. I understand the risks, and I am still alive.
Here is one of a dozen scripts where I used one or more global variables in order to get them inside a conditional. I have commented out the second comment block, so it is the second block of code that actually gets executed. When I simply want to view the metrics, I reverse that somewhat tortured process. Code:
#Motion compensated scene detection. Create file with #frame numbers where each scene change happens. Loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll") filename = "e:\Scenes.txt" global dFact = 2.0 global dMin = 2.0 BLOCKSIZE = 8 thSCD1 = (BLOCKSIZE*BLOCKSIZE) * 64 setMTMode(5,6) source = AVISource("e:\fs.avi").convertTOYV12().killaudio() setMTMode(2) prefiltered = source.blur(1.0) superfilt = MSuper(prefiltered,pel=2) super = MSuper(source, pel=2) back_vec = MAnalyse(superfilt,isb=true, blksize=BLOCKSIZE,overlap=2,search=0) forw_vec = MAnalyse(superfilt,isb=false, blksize=BLOCKSIZE,overlap=2,search=0) backcmp = source.MCompensate(super, back_vec, thSCD1=thSCD1, thSCD2=255) forwcmp = source.MCompensate(super, forw_vec, thSCD1=thSCD1, thSCD2=255) global mcomp_clip = interleave(forwcmp, source, backcmp) #--------------------------------- #Next six lines let you view the metrics in order to set detection metrics. /* global script = """Subtitle("\nScene = " + String( (dFact * YDifferenceToNext (mcomp_clip) + dMin ) ) + \ "\nYDiffP = " + String( YDifferenceFromPrevious(mcomp_clip) ), lsp=0)""" global metrics = ScriptClip(mcomp_clip,script) final = ScriptClip(mcomp_clip,"""YDifferenceFromPrevious(mcomp_clip) > (dFact * YDifferenceToNext(mcomp_clip) \ + dMin ) && (current_frame %3 == 1) ? Subtitle(metrics,"New Scene",size=Height/4,align=5) : metrics""") return selectevery(final,3,1) */ #--------------------------------- #Evaluate every 3rd frame using Mod(3) = 1 #Comment out next three lines when viewing metrics with code above #/* WriteFileIf(mcomp_clip, filename, "(YDifferenceFromPrevious(mcomp_clip) > \ (dFact * YDifferenceToNext(mcomp_clip) + dMin )) && (current_frame %3 == 1)", \ "current_frame/3", append = false) #*/ |
27th April 2017, 17:21 | #13 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Quote:
The above Multi-instance function, provides unique named Functions and unique named Globals, and so are safe to use in multi-instance, so long as below name is unique in the entire script, (multi-instance use in same script ok) in this case I've just used "MX". You cannot have two different multi-instance functions both using the same GIFunc name (ie 'MX') Code:
GIFunc ="MX" # Function Name, Supply unique name for your multi-instance function. DEBUG_MX_1.TXT Code:
Function Fn_MX_1(clip c1,clip c2,Bool Show,String Fmt) { c1 n = current_frame If(Prev_MX_1 == n) { # Cache failure, requested same frame again. RT_DebugF("%d ] Cache Failure",n,name="Fn_MX_1_DBUG: ") } Else If(Prev_MX_1 + 1 != n) { # Init OR Rewind OR User jumped about, dont you just hate users! if(n == 0) { if(Prev_MX_1 == -666) { RT_DebugF("%d ] Initialized to frame 0",n,name="Fn_MX_1_DBUG: ") } else { RT_DebugF("%d ] Rewind to frame 0",n,name="Fn_MX_1_DBUG: ") } } else { RT_DebugF("%d ] User Jumped About",n,name="Fn_MX_1_DBUG: ") } } if(Show) { RT_Subtitle(Fmt,n, c1.RT_AverageLuma(n=n), c2.RT_AverageLuma(n=n)) } Global Prev_MX_1=current_Frame # Previous frame (For next interation jump about detect) Return Last } ####################################### # Unique Global Variables Initialization ####################################### Global Prev_MX_1= -666 # Init vars, Prev = -666 forces initalize ####################################### # Unique Runtime Call, GScriptClip must be a one-liner: ####################################### ARGS = "c2,Show,Fmt" c1.GScriptClip("Fn_MX_1(last, "+ARGS+")", local=true, args=ARGS) Code:
Function Fn_MX_2(clip c1,clip c2,Bool Show,String Fmt) { c1 n = current_frame If(Prev_MX_2 == n) { # Cache failure, requested same frame again. RT_DebugF("%d ] Cache Failure",n,name="Fn_MX_2_DBUG: ") } Else If(Prev_MX_2 + 1 != n) { # Init OR Rewind OR User jumped about, dont you just hate users! if(n == 0) { if(Prev_MX_2 == -666) { RT_DebugF("%d ] Initialized to frame 0",n,name="Fn_MX_2_DBUG: ") } else { RT_DebugF("%d ] Rewind to frame 0",n,name="Fn_MX_2_DBUG: ") } } else { RT_DebugF("%d ] User Jumped About",n,name="Fn_MX_2_DBUG: ") } } if(Show) { RT_Subtitle(Fmt,n, c1.RT_AverageLuma(n=n), c2.RT_AverageLuma(n=n)) } Global Prev_MX_2=current_Frame # Previous frame (For next interation jump about detect) Return Last } ####################################### # Unique Global Variables Initialization ####################################### Global Prev_MX_2= -666 # Init vars, Prev = -666 forces initalize ####################################### # Unique Runtime Call, GScriptClip must be a one-liner: ####################################### ARGS = "c2,Show,Fmt" c1.GScriptClip("Fn_MX_2(last, "+ARGS+")", local=true, args=ARGS) seeing as he was party to its conception. EDIT: The unique calling code is below the actual unique functions. EDIT: Produces this in DebugView on first frame Code:
[4024] Fn_MX_1_DBUG: 0 ] Initialized to frame 0 [4024] Fn_MX_2_DBUG: 0 ] Initialized to frame 0
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 27th April 2017 at 17:26. |
|
27th April 2017, 17:39 | #14 | Link | ||
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
Your script has five global variables and not one of them actually needs to be global, even when uncommenting the code to display metrics. When everything is at outer script level, there is never a need for globals! Note also that the input clip to ScriptClip and friends becomes 'last' inside the run-time script, so code such as Quote:
Code:
WriteFileIf(mcomp_clip, filename, "(YDifferenceFromPrevious() > \ (dFact * YDifferenceToNext() + dMin )) && (current_frame %3 == 1)", \ "current_frame/3", append = false) Last edited by Gavino; 27th April 2017 at 17:42. |
||
27th April 2017, 17:42 | #15 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
So there you are John, not so much a bollocking for using Globals, but for your god awful wrong use of them
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
27th April 2017, 23:50 | #16 | Link |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,695
|
I am so embarrassed ...
... but, when faced with my own incompetence, I am reminded of the story my dad was told in lecture hall at M.I.T. on the first day of classes in 1938: "According to all of our engineering calculations, the bumblebee cannot possibly fly. However, the bumblebee, not being able to do these calculations, merrily flies from one flower to the next."So, sometimes my crummy scripts actually work, despite violating all rules, protocols, and social conventions. I do try to behave and follow the rules, whenever I can. Thanks to both StainlessS and Gavino for their continued patience and guidance. |
|
|