VideoHelp Forum




+ Reply to Thread
Results 1 to 27 of 27
  1. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    I am trying to fit varying ranges of video into fixed time periods with all of them rendering at the same framerate.

    Here is a failing script to create 76 frames:

    Animate(front, 0, 15, "Trim", 15,-1, 41,-1) \
    + Animate(front, 16, 35, "Trim", 42,-1, 75,-1) \
    + Animate(front, 36, 55, "Trim", 76, -1, 100, -1) \
    + Animate(front, 56, 61, "Trim", 101, -1, 134, -1) \
    + Animate(front, 62, 75, "Trim", 135, -1, 160, -1)

    In the first invocation, I intend for 15, -1 be the start args and 41, -1 to be the end args. But, I am doing something wrong I assume, because VirtualDub and AvsPmod say that the script creates 5 frames.

    I also tried putting the clip at the start of each set of arguments:

    Animate(0, 15, "Trim", front, 15, -1, front, 41, -1)

    and I get the same result.

    What I think the filter is doing is interpolating the range of values from 15 to 41 so that Trim(front, x, -1) is invoked 16 times with x being the interpolated value. But, that isn't what is happening.

    Have I misunderstood the syntax? Or, am I misunderstanding what Animate does?
    Quote Quote  
  2. You can't use animate with trim

    Describe what end result you want. How did you want the clip organized as the final result ?
    Quote Quote  
  3. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Oh, I should explain that I am expecting the frames created by Animate to be a result, rather than destructively editing some clip. In other words, from arbitrary clip X take frame Y and render it.

    I want to concatenate a range of frames:

    16 frames from the range 15 - 41, then
    19 frames from the range 100 - 76, etc.

    I was hoping that Animate would interpolate the frame numbers, e.g.:

    Resulting frame #00 from specified clip, frame #15
    Resulting frame #01 from specified clip, frame #16
    Resulting frame #02 from specified clip, frame #18
    Resulting frame #03 from specified clip, frame #20
    Resulting frame #04 from specified clip, frame #21
    Resulting frame #05 from specified clip, frame #23
    Resulting frame #06 from specified clip, frame #25
    Resulting frame #07 from specified clip, frame #26
    Resulting frame #08 from specified clip, frame #28
    Resulting frame #09 from specified clip, frame #30
    Resulting frame #10 from specified clip, frame #31
    Resulting frame #11 from specified clip, frame #33
    Resulting frame #12 from specified clip, frame #35
    Resulting frame #13 from specified clip, frame #36
    Resulting frame #14 from specified clip, frame #38
    Resulting frame #15 from specified clip, frame #40

    Except interpolated consistently.

    Why would it not be able to use Trim? I'm using trim to select single frames from the source clip.
    Quote Quote  
  4. EDIT: that's not the full reason why...

    It doesn't work like you think, because there you are returning 2 single frame endpoints but to avisynth, they have no relationship to each other. I think it has to do with the -1 for the current frame , and the way avisynth handles frames - Trim physically cuts frames so you have different lenghts for each increment, but Trim itself does not have an interpolation function

    You would have to so this separately by interpolating the range for each section separately then splicing them together
    Last edited by poisondeathray; 8th Nov 2014 at 14:54.
    Quote Quote  
  5. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Ok. That's the only thing I am using Animate for is to do the interpolation. I don't expect Trim to interpolate anything.

    If Animate doesn't do that then I have to find some other way of doing this. And, I'm having trouble thinking of what Animate would be for then if it doesn't interpolate. But, the description sort of says it interpolates:

    At frame start_frame and earlier, the filter is evaluated with the arguments given by start_args. At frame end_frame and later, the filter is evaluated with the arguments given by end_args. In between, the arguments are linearly interpolated for a smooth transition.

    So, this works (creates a sequence of 2 frames):

    clip1.Trim(10, -1) + clip1.Trim(23, -1)

    or with separate clips:

    clip1.Trim(10, -1) + clip2.Trim(23, -1)

    Do the individual clips have a relationship to each other?

    Before trying Animate I was using sequences like:

    clip1 = clip.Trim(0,15)
    clip2 = clip.Trim(15,51)

    ChangeFPS(AssumeFPS(clip1, 44.0), 30)
    + ChangeFPS(AssumeFPS(clip2, 68.75), 30)

    But, I am getting tired of trying to calculate the FPS transformations. I would like a function to do it.
    Quote Quote  
  6. animate interpolates, but you are changing the length of the clip with each step using trim() - that is problematic will throw an error in avisynth

    When you say "interpolate" I'm assuming from what you've posted that you mean linear interpolation , but snapping to whole frames ? ie. Not blending, or optical flow interpolation (generation of intermediate inbetween frames)
    Quote Quote  
  7. There is a function called remapframes from stickboy
    http://www.avisynth.nl/users/stickboy/

    and an updated version (slightly different syntax)
    http://forum.doom9.org/showthread.php?p=1644971#post1644971

    When you remap frames from a sourceclip that exceeds the frames in the baseclip that you are replacing, frames will be dropped in a linear fashion, just like you've outlined in post #3. I would argue it's not smooth (because the drops aren't "evenly spaced" it it's not an evenly divisible number - but maybe that's the effect you want.) Blends or optical flow/motion interpolation would produce smoother results

    In this case, you are remapping frames from the original clip, back into the original clip, but you can specify different source vs. baseclips.

    Code:
    orig=colorbars().showframenumber()
    
    orig
    remapframes(orig, mappings="[0 15] [15 41]", sourceclip=orig)

    You can load the mappings as a separate text file if you have a lot of them, or you can use implicit "last" if you just want to do them line by line like you were doing in the 1st post

    Code:
    orig=colorbars().showframenumber()
    
    orig
    remapframes(mappings="[0 15] [15 41]", sourceclip=orig)
    remapframes(mappings="[16 35] [42 75]", sourceclip=orig)
    remapframes(mappings="[36 55] [76 100]", sourceclip=orig)
    remapframes(mappings="[56 61] [101 134]", sourceclip=orig)
    remapframes(mappings="[62 75] [135 160]", sourceclip=orig)
    
    Trim(0,75)
    In this example, the original source was longer than 76 frames, so you have to trim it down to 76 frames (frame 76 onward just carry on with the regular original numbering)
    Last edited by poisondeathray; 8th Nov 2014 at 17:05.
    Quote Quote  
  8. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Thanks, I am starting to look at it. But, I am so confused now. I don't know how the scripts I have written are working. And, so I am unsure what remapframes does.

    The avisynth filters are all destructive? To select frames for rendering I have to delete the frames that I don't want rendered?

    With this:

    a = AVISource("a.avi").Loop(1, 0, 9) # a.avi has 180 frames
    b = AVISource("a.avi").Loop(1, 0, 9)

    a + b

    I get 360 frames... Why isn't it either 20 or 380?
    Quote Quote  
  9. Originally Posted by cheyrn View Post
    Before trying Animate I was using sequences like:

    clip1 = clip.Trim(0,15)
    clip2 = clip.Trim(15,51)

    ChangeFPS(AssumeFPS(clip1, 44.0), 30)
    + ChangeFPS(AssumeFPS(clip2, 68.75), 30)

    But, I am getting tired of trying to calculate the FPS transformations. I would like a function to do it.
    As a function:

    Code:
    function DecimateToNFrames(clip vid, int N)
    {	
        ChangeFPS(vid, vid.framerate * N / vid.FrameCount)
        AssumeFPS(vid.framerate)
    }
    Then call it with:

    Code:
    WhateverSource()
    DecimateToNFrames(last.Trim(15, 41), 15)\
    +DecimateToNFrames(last.Trim(100, 176), 19)
    Quote Quote  
  10. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Thank you. I guess if I wish it was a function, I could make it a function... That looks like it is going to be the solution to what I am working on right now.

    Everything I know is wrong though. How does this work:

    c1 = AVISource("a.avi") # 180 frames

    Loop(c1.Trim(100, -1), 1) + Loop(c1.Trim(0, -1), 1) + Loop(c1.Trim(44, -1), 1)

    Renders the 101th, 0th and 44th frame. If Trim is destructive, wouldn't there be no 45th frame?
    Quote Quote  
  11. Originally Posted by cheyrn View Post
    Thanks, I am starting to look at it. But, I am so confused now. I don't know how the scripts I have written are working. And, so I am unsure what remapframes does.

    The avisynth filters are all destructive? To select frames for rendering I have to delete the frames that I don't want rendered?

    With this:

    a = AVISource("a.avi").Loop(1, 0, 9) # a.avi has 180 frames
    b = AVISource("a.avi").Loop(1, 0, 9)

    a + b

    I get 360 frames... Why isn't it either 20 or 380?




    Define what you mean by "destructive" ?

    In the world of video editing, "destructive editing" means changes to the original file. So in that sense, it's not destructive. Same thing as if you import video into as standard NLE - that's "Non destructive editing" because original file is just referenced, but not altered in anyway



    Loop repeats those frames within the sequence . Loop isn't the same thing as Trim - Everything outside the loop range still continues on as normal

    Loop(1,0,9) will do nothing because frames 0-9 inclusive in the original sequence will be looped once. ie. 0,1,2,3,4,5,6,7,8,9,10,11.... . But that is what happens "normally"

    However if I use Loop(2,0,9) , 0-9 will be run twice (once normal, plus one more), then continue on as normal . ie. 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,10,11...
    Last edited by poisondeathray; 8th Nov 2014 at 18:56.
    Quote Quote  
  12. Originally Posted by cheyrn View Post
    Thank you. I guess if I wish it was a function, I could make it a function... That looks like it is going to be the solution to what I am working on right now.

    Everything I know is wrong though. How does this work:

    c1 = AVISource("a.avi") # 180 frames

    Loop(c1.Trim(100, -1), 1) + Loop(c1.Trim(0, -1), 1) + Loop(c1.Trim(44, -1), 1)

    Renders the 101th, 0th and 44th frame. If Trim is destructive, wouldn't there be no 45th frame?
    This is expected because loop is set to 1

    Trim(100,-1) should return frame 100 only
    Trim(0,-1) should return frame 0 only
    Trim(44,-1) should return frame 44 only

    So it should return 3 frames : 100,0,44


    If you set the loop to 2, it would duplicate each frame

    Loop(c1.Trim(100, -1), 2) + Loop(c1.Trim(0, -1), 2) + Loop(c1.Trim(44, -1), 2)

    Should return 100,100,0,0,44,44



    RE: destructive or not. Each time, you referenced "c1" which has frames 0-179 . "c1" is defined as the original source. So in that sense it's not "destructive", and why you get frame number 44 - because you're "starting all over again" by referencing c1

    You might be confused when "last" is implied

    If I took that c1 clip, then applied sequential trims, then it becomes "destructive", unless you reference c1 (or another clip) again

    e.g

    c1 #frames 0-179
    Trim(0,100) # now current clip only contains frames 0-100


    But this actually means

    c1
    Trim(last, 0,100)
    # other filter

    So all other filters now have implied "last" and deal with the "new" 0-100 frame sub clip

    But If I call "c1" again, that refers to the original 0-179 frame clip, not the current 0-100 frame sub clip
    Last edited by poisondeathray; 8th Nov 2014 at 19:00.
    Quote Quote  
  13. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Thanks. I overlooked "last" in the getting started document. And, I understand the difference between loop and trim, and why referencing the clip variable again "starts over".

    I'm still a bit confused about some things, though. Doesn't Animate accumulate data in "last"? Or, accumulate it somewhere and leave it in last?

    I read that functions always return a new clip. So, why doesn't this accumulate segments of the clip?

    function segment(clip c, int start, int end)
    {
    c.Trim(start, end)
    }

    Animate(some_clip, 0, 9, "segment", 0, 3, 4, 9)

    Not understanding this still leaves me unsure about using remapframes.

    Oh, about "destructive", I meant modifying existing data, as opposed to creating new video data.

    If you "filter" coffee, it creates new coffee without some stuff, as far as the coffee ending up in a different container. It is destructive if you repeatedly dip a tea strainer into a container of coffee to remove coffee grounds.
    Last edited by cheyrn; 10th Nov 2014 at 13:57. Reason: OCD
    Quote Quote  
  14. It doesn't "accumulate" , because you're using trim. If you used something like levels() or some other filter it would work by changing the values each frame , interpreting linearly between the endpints. So you could create a fade to black for example. Trim won't work with animate() because it changes the framecount each step

    remapframes() uses a different mechanism. It literally "remaps" frames from one clip into the other clip. If you've ever done video editing, it's like splicing one clip into another, or another way of looking at it for the end result is overlaying a clip over a range of frames, replacing the old frames (It doesn't use overlay, but that's the same effect). Normally the frame count is the same - e.g. you replace 10 frames with 10 frames from another clip. However, if the framecount is different, it does linear interpolation
    Quote Quote  
  15. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    I thought that function parameters were copies of the values passed to them as arguments. So, it couldn't be changing the clip. Or, does animate discard the results of functions? Or is "result" the wrong concept regarding return from a function?
    Quote Quote  
  16. Originally Posted by cheyrn View Post
    I thought that function parameters were copies of the values passed to them as arguments. So, it couldn't be changing the clip. Or, does animate discard the results of functions? Or is "result" the wrong concept regarding return from a function?


    It's like turning a knob or dial for settings. If you're familiar with setting "keyframes" for effects in editing programs it's analogous to that

    For example, If I change the "brightness" from 0-100 from frames 0-10 . (I'm just using "brightness" as an example, it's not a real filter called by "brightness", but can be used in other filters)

    Frame 0 would be 0
    Frame 1 would be 10
    Frame 2 would be 20
    .
    .
    .
    Frame 10 would be 100

    The resulting clip is 11 frames long, frames zero to 10 inclusive, and the brightness increases over those frames



    You can't use something like trim(), because each step changes the timeline framecount.
    Quote Quote  
  17. Originally Posted by cheyrn View Post
    I'm still a bit confused about some things, though. Doesn't Animate accumulate data in "last"? Or, accumulate it somewhere and leave it in last?
    You get one frame at a time out of Animate, not one video at a time.
    Quote Quote  
  18. Member
    Join Date
    Sep 2012
    Location
    Australia
    Search Comp PM
    I think I see it, Animate Works with frames, "+" works with clips, so when you pass a series of frames to "+" it converts just those frames into a clip and that's what you're left with, a clip consisting of only those frames.
    Quote Quote  
  19. Member
    Join Date
    Sep 2012
    Location
    Australia
    Search Comp PM
    Oh, right, he's not actually appending each of the frames he creates as he runs them through animate, so in the end he just ends up with the single frame pumped out by the last call to trim().
    Quote Quote  
  20. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    I still don't get it. But, I can understand if this thread is getting tiresome and don't feel you have to keep helping me.

    I don't need to use Animate. But, it seems to point out something that I don't understand about AviSynth. The original example using Trim was creating one frame at a time (or trying to). So, I don't understand the comment about getting one frame at a time vs. one video at a time from Animate.

    I thought that functions can't modify a value that they are passed. And there is a comment in the description of functions that they always create a new value and never modify a value. So, whether it is something like a brightness filter or not, how can it be changing the framecount?

    I also don't follow the comment about frames vs. clips and +. Does Animate use +? If + converts just the frames it's passed (as opposed to I don't know what), how does that mean that it produces one frame?
    Quote Quote  
  21. Originally Posted by cheyrn View Post
    I still don't get it. But, I can understand if this thread is getting tiresome and don't feel you have to keep helping me.

    I don't need to use Animate. But, it seems to point out something that I don't understand about AviSynth. The original example using Trim was creating one frame at a time (or trying to). So, I don't understand the comment about getting one frame at a time vs. one video at a time from Animate.

    I thought that functions can't modify a value that they are passed. And there is a comment in the description of functions that they always create a new value and never modify a value. So, whether it is something like a brightness filter or not, how can it be changing the framecount?

    I also don't follow the comment about frames vs. clips and +. Does Animate use +? If + converts just the frames it's passed (as opposed to I don't know what), how does that mean that it produces one frame?



    Trim cuts the clip. It changes the framecount. Avisynth will return the 1st argument only. Even if it worked as you thought it did, nothing in your function says "append" or join these clips ("+" in avisynth). i.e Those two endpoints have no relationship to each other - i.e they aren't joined

    If you take the brightness example above, nothing is cut. Trim() isn't used. It's 1 whole single video clip. Each frame is "already joined" because nothing was cut in the first place . All animate does, is change the filter settings per frame, like turning a knob
    Quote Quote  
  22. First consider a simple function with animate:

    Code:
    function NullFunc(clip c)
    {
        return(c)
    }
    
    Animate(some_clip, 0, 9, "NullFunc")
    NullFunc() doesn't do anything it just returns the clip that was input. When AviSynth starts processing at frame 0 it calls NullFunc() via Animate(). NullFunc() returns some_clip. AviSynth outputs frame 0 of that clip -- ie, frame 0 of some_clip. At the next frame, frame 1, NullFunc() returns the some_clip clip again. AviSynth outputs frame 1 of that clip -- which is frame 1 of some_clip. For frame 2 NullFunc() returns some_clip again. AviSynth outputs frame 2 from that clip... So the output is simply some_clip. AviSynth does not append some_clip 10 times.

    Now consider a slightly more complex funtion:

    Code:
    function Trim1(clip c)
    {
        return(c.Trim(1,0))
    }
    
    Animate(some_clip, 0, 9, "NullFunc")
    Trim1() simply removes the first frame of the input video. For the first frame Trim1() returns the clip minus the first frame. AviSynth outputs frame zero of the trimmed clip -- frame 1 of some_clip. For the next frame Trim1() returns some_clip minus the first frame again. AviSynth outputs frame 1 of that clip, frame 2 of some_clip. The net result is some_clip minus its first frame.

    Now consider your script from earlier:

    Code:
    function segment(clip c, int start, int end)
    {
      c.Trim(start, end)
    }
    
    Animate(some_clip, 0, 9, "segment",  0, 3, 4, 9)
    The process is the same. It doesn't matter that your trim points are changing. When processing frame N AviSynth outputs frame N of the clip returned by segment(). It does not append the results of all the trims, it outputs only one frame from each trim.
    Quote Quote  
  23. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Trim is not cutting the copy of the clip that it is passed by value from the function call? Trim is able to modify a variable that isn't global and is outside of the function? Or, is the variable like a copy of a pointer, so you can't change the pointer but you can change what it's pointing at?

    If the later is true, then what is the different mechanism that does this compared to how segment is independent of clip here and Trim doesn't change it:

    clip = AVISource("...")
    segment = clip.Trim(0, 3)

    segment.framecount # 4
    clip.framecount # 100

    How is the filter able to modify the clip? Variable scoping rules are different for functions passed to Animate?
    Quote Quote  
  24. Member
    Join Date
    Sep 2012
    Location
    Australia
    Search Comp PM
    No they're not, Trim (0, -1) returns a clip with a length of one frame, animate has no built in function to change the length of a clip, and you haven't written one in either. Exactly what makes you think anything you've written will change a 1 frame clip into a clip of any other size?

    It may be possible to do what you're trying to do with Animate, a custom function and maybe a global variable to get the final clip out of the animate function, but once you understand what you're doing you'll see it would never work.

    think about this:

    a = last
    Trim (a, 0, -1)
    Trim (a, 1,-1)
    Trim (a, 2, -1)
    Trim (a, 3, -1)

    According to your logic, that should return a clip 4 frames long. Does it?
    Quote Quote  
  25. Member
    Join Date
    Sep 2012
    Location
    Australia
    Search Comp PM
    If you think Animate is passing a clip consisting of one frame to these filters and then appending the resulting frame, what the hell is Trim(3,-1) going to return?

    If you think Animate is creating as many instances of the filter as there are frames and returning one frame from each clip, how does it know which frame to return if you've trimmed the clip to have a frame count smaller than the number of the original frame?
    Quote Quote  
  26. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    Probably I just need to finish reading the documentation. I don't mean to be asserting that Animate works some way. Obviously it doesn't work the way I can think of it working.

    I am trying to figure out where my logic is wrong. The point of that is that is to find out if there is another aspect of AviSynth that I am still not understanding.

    This does return 4 frames:

    clip = AVISource("...")

    copy1 = clip
    copy2 = clip
    copy3 = clip
    copy4 = clip

    copy1.Trim(1, -1) + copy2.Trim(2, -1) + copy3.Trim(3, -1) + copy4.Trim(4, -1)

    MessageClip("Last frames: " + string(last.framecount)) # indicates 4

    The copies represent what I am imagining a function's parameter would be.

    People have been saying that Animate doesn't splice what is returned and so it is like you indicate. last is repeatedly being set to 1 frame.

    So. Does Animate, do something like:

    Animate(clip, 0, 3, "arity2function", 0, 0, 99, 99)

    copy = clip
    clip = arity2function(copy, 0, 0)
    copy = clip
    clip = arity2function(copy, 49, 49)
    copy = clip
    clip = arity2function(copy, 50, 50)

    So, it simply passes arguments to a function and replaces the entire clip after each step? Or, something similar that replaces or modifies the entire clip? Or, am I not understanding something basic about how filters work, or how functions work, or something else.
    Quote Quote  
  27. Member
    Join Date
    Nov 2005
    Location
    United States
    Search Comp PM
    I think I figured it out. Looking at code it seems to do something like this:

    copy = clip
    clips[0] = arity2function(copy, 0, 0)
    copy = clips[0]
    clips[1] = arity2function(copy, 49, 49)
    copy = clips[1]
    clips[2] = arity2function(copy, 50, 50)

    It forms a pipeline where each stage gets the clip from the previous stage. Essentially, it does the "reduce" list operation.

    Since the example function returns 1 frame, the next stage tries to find the nth frame in the 1 frame clip and there is none.

    It's confusing for me because to animate is to orchestrate and to filter is to transform.

    A cow is a filter. Grass goes in and pies come out. A hammer is not a filter, it starts with something and at the end the something is different.

    An animated corpse is one that has been made to move. If you dip it in glue, then pass it along where the glued corpse is sent through a wind tunnel with feathers blowing in it and then it's passed on where the feathered glued corpse is diced into cubes etc. etc. You are not animating a corpse.

    In any case, the function of animate doesn't seem to indicate something about filters or functions AviSynth that wasn't clarified for me after the intial post. Thanks
    Quote Quote  
Visit our sponsor! Try DVDFab and backup Blu-rays!