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?
+ Reply to Thread
Results 1 to 27 of 27
-
-
You can't use animate with trim
Describe what end result you want. How did you want the clip organized as the final result ? -
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. -
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 togetherLast edited by poisondeathray; 8th Nov 2014 at 14:54.
-
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. -
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) -
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)
Last edited by poisondeathray; 8th Nov 2014 at 17:05.
-
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? -
As a function:
Code:function DecimateToNFrames(clip vid, int N) { ChangeFPS(vid, vid.framerate * N / vid.FrameCount) AssumeFPS(vid.framerate) }
Code:WhateverSource() DecimateToNFrames(last.Trim(15, 41), 15)\ +DecimateToNFrames(last.Trim(100, 176), 19)
-
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? -
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.
-
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 clipLast edited by poisondeathray; 8th Nov 2014 at 19:00.
-
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
-
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 -
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. -
-
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.
-
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().
-
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 -
First consider a simple function with animate:
Code:function NullFunc(clip c) { return(c) } Animate(some_clip, 0, 9, "NullFunc")
Now consider a slightly more complex funtion:
Code:function Trim1(clip c) { return(c.Trim(1,0)) } Animate(some_clip, 0, 9, "NullFunc")
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)
-
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? -
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? -
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? -
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. -
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