# AVSLib :: sample script # Copyright (c) 2007 George Zarkadas (gzarkadas@users.sourceforge.net) # This program is free software; you can redistribute it and/or modify it under the terms of # the GNU General Public License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # You should have received a copy of the GNU General Public License along with this program; # if not, write to the "Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA" # load required modules LoadModule("avslib", "base", "constants") LoadModule("avslib", "base", "conversion") LoadPackage("avslib", "array") LoadPackage("avslib", "clip") LoadModule("avslib", "numeric", "rounding") LoadModule("avslib", "string", "search") LoadModule("avslib", "filters", "edit") LoadModule("avslib", "filters", "stack") # transition code Function Crop4x4(int i, clip c) { cw = Round(c.Width / 4) ch = Round(c.Height / 4) row = Int(i / 4) # [0..3] col = i % 4 # [0..3] return c.Crop(col * cw, row * ch, cw, ch, true) } # Using a single underscore is a good convention for private user globals; # they do not clash with AVSLib namespace global _crop_clip = BlankClip(length=0) Function ClipDivide4x4(clip base) { loop = ArrayRange(0, 15, step=1) global _crop_clip = base return ArrayOpFunc(loop, "Crop4x4", "_crop_clip") } # assume each subclip is 15 frames long; appear is a flags array global _fade_count = 0 # either blanks clip c or leaves it unchanged, depending on value of flag Function _ovl_clip5(clip c, val aflag) { return aflag > 0 ? c : c.BlankClip() } Function FadeSubClip(clip subclip, string appear) { ap = ArraySplit(appear, _fade_count, chunksize=5) # increase counter so that next call process next subclip global _fade_count = _fade_count + 1 # split subclip to 5 pieces ac = ArrayCreate( \ subclip.EditTrim(0, 3), \ subclip.EditTrim(3, 6), \ subclip.EditTrim(6, 9), \ subclip.EditTrim(9, 12), \ subclip.EditTrim(12, 15) \ ) # blank subclip in all parts where ap has zeros and recombine pieces video = ArrayOpArrayFunc(ac, ap, "_ovl_clip5").ArraySum() # keep audio from original clip to maintain precision return AudioDub(video, subclip) } # Creates a vanishing / appearing checkboard transition effect. # Since we will use the function with EditJoin we know that there always be two clip arguments. # Function Transition(clip c1, clip c2) { start = c1.EditTrim(0, -8) # all but last 8 ef1 = c1.EditTrim(-8) # last 8 ef2 = c2.EditTrim(0, 7) # first 7 end = c2.EditTrim(7) # all but first 7 # divide effect clips to a matrix of 4x4 subclips, each with 15 frames & merge (+) cr = ArrayOpArray(ef1.ClipDivide4x4(), ef2.ClipDivide4x4(), "+") # create subclip appearence flag arrays, one for each 3 frames (5 steps total) # in each step make 4 subclips to dissapear for ef1 and 4 to apear for ef2 b1 = "1,1,0,1, 0,1,1,1, 1,0,1,1, 1,1,1,0" b2 = "1,1,0,1, 0,0,1,0, 1,0,0,1, 0,1,1,0" b3 = "0,0,0,1, 1,0,0,0, 0,0,0,1, 0,0,1,0" b4 = "0,0,1,1, 1,0,1,0, 0,1,0,1, 1,0,1,0" b5 = "1,0,1,1, 1,1,1,0, 0,1,0,1, 1,1,1,1" # multiplex flag arrays in order to create continuous blocks of flags # (ie the columns of the table above) for each subclip appear = ArrayPlex(b1, b2, b3, b4, b5) global _fade_count = 0 crf = ArrayOpFunc(cr, "FadeSubClip", StrQuote(appear)) trans = Stack(crf, 4, 4) return start + trans + end } # load a text file containing dir /b output # surrounded by triple quotes at the start and end of file dir = Import("files.txt") # load two text files containing integers # (target width and height for the clips in dir) tw = Import("width.txt") th = Import("height.txt") Assert(tw.IsInt && th.IsInt, "Input Error: width or/and height files contain invalid data") # after that dir is an array of filenames! # but be careful if you hand-type arrays... (see the transition code block) ArrayDelimiterSet(CRLF) # cleanup dir from invalid files (CInt is used to convert true/false to 1/0) okflag = dir.ArrayOpFunc("Exist").ArrayOpFunc("CInt") dir = dir.ArrayReduce(okflag) Assert(dir.ArrayLen > 0, "Input Error: files.txt does not contain any valid filename") # read in clips clp = dir.ArrayOpFunc("DirectShowSource") # force clip parameters (dimensions, framerate, colorspace) to be the same # assume all clips are progressive b_same_fps = (clp.ArrayOpFunc("Framerate").ArrayDistinct().ArrayLen() == 1) pixel_type = clp.JointPixelType() fps = clp.JointFPS() # to assure that target width, height match any clip's colospace # restrictions we allow for the more restrictive type (yv12) tw = RoundBs(tw, 4) th = RoundBs(th, 4) # now convert clips (resize, convertto..., changefps) clp = clp.ArrayOpFunc("Spline36Resize", String(tw) + "," + String(th)) clp = clp.ArrayOpFunc("ConvertTo" + pixel_type) clp = b_same_fps \ ? clp \ : clp.ArrayOpFunc("ConvertFPS", String(fps)) # restore now default array delimiter, in order for transition code to work # restore also delimiters inside clp (a simple strreplace op.) old = ArrayDelimiterReset() clp = StrReplace(clp, old, ",") # join clips together one after the other, applying EditJoin with # custom user function (our transition) in each join # we cannot pass a quoted string to sum_args (even with three double quotes), # so we assign the string to a global and pass in the global's name unquoted global _tr_func = "Transition" return clp.ArraySum(sum_func="EditJoin", sum_args="op=EDOP_USER, extra_info=_tr_func")