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. |
2nd March 2008, 00:29 | #1 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
CutFrames: Opposite of Trim
Code:
# CutFrames() - March 9th, 2008 # Cut a range of frames from a single a/v clip. # # Parameters: # int start - start of cut # int end - end of cut # int duration - duration of fade between cuts # int fade_color - blank clip color (usually in Hex RGB) used at start or end of clip only # string transition - pass a function name, if user wants to use something other then Dissolve # val opt1 - pass a variable to the fade/transition function # val opt2 - pass a variable to the fade/transition function # val opt3 - pass a variable to the fade/transition function # # Preconditions: # start >= 0 ; start can not be a negative value # start-duration > 0 # start = 0 then a fade in is used # end = 0 cut till the end of the clip and a fade out is used # start != end ; mainly a condition to check for start == 0 and end == 0 function CutFrames(clip c, int start, int end, int "duration", int "fade_color", string "transition", val "opt1", val "opt2", val "opt3") { # Set Defaults duration = default(duration, 0) transition = default(transition, "Dissolve") fade_color = default(fade_color,$000000) opt1=(Defined(opt1) ? ", "+string(opt1): "") opt2=(Defined(opt2) ? ", "+string(opt2): "") opt3=(Defined(opt3) ? ", "+string(opt3): "") opts = opt1 + opt2 + opt3 end = c.Framecount()-1 == end ? 0: end d = c.BlankClip(duration, color=fade_color) # Check For Any Unreasonable Inputs Assert(start >= 0, "CutFrames: Starting Frame[" + String(start) + "] must be a positive value") Assert((start == 0) || (start-duration >= 0), "CutFrames: Starting Frame[" + String(start) + "] must be greater then or equal to" + Chr(10) + " inputed duration[" + String(duration) + "]") Assert(start <> end, "CutFrames: Start and End cannot both be the same") Assert(end <= c.Framecount()-1, "CutFrames: End[" + String(end) + "] is greater then " + Chr(10) + "clip length[" + String(c.Framecount()-1) + "]") Assert((end == 0) || (end+duration <= c.Framecount()-1), "CutFrames: Ending Frame[" + String(end) + "] must be less then or equal to" + Chr(10) + " last frame - duration [" + String(c.Framecount()-1-duration) + "]") # Select uncut frames (or blanks) as transition components: clip1 = (start == 0) ? d : c.trim(0, -start) clip2 = (end == 0) ? d : c.trim(end+1, 0) # Perform transition: Eval(transition + "(clip1, clip2," + string(duration) + opts + ")") } CutFrames(200, 400) - Cut out frames 200-400 from the video. Resulting length: 799 CutFrames(200, 400, 20) - Cut out frames 200-400 using Dissolve() for a 20 frame fade. Transition starts on frame 180; Resulting length: 779 CutFrames(210, 390, 20) - Cut out frames 210-390 using Dissolve() for a 20 frame fade. Transition starts on frame 190; Resulting length: 799 CutFrames(400, 200, 20) - Replay frames 200-400 using Dissolve() with a 20 frame fade. Transition starts on frame 380; Resulting length: 1179 CutFrames(200, 400, 20, $000000, "TransSwing", false, 1, 1) - Cut out frames 200-400 using TransSwing() for a 20 frame fade, passing 3 additional arguments to TransSwing(). Transition starts on frame 180; Resulting length: 779 CutFrames(0, 400) - Cut out frames 0-400 from the video. Resulting length: 599 CutFrames(0, 400, 20) - Cut out frames 0-400 from the video using Dissolve() for a 20 frame fade from black (FadeIn). Resulting length: 599 CutFrames(200, 0) - Cut out frames 200-1000 from the video. Resulting length: 199 CutFrames(200, 0, 20) - Cut out frames 200-1000 from the video using Dissolve() for a 20 frame fade into black (FadeOut). Resulting length: 199 CutFrames(0, 400, 20, $FF0000) - Cut out frames 0-400 from the video using Dissolve() for a 20 frame fade from red (FadeIn). Resulting length: 599 Tips:
Footnotes: Loop() can delete frames as well. Second to last example on page. Future Ideas: This is a RFC (Request For Comments), your input is greatly appreciated. Edits: March 4th, 2008: Got rid of ugly logic - Thanks Gavino March 7th, 2008: Added error checking and FadeIn/FadeOut - Thanks stickboy for pointing out how this can fail and for header suggestions March 8th, 2008: Improved End error checking March 8th, 2008: Fixed cut points, now they are excluded - Thanks Gavino. Examples changed as a result. March 9th, 2008: More code cleanup, added color option to fadeI/O, fixed end boundary condition - Thanks Gavino.
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer Last edited by mikeytown2; 15th March 2008 at 14:04. |
2nd March 2008, 12:54 | #2 | Link |
AviSynth Enthusiast
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
|
Even your simple version is problematic. Be careful when using Trim with variable arguments.
|
2nd March 2008, 15:02 | #3 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Thanks for pointing this out! After looking at your functions and reading the headers, i think i will use Trim3.
http://avisynth.org/stickboy/jdl-util.avsi You really like Assert, i had to go look it up. http://avisynth.org/mediawiki/Intern...trol_functions So reworking my first example it should be something like this Code:
function CutFrames(clip c, int start, int end) { return c.trim3(0, start) + c.trim3(end, c.Framecount()) }
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer |
2nd March 2008, 21:16 | #4 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
CutFrames(4444, 5555) CutFrames(2222, 3333) ... Then if you decide to remove any of the cuts, the frame numbers in the other ones will still be valid. Gavino |
|
3rd March 2008, 08:08 | #5 | Link |
Errant Knight
Join Date: Oct 2004
Location: St Louis, M0 US
Posts: 364
|
Hello,
Lots of ways to skin this cat, here is one I use often, it is easier for me to understand weeks, maybe months, into something. Code:
some source filter or filters # source filters return a clip "last" # which is equivalent to " last = source filter " # unless assigned to a clip variable, # (for example " source = source filter ") trim(framestart, frameend) + trim(fs, fe) + trim(fs, fe) + trim(fs, fe) # yep that sucks, and if there are a lot of them it really sucks aclip = trim(fs, fe) # aclip is assigned the clip returned by " trim(last, fs, fe) " aclip = aclip + trim(fs, fe) # The just keep doing it aclip = aclip + trim(fs, fe) aclip = aclip + trim(fs, fe) aclip = aclip + trim(fs, fe) aclip = aclip + trim(fs, fe) aclip = aclip + trim(fs, fe) aclip = aclip + trim(fs, fe) # want to comment one out #aclip = aclip + trim(fs, fe) aclip = aclip + trim(fs, fe) # at this point the script's output is still equal to " last ' # aclip # which is the same as last = aclip Code:
# add dissolves between all clips aclip = trim(fs, fe) aclip = Dissolve(aclip, trim(fs, fe), 60) aclip = Dissolve(aclip, trim(fs, fe), 60) aclip = Dissolve(aclip, trim(fs, fe), 60) aclip = Dissolve(aclip, trim(fs, fe), 60) aclip |
3rd March 2008, 19:30 | #6 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
@Gavino Thank you for the reverse order hint, that makes this a lot simpler to implement.
@Ebobtron The option to dissolve/blend the clips would be a good thing. [http://avisynth.org/mediawiki/Dissolve] In the long run, i would like to be able to support any transition. [http://avisynth.org/vcmohan/TransAll/docs/index.html] I think i would have to use an eval statement in order to do it. [http://avisynth.org/mediawiki/Intern...trol_functions] In terms of the structure of the AddCutPoint function, i think it would look something like this AddCutPoint(clip c, int start, int end, string transition, int duration) where clip c is the a/v stream to cut up. int start is the starting frame to cut, int end would be the last or ending frame to cut. String transition would be the function name, and int duration is how long the transition will last. This function call would then store these 5 values into a 5 dim array. the only question i have is about storing a clip into an array; is this a bad idea? Int's and strings shouldn't be an issue but i'm not sure about the clip variable. The reason for storing the clip variable would be in the case of multiple a/v clips in a single script. Anyway here is the simple script with transitions added Code:
function CutFrames(clip c, int start, int end, string "transition", int "duration") { duration = default(duration, 0) return Defined(transition) ? Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", c.Framecount()), " + string(duration) + ")") : c.trim(0, start) + c.trim(end, c.Framecount()) } CutFrames(200, 800, "Dissolve", 60) EDIT I think i like this function better Code:
function CutFrames(clip c, int start, int end, int "duration", string "transition") { duration = default(duration, 0) transition = default(transition, "Dissolve") return Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", c.Framecount()), " + string(duration) + ")") } CutFrames(200, 800, 60)
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer Last edited by mikeytown2; 3rd March 2008 at 22:28. |
4th March 2008, 01:30 | #7 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
Gavino |
|
4th March 2008, 03:31 | #8 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
@Gavion I was planing on using a sort array method, to order the array from largest to smallest, inside the ProcessCutPoints() function. Without your helpful input, i probably would have done it another way, with a lot of math calc involved.
After looking at [http://avisynth.org/mediawiki/Arrays] and [http://avslib.sourceforge.net/functi...raycreate.html], i have decided to drop the idea of processing multiple clips simultaneously. The ProcessCutPoints() function should clear the arrays, so that it can still do cuts on multiple clips; just not all at the same time. Speaking of arrays i think 4 single dim arrays would be the easiest to do with the avisynth language. I just need a way to sort this, otherwise as Gavion has pointed out, my simple method is quite adequate. Any input would greatly be appreciated, should i go for the 2 step process or should i leave this as is? EDIT Multiple options can be passed to the blending function now Code:
function CutFrames(clip c, int start, int end, int "duration", string "transition", string "opt1", string "opt2", string "opt3") { duration = default(duration, 0) transition = default(transition, "Dissolve") return \ Defined(opt3) ? Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", c.Framecount()), " + string(duration) + ", " + String(opt1) + ", " + String(opt2) + ", " + String(opt3) + ")") : \ Defined(opt2) ? Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", c.Framecount()), " + string(duration) + ", " + String(opt1) + ", " + String(opt2) + ")") : \ Defined(opt1) ? Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", c.Framecount()), " + string(duration) + ", " + String(opt1) + ")") : \ Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", c.Framecount()), " + string(duration) + ")") } CutFrames(200, 800, 60, "TransSwing", "false", "1", "1") You can also use this as a quick, apply effect to range function, that takes 2 clips as input Code:
CutFrames(200, 150, 50, "EffectName") Code:
CutFrames(300, 150) Code:
CutFrames(800, 100, 695)
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer Last edited by mikeytown2; 4th March 2008 at 04:39. |
4th March 2008, 13:15 | #9 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
Of course YMMV, and your time and effort are yours to spend as you wish. Incidentally, I suggest a modification to your enhanced CutFrames function: change the types of opt1, opt2 and opt3 from 'string' to 'val'. This would allow you to pass numerical parameters without quotes. Also (and again, it's a matter of personal taste), I would tidy up the last part as follows: Code:
opt1=(Defined(opt1) ? ", "+string(opt1): "") opt2=(Defined(opt2) ? ", "+string(opt2): "") opt3=(Defined(opt3) ? ", "+string(opt3): "") return Eval(transition + "(c.trim(0, " + string(start) + "), c.trim(" + string(end) + ", 0), " + string(duration) + opt1 + opt2 + opt3 + ")") |
|
4th March 2008, 22:50 | #10 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Updated first post with latest function and put up examples as well as a very helpful tip.
Thanks to Gavino for your help in cleaning up the code and the tip. Thanks to Ebobtron for pointing out transitions. Thanks to stickboy for directing me towards his other trim functions; i didn't use them because of dependency issues though.
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer |
5th March 2008, 20:37 | #11 | Link | |
AviSynth Enthusiast
Join Date: Jul 2002
Location: California, U.S.
Posts: 1,267
|
Quote:
It's not as if they're unlikely inputs. You only need to call CutFrames(c, 0, ...) for it to be wrong. I've made my functions public domain for a reason. If you don't want to tell people to go download my scripts (and I don't think anyone actually has any problem with that), you're free to simply copy and paste the parts you need. |
|
7th March 2008, 22:54 | #12 | Link | |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Quote:
I never considered 0 as an input for this function (was thinking they would use trim), now i think CutFrames handles this quite nicely. I also added Preconditions to the header. Where should i pass the BlankClip Color property into this function? i was thinking after int "duration".
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer |
|
9th March 2008, 02:37 | #13 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
@mikeytown2: Looking at this again, I've just spotted something ...
Quote:
(and even if it did cut out 200-400, the length would then be 799) As the function is written, frames 'start' and 'end' are excluded from the cut, ie they appear in the output clip. I assume this is an oversight and you intended it to work as described in the example. Gavino |
|
9th March 2008, 03:24 | #14 | Link | |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Quote:
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer |
|
9th March 2008, 17:05 | #15 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Almost, but I think you've still got one of the boundary conditions wrong.
Since the last frame of a clip is actually framecount-1, this value (rather than framecount) should be the max allowed for end (and mapped internally to 0). Also, it might be clearer to replace: Code:
#Funkey Conditions start = (start == 0) ? -1 : start start = (start == 1) ? 0 : start #Perform Cut return start == -1 ? \Eval(transition + "(d, c.trim(" + string(end+1) + ", 0), " + string(duration) + opts + ")"): \end == 0 ? \Eval(transition + "(c.trim(0, " + string(start-1) + "), d, " + string(duration) + opts + ")"): \Eval(transition + "(c.trim(0, " + string(start-1) + "), c.trim(" + string(end+1) + ", 0), " + string(duration) + opts + ")") Code:
# Select uncut frames (or blanks) as transition components: clip1 = (start == 0) ? d : c.trim(0, -start) clip2 = (end == 0) ? d : c.trim(end+1, 0) # Perform transition: Eval(transition + "(clip1, clip2," + string(duration) + opts + ")") Gavino |
9th March 2008, 23:25 | #16 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Gavino thank you for improving this function, it would be a lot uglier without your help!
I was thinking about the fade color option, is there any way to test if an int is hex ($000000), if it has a "$" in it? If there is, then an idea i have is to get rid of the fade_color variable and use the start and end variables instead. Because the only time the blank clip is used is when start or end = 0; then if start or end is a color it would set the color with that value and then set start or end to 0. Example: CutFrames(0, 400, 20, $FF0000) would be CutFrames($FF0000, 400, 20) and CutFrames(400, 0, 20, $FF0000) would be CutFrames(400, $FF0000, 20). This would eliminate the unnecessary color variable in this example: CutFrames(200, 400, 20, $000000, "TransSwing", false, 1, 1) Good/Bad, is it even possible idea?
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer |
10th March 2008, 00:57 | #17 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,433
|
Quote:
If passing an unnecessary color parameter bothers you, you could move fade_color to the end of the function parameter list, then pass it by name on the infrequent occasions that a non-default value is wanted. There seems to be a typo in your latest edit: Code:
bg_color = default(fade_color,$000000) Code:
fade_color = default(fade_color,$000000) |
|
10th March 2008, 01:05 | #18 | Link |
Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Thanks for the catching the typo! I originally called it background color, then i thought fade described it better. Thanks for looking into the int/hex issue, it's not a major issue, just thought it might be better if it was possible. I'll leave fade_color where it is.
__________________
Mine: KenBurnsEffect/ZoomBox CutFrames Helped: DissolveAGG ColorBalance LQ Animation Fixer |
Thread Tools | Search this Thread |
Display Modes | |
|
|