VideoHelp Forum
+ Reply to Thread
Results 1 to 16 of 16
Thread
  1. Good morning. I have noticed that in some scripts, people add specific names for their vid, and then after a few command lines, they add the term "last", before applying additional filters. My question is: Why is this done? Does this make any significant difference in the way the filters operate? For example, what is the difference between:

    Code:
    MPEG2Source("blah.avi)
    TFM(d2v="blah.avi")
    TDecimate(mode=1)
    Crop(10,0,-4,-0)
    
    #color work
    Tweak (sat=0.72)
    ChromaShift()
    MergeChroma(awarpsharp2(depth=20))
    
    #clean up junk
    super = MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    
    #darken lines and antialiasing
    Toonlite(0.7)
    Santiag(). TurnRight(). Santiag().TurnLeft()

    And


    Code:
    Vid=MPEG2Source("blah.avi")
    TFM(Vid)
    TDecimate(mode=1)
    Crop(10,0,-4,-0)
    
    #color work
    Tweak (sat=0.72)
    ChromaShift()
    MergeChroma(awarpsharp2(depth=20))
    vid=last
    
    #clean up junk
    super = Last. MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    
    #darken lines and antialiasing
    Toonlite(0.7)
    Santiag(). TurnRight(). Santiag().TurnLeft()
    Quote Quote  
  2. Functionally those are the same, and the 1st is more simplified

    But in general, it's mainly for organizational purposes. When you have complex scripts, you often feed different parts into different filter paths and combine them . It's basically a signpost, or node label that you can use later to plug into other sections later . That example script is really only a simple linear chain, so the "last" are redundant

    For example, you might have wanted to insert another original=last after the crop , to weighted merge back parts of the original after some filters, that way you can modulate the strength of effects with more control . Or you might have wanted to use a separately prefiltered version for the motion vectors for different results of mdegrain (often this is done with noisy sources) . Or you might want to filter shadows selectively with differently weighted filtered versions.

    Another reason is some people lose track of implied "last" , and can sometimes get different results that what they intended
    Quote Quote  
  3. Okay, I may be starting to understand this a little bit. So in the example of my script, I would like to apply different functions of Mdegrain2 to different sections of the clip: For most of my clip, the above function works well. However, In some parts of the clip, I'd like to use dct=1 for flicker, while in another part (such as dark scenes), I'd like to lower the blocksize from 8 to 4 to avoid blurring. Taking what you explained and combining it with my limited knowledge of how to use Avisynth, I'm guessing my script would go something like this (just an example):

    Code:
    #source video with the basics, including colorwork
    vid=MPEG2Source("blah.avi"). TFM(Vid). TDecimate(mode=1). Crop(10,0,-4,-0)
    Tweak (sat=0.72). ChromaShift(). MergeChroma(awarpsharp2(depth=20))
    vid=last
    
    #use Mdegrain2 with default settings from clip 0 to clip 1999
    clip1=Trim(clip, 0, 1999)
    super = Last. MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    
    #use Mdegrain2 with DCT=1 from frames 2000 - 2500
    clip2=Trim(clip, 2000, 2500)
    super = Last. MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4,DCT=1)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4,DCT=1)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4,DCT=1)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4,DCT=1)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    
    #back to default settings from frames 2501-2800
    clip3=Trim(2501-2800) 
    *** here I would just paste Mdegrain2 again at default settings
    
    #use Mdegrain2 with lower blocksize for dark scene from frames 4000-4200
    ***repeat step as above with desired parameters
    
    final_clip=clip1 + clip2 + clip3 + clip4
    
    #darken lines and antialiasing for the ENTIRE clip.
    Toonlite(0.7)
    Santiag(). TurnRight(). Santiag().TurnLeft()
    I'm going to try this out right now, HOWEVER, you can imagine having to continuously re-paste this rather long complex function in my script over and over again for different parts of the clip . Is there a way I can make my script simpler and still perform the same task? I'm assuming probably not. In this case, I think that adding the "vid=last" function will only simplify it for me in the sense that I don't have to continuously keep calling my source video with the basics whenever I have to apply a different function.

    Nevertheless, one can only hope.

    Thank you.
    Last edited by Betelman; 5th May 2019 at 15:34.
    Quote Quote  
  4. Basically, most filters require a video stream as an input and produce a video stream as an output. Logically:

    Code:
    output = filter(input, ...)
    If you don't specify inputs and outputs name the name "last" is used:

    Code:
    filter(...)
    logically becomes
    Code:
    last = filter(last, ...)
    The pipe command (.) sends the output of the filter on the left directly to the filter on the right without naming it.

    Now let's look at your script:

    Code:
    vid=MPEG2Source("blah.avi"). TFM(Vid).TDecimate(mode=1).Crop(10,0,-4,-0)
    This is going to fail because vid isn't created until the output of Crop. So you can't reference it in the filter sequence.

    Code:
    Tweak (sat=0.72). ChromaShift(). MergeChroma(awarpsharp2(depth=20))
    This is going to fail because you haven't specified what clip you want to filter. The name "last" will be assumed for the input and the output. Substituting the "last: manually this line looks like:

    Code:
    last = last.Tweak (sat=0.72). ChromaShift(). MergeChroma(awarpsharp2(depth=20))
    But no last has been created yet for Tweak to work on.

    I think this is what you wanted:

    Code:
    MPEG2Source("blah.avi")
    TFM()
    TDecimate(mode=1)
    Crop(10,0,-4,-0)
    Tweak (sat=0.72)
    ChromaShift() # this won't do anything since you don't specify any shifts
    MergeChroma(awarpsharp2(depth=20))
    vid = last # remember the state of the video at this point
    
    #use Mdegrain2 with default settings from clip 0 to clip 1999
    Trim(vid, 0, 1999)
    super = MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    clip1 = last
    
    #use Mdegrain2 with DCT=1 from frames 2000 - 2500
    Trim(vid, 2000, 2500)
    super = MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4,DCT=1)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4,DCT=1)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4,DCT=1)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4,DCT=1)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    clip2 = last
    
    #back to default settings from frames 2501-2800
    Trim(vid, 2501,2800) 
    *** here I would just paste Mdegrain2 again at default settings
    clip3 = last
    
    #use Mdegrain2 with lower blocksize for dark scene from frames 4000-4200
    Trim(vid, 4000,4200) 
    ***repeat step as above with desired parameters
    clip4 = last
    
    clip1 + clip2 + clip3 + clip4
    
    #darken lines and antialiasing for the ENTIRE clip.
    Toonlite(0.7)
    Santiag(). TurnRight(). Santiag().TurnLeft()
    I haven't tested that script so there may still be some errors...
    Last edited by jagabo; 5th May 2019 at 17:29.
    Quote Quote  
  5. Just to expand on what jagabo wrote -


    That's a common pitfall for "implied last" - you're not going to get what you expect because "implied last" isn't final_clip where you have
    final_clip=clip1 + clip2 + clip3 + clip4

    **Whenever you have somethingA=somethingB , that doesn't count as "implied last" . This is a very common pitfall

    If you would have put
    clip1 + clip2 + clip3 + clip4 , like jagabo's script it would have worked, because than is now "implied last" and that output gets fed into Toonlite(0.7), Santiag(). TurnRight(). Santiag().TurnLeft()

    Of if you explicitly called what you wanted (final_clip), it would work too
    final_clip
    Toonlite(0.7)
    Santiag(). TurnRight(). Santiag().TurnLeft()


    I find that's where the labels , with descriptive names help sort things out on more complex scripts . When you explicitly call a name, you know exactly what it's referring to

    Instead of "vid" , or "Clip1" , use something that describes it better

    So it might "v1" for ivtc, tweak, chromashift up to mergechroma, it be "md2" for mdegrain default settings , "md2_dct1" for mdegrain with dct1 , etc... If you had clip1, clip2, clip20 , it would be disasterous to manage on more complex scripts

    For your example, think of it as 3 different versions or states of the video with the entire frame range . You're just mixing and matching them as if you were using an editor, swapping between versions for frame ranges

    Instead of applying trim so early , apply trim at the end, or use a helper function such as replace frames. This way you can mix and match different parts in different order more easily. If you already trimmed it to specific section when you had clip1=last, etc.. you can no longer use that "name" for other frames without redefining it and typing it all out again . It's limiting your options too early . For example if you wanted later on 10000-15000 filtered with md2 ,15001-18000 with md2_dct1 you would use

    ... ++ md2.trim(10000,15000) ++ md_dct1.trim(15001,18000) ++ ...

    You couldn't use the names clip1, clip2 etc.. because those frame ranges were already excluded
    Quote Quote  
  6. Well, I tested it. It worked. Thank you, gentlemen.
    Quote Quote  
  7. Wait, I just took a second look at what you said PDR:

    Instead of applying trim so early , apply trim at the end, or use a helper function such as replace frames. This way you can mix and match different parts in different order more easily. If you already trimmed it to specific section when you had clip1=last, etc.. you can no longer use that "name" for other frames without redefining it and typing it all out again . It's limiting your options too early . For example if you wanted later on 10000-15000 filtered with md2 ,15001-18000 with md2_dct1 you would use

    ... ++ md2.trim(10000,15000) ++ md_dct1.trim(15001,18000) ++ ...

    You couldn't use the names clip1, clip2 etc.. because those frame ranges were already excluded
    It seems to me that you're suggesting I can actually "name" a function in my script (in this case, Mdegrain2--whether with it's default settings or tweaked parameters) so that I can re-use it in other parts of my clip without having to re-type the whole function over and over again, am I correct? This would actually make my script shorter and simpler to manage. Can you show me a brief example, using my script, so that I can see how this works? This would be very good if I can actually do that.
    Quote Quote  
  8. Yes, you can create your own functions:

    Code:
    function md2(clip v)
    {
        v # make v "last"
        backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
        backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
        forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
        forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
        MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    }
    Then call that function within your main script.

    Or you can just name the filtered clips and do your cuts/pastes at the end.

    Code:
    #use Mdegrain2 with default settings from clip 0 to clip 1999
    vid
    super = MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
    MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
    clip1 = last
    
    #use Mdegrain2 with DCT=1 from frames 2000 - 2500
    vid
    super = MSuper(pel=2, sharp=1)
    backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4,DCT=1)
    backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4,DCT=1)
    forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4,DCT=1)
    forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4,DCT=1)
    MDegrain2(sup
    clip2 = last
    
    Trim(clip1, 0, 1999) + Trim(clip2, 2000,2500)
    Quote Quote  
  9. Thank you. I'll test tomorrow.
    Quote Quote  
  10. I tested my clip and I think I'm starting to understand why and when the term "last" is used in a script.

    So far, it seems to be working very well when the goal is to apply different filters/functions to different parts of a video. This prevents me from having to continuously copy/paste long functions (such as Mdegrain), making my script unnecessarily long.

    I created a simple test script with 3 different filters to see how this works, and added instruction comments to myself in the script just in case.

    It worked perfectly when I ran the test. However, because I know that an extra set of eyes never hurts, I welcome you all to look at it at your convenience. Does my sample script reflect the advice given here?

    You gentlemen have been very helpful here. I appreciate your time and advice.


    Code:
    MPEG2Source("blah.d2v")
    TFM("blah.d2v")
    TDecimate(mode=1) 
    Crop(10,0,-6,-0)
    AddBorders(10, 0,6, 0)
    Vid=last
    
    #Now, once you put Vid=last (last line), you're specifying the condition of your original clip (TFM, TDecimate, Crop, AddBorders).  This allows you to apply all other filters/functions to your clip under this condition.  
    #To do this correctly, remember to add the term Vid next to each of your filters/functions below. 
    
    #Grayscale
    Vid. Grayscale()
    Decolor = last  ##-------> you can name your filter whatever you want.  Just for testing purposes, I named it Decolor.
    
    #Flip horizontal
    Vid. FlipHorizontal() #-----> notice that if you remove the "vid" part, it will flip it but in Greyscale.  Why? Because it's doing it based on the most recent "last".  This is why you have to specify your original clip by adding "vid".
    Sideways=last  #------> Whatever name you want.
    
    #Invert colors
    Vid. Invert()
    Weirdo=last
    
    #Specify the function/filter and the frames you wish to apply that function/filter to, and just add them up!
    Trim(Decolor, 0, 500) + Trim(Sideways, 501,600) + Trim(Weirdo, 601, 1000)
    Last edited by Betelman; 7th May 2019 at 06:29.
    Quote Quote  
  11. If you're not using "last" again after this sequence:

    Code:
    #Grayscale
    Vid. Grayscale()
    Decolor = last  ##-------> you can name your filter whatever you want.  Just for testing purposes, I named it Decolor.
    it can be simplified to just:

    Code:
    #Grayscale
    Decolor = Vid. Grayscale() ##-------> you can name your clip whatever you want.  Just for testing purposes, I named it Decolor.
    Same for the other similar sequences.
    Quote Quote  
  12. Ah, now THAT is even better.

    Works like a charm, and simplifies my script.

    Thank you.
    Quote Quote  
  13. As Columbo would say:"one last thing"...

    Following the same logic and pattern for this script, if, for some reason, I wanted to proceed with a portion of my video (ex: frames 1001-1500) as the original clip with no filters, but it's conditions (TFM, TDecimate, etc), I just have to add a clip called:

    Code:
    #Normal clip with it's conditions
    Normal=vid
    and then add it to my other clips as such:

    Code:
    .....+Trim(Normal, 1001, 1500)
    Quote Quote  
  14. Since vid isn't changed in your script you could just use vid in your trims. But making another clip from it called Normal makes it logically a little clearer.
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!