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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 26th April 2017, 22:55   #1  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
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)))"
Any idea?
MysteryX is offline   Reply With Quote
Old 26th April 2017, 22:59   #2  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
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.
raffriff42 is offline   Reply With Quote
Old 26th April 2017, 23:25   #3  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
How do you write it?
MysteryX is offline   Reply With Quote
Old 26th April 2017, 23:59   #4  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
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.
raffriff42 is offline   Reply With Quote
Old 26th April 2017, 23:59   #5  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by MysteryX View Post
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)))"
Code:
ClipA = ClipA.ScriptClip("Subtitle(string(ClipB.AverageLuma))")
No need for global variables if at outer script level (not inside a function).
If inside a function, use GRunT:
Code:
ClipA = ClipA.GScriptClip("Subtitle(string(ClipB.AverageLuma))", args="ClipB")
__________________
GScript and GRunT - complex Avisynth scripting made easier

Last edited by Gavino; 27th April 2017 at 00:01.
Gavino is offline   Reply With Quote
Old 27th April 2017, 00:14   #6  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
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.
MysteryX is offline   Reply With Quote
Old 27th April 2017, 00:52   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
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 ???
StainlessS is offline   Reply With Quote
Old 27th April 2017, 00:56   #8  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
What is the basic syntax to create global script variable ClipB?
MysteryX is offline   Reply With Quote
Old 27th April 2017, 01:12   #9  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
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))")
both tested/working

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.
StainlessS is offline   Reply With Quote
Old 27th April 2017, 10:52   #10  |  Link
Gavino
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)
and it does, but ...
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)
Here, despite appearances, Clip3 will be used inside both ScriptClip instances.
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
...
Here, the value of ClipB inside the ScriptClip call will be the 'something else', not the original value, again because the second assignment happens before the run-time script is evaluated.

These are both examples of what I call the 'variable binding problem' and what led me to produce GRunT (which solves it).
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 27th April 2017, 14:07   #11  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
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
EDIT: Small fix to debug output when user jumped about

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.
StainlessS is offline   Reply With Quote
Old 27th April 2017, 16:53   #12  |  Link
johnmeyer
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)
#*/
johnmeyer is offline   Reply With Quote
Old 27th April 2017, 17:21   #13  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Quote:
Originally Posted by johnmeyer View Post
I get my wrist slapped by Gavino every time I use global variables.
And rightly so

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.
With two instances produces these results:- (The RT_WriteFile() line uncommented)

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)
DEBUG_MX_2.TXT
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)
I feel quite sure that the big G would not give you a hard time for using such an arrangement as above,
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.
StainlessS is offline   Reply With Quote
Old 27th April 2017, 17:39   #14  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by johnmeyer View Post
Here is one of a dozen scripts where I used one or more global variables in order to get them inside a conditional.
I think you've chosen a bad example here, John.
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(mcomp_clip) > \
           (dFact * YDifferenceToNext(mcomp_clip) + dMin )) && (current_frame %3 == 1)", \
            "current_frame/3", append = false)
can be replaced by
Code:
WriteFileIf(mcomp_clip, filename, "(YDifferenceFromPrevious() > \
           (dFact * YDifferenceToNext() + dMin )) && (current_frame %3 == 1)", \
            "current_frame/3", append = false)
eliminating a possible reason for introducing a global variable when used inside a function (for example if mcomp_clip had been a function parameter).
__________________
GScript and GRunT - complex Avisynth scripting made easier

Last edited by Gavino; 27th April 2017 at 17:42.
Gavino is offline   Reply With Quote
Old 27th April 2017, 17:42   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
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 ???
StainlessS is offline   Reply With Quote
Old 27th April 2017, 23:50   #16  |  Link
johnmeyer
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.
johnmeyer is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 01:31.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.