Examples :: Load, convert and join arbitrary clips

This script extends the basic ideas of the fifth example, that is to load arbitrary clips and arguments supplied in external text files through proper changing of the default AVSLib's array delimiter and process them.

The example script applies moderately complex filtering (resizing, colorspace and fps conversion) based on the arguments' values and then joins the clips serially in a single timeline.

Shell scripts to automate the creation of the text files as well as the rendering of the .avs script are also provided. The later allow to treat the script as an Avisynth "program" which, in cooperation with a command line driven encoder (such as Avs2Avi, ffmpeg or VirtualDub plus a Sylia script) can fully automate complex NLE processes, reducing them to single shell command invocations.

First the script:

# load required modules

LoadModule("avslib", "base", "constants")
LoadModule("avslib", "base", "conversion")
LoadPackage("avslib", "array")
LoadPackage("avslib", "clip")
LoadModule("avslib", "numeric", "rounding")

# load a text file containing dir /b or equivalent 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 the line below dir is an array of filenames! 
# but be careful if you hand-type arrays...


# 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)

# 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))

# join clips together one after the other, applying Dissolve(c1, c2, 6) in each join

return clp.ArraySum(sum_func="Dissolve", sum_args="6")

In the example above a way to auto-convert all supplied clips to compatible characteristics for splicing is presented.

The core task of clip properties scanning is made by two functions of the clip package: JointPixelType and JointFPS. The first returns the dominant colorspace of a clip array, while the second the dominant framerate (so that the fewest conversions result from converting all array's clips to these values).

Based on these values (and also on the user-supplied arguments for the target size) the homogenisation of the (possibly heterogenuous) clips passed in as arguments is made compactly in just a few lines of code with the use of array operators (see also the related tutorial). The same is true for the creation of the final combined timeline.

As in the fifth example, the creation of the .txt files can easily be automated with a custom shell script. A working example for the clips (say named "avidir.cmd") is provided below:

@echo off
echo """
for %%f in (%1) do @echo %%~ff
echo """

The shell script takes one (needed) argument, a wildcard specification which can include path information in case the files are not at the current directory. The script outputs absolute filenames, so that the calling avisynth script can be located anywhere in the filesystem.

The final step to automate the process is to make another custom shell script (say "makeavi.cmd") that will update the contents of the text files and (optionally, depending on your needs) invoke the encoder. For example:

@echo off
avidir %1 > files.txt
echo %2 > width.txt
echo %3 > height.txt
avs2avi script.avs -l %4

The top level shell script takes four arguments, a wildcard specification, two integer values for the width and heigh and an additional 4th argument (a filename with the codec settings). It is assumed that the encoder executable is placed at a folder included in the PATH environment variable.

Thus you can invoke a single shell command in order to import, NLE process and encode a set of clips, such as:

makeavi [wildcard] [width] [height] [codecsettings]

If another encoder is used , the top level script must be modified appropriately to account for the different command line options needed by the encoder.