SA LP Tech Support Fort Wiki
Advertisement

AviSynth Tutorial: No Prior Experience Required

Looking for an awesome editing program that doesn't cost a dime? You're in the right place. AviSynth is a free, non-linear video editor. I'll explain what non-linear means in a bit, but the free part is pretty amazing, given the power of this system.

Before we continue, I need to let you in on the one big stumbling block most people have with AviSynth: it has no GUI. That is, editing with AviSynth is done not with some program window, but rather by writing code in a Notepad (called a script). If you've never done programming, this may seem daunting, but I guarantee you, it's absolutely easy, and offers some very big advantages over other free video editors. After going through this guide, I guarantee you will be able to make many simple edits, and even a few relatively complex edits, very little of which you could do with other free software.

Why Use AviSynth?[]

First and foremost, AviSynth is a non-linear video editor. What this means is that using Avisynth, you can access any frame of the video at any time, without having to bother with going through the rest of your video. Why is this awesome? It means that every frame (or group of frames) can be accessed individually, and you can put effects on each of them, or rearrange them as you please. Editing software such as VirtualDub lacks this ability. You can create and use a lot more effects with AviSynth.

Second, AviSynth doesn't work with gigantic video files themselves, but rather the 2-5 kb text file you write. This means that if you mess up an edit, rather than re-encoding your lossless video, you can just change the text file and reload it. This will save you hours compared to working with VirtualDub.

There are other incidental advantages, but those two are the biggest, and trust me, they make learning AviSynth worth it. So who needs introductions, let's dive in.

What To Expect From This Guide[]

I'm hoping this guide can help total beginners start from scratch with AviSynth. However, I'm also hoping to add a lot of the useful filters and other tricks I and others have found, so that even people who know how to use AviSynth can use this guide to learn something new.

If you have anything you think I should add, just post in the Tech Support Fort telling me about it, especially if it's a useful plugin or script that isn't in here.

Your First Script[]

(Largely stolen from the AviSynth wiki.)

After downloading and installing AviSynth, open up any simple text editor. I'm a fan of Notepad++, but even vanilla Notepad will work (Do not use Word or anything that would give you a .doc or .docx file, they have wrapper code you don't see that messes up how AviSynth reads the script).

Find an avi file you want to work with. Make it something you've recorded, just for fun. Try to make sure your video is at least 4000 frames in size (a little over 2 minutes, if you recorded at 30 frames per second), for future tutorials. Now, copy this into the Notepad file:

AviSource("c:\folder\myclip.avi")

Provide the filepath of your own clip there, rather than the placeholder. Make sure you leave the quotes in. NOTE: You do not need to give the entire filepath, but that will let you be sure you get the right file. AviSource goes looking for files based on the directory the .avs file is saved in, which means if you save the script in the exact same folder as the video, you can just put "<video name>.avi" in your AviSource call. It looks shorter and nicer but if you ever move the video file around it might screw things up.

Once that's settled, save the file, but make sure to save it as .avs, rather than .txt. If you did this right, the file will show up in its folder with an AviSynth logo (at least, by default). Now right click and open your .avs file with any avi player. It should work, and you'll have your input video, completely unedited. You can do the exact same stuff with it in the player as any avi file.

NOTE: .avs files are functionally identical to .avi files. This means that anything you can do with an .avi file, you can do with an .avs file, including using AviSource on them. That is, you can totally make a script that begins with:

AviSource("c:\folder\myclip.avs")

HOWEVER! AviSourcing .avs files can lead to some weird errors, so when you want to do that, actually use the Import command:

Import("c:\folder\myclip.avs")

Let me repeat, Do not use AVISource() in your script to load other scripts, use Import() instead. The two lines above are functionally identical, but AviSource sometimes does weird stuff with .avs files, so only use it for .avi files.

Why do this? Sometimes it can be easier to organize information in two separate files, or keep them separate for other reasons. Before I do commentary, I make all my cuts in one .avs file and save it. Then, when I want to put my commentary over it, I make a new .avs file that grabs the first one using Import. It's nice to have the option.

And there you go, that's all you have to do to write a script that plays a video. Almost every AviSynth script will start with this or something like this, with a video input for AviSynth to work with. Easy, no?

Useful Trick, especially for those of us using FRAPS: You know how FRAPS saves multiple 4 gigabyte files on your computer and that annoys you? You can stitch these files together effortlessly in AviSynth:

AviSource("frapsvid1.avi") + AviSource(“frapsvid2.avi”)

Remember to use the full filepath for both files. Now open it in a video player, and it'll give you both videos, first the first one, then the second right after, as if there was never a break. Using + to connect every AviSource video you want to add, you can do this with as many avi clips as you want; however, they must be the same resolution, same colorspace, same codec, and several other things. However, if you recorded everything you want to use in the same way this will almost never be a problem.

NOTE (from QuarkJets): "Avisynth ignores case. AVISource and aviSource and AviSouRcE all do the same thing. This also means that if you create two variables, abc and ABC, they're actually the same variable. This is contrary to most programming languages, so even programming vets need to be careful."

What this means is the fact that I write AviSource in my methods is just because I'm weird. When we start learning functions (really soon) it'll work the same way. Trim will do the same thing as trim or TRIM, but let's not get ahead of ourselves. This usually just means you don't have to be so careful about capitalization.

Your First Edit[]

Now that you have the basics down, let's get into editing. The very first edit you're going to learn is the most useful function in AviSynth, one that almost every other edit relies on in some way: the mighty Trim function.

Trim(clip clip, int first_frame, int last_frame)

If you've programmed, you might understand this. If you haven't programmed, don't panic. This is a function. It's basically a single line of code that you give arguments (clip, first_frame, and last_frame, in this case), and that gives you something based on those arguments. This particular function will take the clip you give it and trim it down, cutting off every frame before first_frame and every frame after last_frame. (If you're wondering what the heck an int is, it's short for integer. Any argument that wants an int will take any integer you give it, but no decimals) Go back to your first script and add this on the second line:

Trim(500, 1000)

What we're doing here is calling the Trim function, giving it the number 500 for first_frame and the number 1000 for last_frame. If you're wondering why we didn't give it a clip argument, that's because by default, AviSynth will set the first clip argument in a function to the last video input, in this case the AviSource you gave it on the previous line.

Save it and open the file in your video player. What you'll get (assuming your video is at least 1000 frames long) is a 500 frame clip from your video. These are frames 500-1000 of your video, played without any of the rest.

This is insanely useful. For the simplest application possible, let's try this. Change your second line so it looks like this:

Trim(500, 1000) ++ Trim(3000,0)

Save it and open it in a video player, as usual. Now you'll see the 500 frames from before, but when they end your video will jump to frame 3000 and play until the rest of the video. Congratulations, you have just made your video do a jump cut, the simplest of all edits. Use it to cut out all your deaths in that terrible Mario Romhack, or remove the egregious backtracking from your Metroid Prime videos. NOTE: When you use 0 for your second argument in Trim, it will automatically give you a clip from your first number to the end of your video, no matter how many frames. 0 in the first argument just starts you off at the beginning of your video.

You can string together however many Trims (and other things, we'll soon see) you want, just like the FRAPS videos from before. And, it's important to note that they don't have to be in order. Trim(3000,0) ++ Trim(500, 1000) will produce the same video as before, but with the two clips in the opposite order. Try it; throw in all sorts of Trims in some crazy order, or try throwing in overlapping clips (like Trim(500,1000) ++ Trim(750,1250)) or even the same Trim twice. You'll see it all works just like how you should expect it to.

FINAL NOTE: You've probably noticed that AviSynth uses frames instead of time for pretty much everything. When doing edits it will make your life much easier if you open your video in a player that always displays the current frame. I use VirtualDub for all my viewing. Anything you like will work, though, as long as it starts your frames with 0, like AviSynth does.

So now you know your first function, Trim. Another function you're probably going to be using a hell of a lot, depending on how you do your videos, is Crop:

Crop(clip clip, int left, int top, int -right, int -bottom, bool align)

We have our clip, four ints, and a boolean value (which doesn't matter, because it defaults to false and you shouldn't need to use it. You don't even need to add it to your script). Crop is pretty self explanatory: it takes pixels off the edges of your video, as if you were cropping a picture. This is useful for removing ugly black borders that you'll end up with when recording in certain ways. Try taking your clip and adding this line below your Trim lines:

Crop(18,28,-46,-48)

Yes, the negatives are important. They differentiate this version of crop with another one, and this one is far easier, so always put the negatives on the final two numbers. Now, this function takes 18 columns of pixels off the left side of the picture, 28 rows of pixels off the top, 46 columns off the right side, and 48 rows off the bottom. You can change these numbers however you want, just make sure the ==first two numbers are positive and the last two are negative==; it gets weird otherwise. Use this function and testing to figure out exactly how many pixels to take off.

There are caveats, though. Many types of color filters and codecs require a specific height and width, usually a number divisible by 2 or 4. When cropping, you'll need to take these into account. But AviSynth will give you errors when you try to open it yourself, and these are actually very helpful, most of the time. So the best way to check if your crop is admissible is to try opening it. If it works in your player it should be fine.

Quick Aside 1: Variables[]

AviSynth lets you define variables, which is useful when you don't want to type out something like AviSource("c:\folder\myclip.avi") all the time, or have more than one clip we're referencing.

To show how this works, let's append parts of two different clips together. Go find another video clip. To make life easy, make it something else you've recorded from the same source. Now make a new script that looks like this:

clip1 = AviSource("c:\folder\myclip1.avi")
clip2 = AviSource("c:\folder\myclip2.avi")
Trim(clip1, 500, 1000) ++ Trim(clip2, 3000, 0)

As usual, substitute your own filepath and file names, but I really don't have to tell you by now, right? Now open it up and play it. You'll get 500 frames of the first clip and then everything from frame 3000 to the end of the second clip. This is how you can insert clips from different videos into your videos. Isn't that great?

You can name variables all sorts of things, but I recommend sticking with things like clip1 and clip2, to make your code easier for you to understand. Trim(fuzzybutt, 20, 400) ++ Trim(batman, 87, 96) will make a lot less sense to you than Trim(clip1, 20, 400) ++ Trim(clip2, 87, 96)

NOTE: Variables have types. A type tells a variable what it should be, and how it should behave (like a clip, like a number, like a string of letters, etc). AviSynth supports the following types:

QuarkJets posted:

Avisynth uses these variable types:

clip - a video clip, may or may not have audio

string - text, basically anything surrounded by quotation marks "". If you need to put quotation marks inside of a string, use """. For example, Subtitle("""Word on the street is that AviSynth is "da bomb"""")

int - an integer

float - floating-point number, ie anything with a decimal point

bool - true or false. Alternatively you can use yes and no but why would you?

val - Joker. When you see this as a function argument, it means that it can be any of the above variable types

AviSynth is capable of guessing the types of your variables simply based on what you put in them. So even if you did something like:

clip = 17

AviSynth would know that clip is an int, not a clip. This would confuse you, so try not to do it.

Quick Aside 2: Comments[]

In most programming languages, comments are a convenient way to keep track of what every line of code is doing in an otherwise confusing script. Even very good coders need comments to keep track of their larger programs. It's just too much to process at once.

AviSynth supports comments in a number of ways. The most common way is the # key, but you can also use /* and */, and finally __END__. The best way to show these is just to make you add them to your script. So doll it up to look something like this:

# AviSynth ignores this
AviSource("c:\folder\myclip.avi") # It ignores this, too, but not the call to AviSource
/* It will also ignore everything after this,
and will continue ignoring things until it gets to */
Trim(500,1000)
__END__
This won't be read at all
Crop(18,28,-46,-48)

First, AviSynth ignores everything you write after #, even if it's in the middle of the line. Try adding a # at the beginning of your line with Trim, and you'll get your full video, because Trim was never called. However, # only lasts until you hit enter. As soon as you start typing on a new line, AviSynth will read whatever you put there.

And that's why you want to write down multi-line comments using /* and */. As soon as AviSynth sees /*, everything afterwards is a comment, regardless of how many lines it spans. It will only stop taking things as comments when it sees */, at which point everything afterwards is part of the script again.

__END__ is a bit of a special case, because it's more of a command than a comment generator. When you write __END__ in your script, it stops reading right there and returns whatever you happen to have right before it. Which means anything you write afterwards (like Crop, or something that AviSynth wouldn't understand) don't get read at all.

If your scripts are simple, you won't really need comments, but it's good to remind yourself what you're doing, especially when they get longer. It can really help to have something that says in plain english #This line trims my clip from frames 500 to 1000, and then cuts to frame 3000

To sum up our two asides, have this helpful block of code from QuarkJets. The only new thing it uses a return statement, which it explains on its own. Don't try to use this, just see if you can read it and understand more or less what everything means and what it would do:

#Don't forget, # denotes a comment!  Anything after # in a line gets ignored by AviSynth
x = 50 # an int
y = 100 # another int
z = 30.0 # float
filename = "C:/SuperMarioRomHack_Stage1.avi" #string

#Now I'm going to load the file and set it to a variable
#AviSource takes a string as its argument and returns a clip.
#Trim takes a clip and two integers as its arguments, and it returns a clip.
clip1 =  AviSource(filename) #clip1 is the .avi file that we assigned to a string earlier
trimmedclip = Trim(clip1, x, y)

return trimmedclip #return marks the end of your script, if you return a clip then that is what gets loaded by your aviplayer.  
#returning anything else should get you a fat error and a punch in the mouth, both rightfully deserved

/*
I could have returned clip1, and then 
loading the script in VirtualDub would 
show me the unedited clip1 instead of trimmedclip.
This is useful for debugging when you've screwed something up!

Pat yourself on the back, if you understand this stuff 
then you could probably feel comfortable learning some Python!
*/

Onward and Upward[]

You're probably feeling pretty good about your skills with the Trim function now. I hate to break it to you, but your cut looks kinda terrible. Jump cuts are usually jarring and mostly used for comedic (or other) effect. If only there was a way to make some sort of smooth transition. Oh, wait, I think I know. Enter the Dissolve function:

Dissolve(clip clip1, clip clip2 [,...], int overlap)

This is one of the few functions that actually do require you to provide a clip (two or more, in fact). However, the Trim function returns a clip, so we can use it for a clip argument. Overlap specifies the number of frames the dissolve takes. The best way to show this is to return to our favorite script. Change your second line from whatever you made it while messing with Trim to:

Dissolve(Trim(500,1000), Trim(3000,0), 60)

Save it and open it. It dissolves from the end of your first clip into the beginning of your second clip. All this code can look difficult to parse if you've never programmed, so I'll take a moment to break it down. You call Trim twice here, and separate them with commas. If you wanted to add another Trim (which would dissolve from the second clip into that one), you would just add it after another comma. There's also a comma separating your final Trim and 60. In AviSynth, commas represent the separators between arguments in functions.

If the straight dissolve isn't your cup of tea, you could always try the FadeIn and FadeOut filters:

FadeIn(clip clip, int num_frames, int color)
FadeIO(clip clip, int num_frames, int color)
FadeOut(clip clip, int num_frames, int color)

These will take the given clip and either fade into it at the start, fade out at the end, or have a fade on both sides, all for the number of frames given by num_frame. You don't even need to enter anything for color unless you want to fade to/from something other than black, so try changing your second line in your script to this:

FadeOut(Trim(500,1000), 30) ++ FadeIn(Trim(3000,0), 30)

See how it looks. If you want to link multiple fades like this, use FadeIO for any clips in the middle.

As you can see, there can be more than one way to approach a lot of these problems. Feel free to toss in both of these or anything else you'd like to break up your cuts. You can even insert still images for cuts (I'll cover this later).

Making Your Own Functions (or using those made by others)[]

Now we're going to step it up a notch. Say you have a section that you want to keep in, but it's just too slow and tedious on its own. What better way to solve this than speeding up the video? Yes, AviSynth can do this, but if you search the wiki (at least as of this writing) you won't find any speed up function.

This is where user defined functions come in. AviSynth lets you create your own functions, which can take several complicated lines and turn them into one that you just give an input and receive an output, just like AviSynth's built in functions.

(I didn't write any of these, for the record. If you wrote any of these or have a source, do tell)

#Author: Plorkyeran, possibly, with modification by me
Function ChangeSpeed(clip c, float factor) 
{
    return c.TimeStretch(tempo=100 * factor).AssumeFPS(c.FrameRate * factor) \
        .ChangeFPS(c.FrameRate)
}

#Author: Nidoking
function ChangeSpeed(clip c, float rate)
{
  orig = FrameRate(c)
  newvid = AssumeFPS(c, orig * rate)
  return ChangeFPS(newvid, c).AudioDub(c.TimeStretch(tempo=100*rate))
}

NOTE: There are others out there, but I can't really find them. I know there are some buried in the old TSF. If you have a speedup function that's different in some way, post it and I'll add it to this as of now paltry list.

Big and scary, but we don't even really need to understand it. Let's take a look exclusively at the first one, for now. The first line is just a comment, which is a line that the computer doesn't read. AviSynth denotes these with #. The second line is the most important part, where we define the function and its arguments. Taking a look at just the name of the function and its arguments, we see:

ChangeSpeed(clip c, float factor)

We have our ever-present clip c, and a factor. The clip is obvious, and the more astute among you have probably guessed that factor is how much you want to speed it up, or slow it down. Float is just a computer sciencey way to say “number with decimals,” so you can put in 2 or .5 or 4.3782, if you so desire.

Below this we have the code that actually creates the speedup. If you look at it, you might be able to understand it, but even if not, you can still use it. Back to our script, I want you to change it to something like this:

AviSource("c:\folder\myclip.avi")
Trim(500, 750) ++ ChangeSpeed(Trim(751,2000), 4) ++ Trim(2001,0)

Function ChangeSpeed(clip c, float factor) 
{
    return c.TimeStretch(tempo=100 * factor).AssumeFPS(c.FrameRate * factor) \
        .ChangeFPS(c.FrameRate)
}

(the most important thing here is the ChangeSpeed in between your trims. Everything else having to do with ChangeSpeed is directly copy/pasted from the code I provided previously)

Yes, you need the whole thing. What's going to happen is pretty predictable: You'll play 250 frames at normal speed, then speed up by 4x for the next 1250 frames, and then go back to regular speed for the rest of the video. NOTE: The sped up section of your video may play badly, skipping frames, messing up the sound, and overall looking bad. ==Do not worry, this is not a problem with the video==, it's AviSynth having to do a bunch of calculations and your computer not being able to do these calculations at 30-60 frames per second. When you encode the video, these calculations won't be made anymore, so it will play perfectly smoothly. Try it.

It's important to note that if you want to use a user created function, you must define it in every single script you want to use it in. Why? Because if you have this function sitting in “analrape.avs” and tell “buttplugs.avs” to use ChangeSpeed, AviSynth will have no idea you want it to look in analrape.avs. NOTE: If you want to make a function such as ChangeSpeed available to every Avisynth script you write without having to include it in the script or Import a common .avs file every time, you can save it in a file with the ".avsi" extension in the Avisynth plugins directory (which will be "plugins" under wherever you have Avisynth installed). Any .avsi file in this directory is implicitly Imported into every script you process, which can save you some time finding or rewriting functions that you use frequently. This will add a tiny bit of overhead to the processing of all Avisynth scripts, but it shouldn't matter unless you put hundreds of functions or plugins in there. Also, if you use a .avsi-sourced function, remember that updating the function will affect any future re-encodings of previous scripts that use the function - the way it's defined at encoding time is how it will work. Be sure your function is solid and works the way you want it to before you make a plugin out of it and depend on it too widely.

Plugins[]

Of course, some more awesome things have been done with AviSynth with more code than we'd like to add to every single script, but thankfully there is another way to add functionality written by other people, and that's plugins.

To demonstrate plugins, I'm going to use my favorite one, yadif. Yadif is Yet Another Deinterlacing Filter, which is useful when you capture off of consoles (like I do). If you need it, you can download it from here.

Download it and save it to your plugins folder. Now take a script that needs deinterlacing and add this line to it at the very top, before anything else:

LoadCplugin("c:\folder\yadif.dll")

I'm not actually sure if you need the full filepath for this, but I put it all in. Now you can call the function Yadif() anywhere in your script. So where should you put it? Well, the best place to deinterlace is always when you have full, unedited footage. Therefore, I find the best place to call it is actually the AviSource for the interlaced footage itself. That is, something like this:

Yadif(AviSource("myclip.avi"))

This will give you a deinterlaced version of the clip, and since it's a clip you can use it in the exact same way as you would any AviSource call, like setting it as a variable or using it as your last variable.

Also, you don't have to worry about the other potential arguments for Yadif, if you read the description in the link above and noticed they were there. If you don't know what they mean then you're fine leaving them on defaults, most of the time.

NOTE: See how Yadif uses the command LoadCPlugin? Some plugins use this, most use LoadPlugin. The page where you get the plugin should specify if you need to do anything special, like LoadCPlugin, so make sure to read that if your plugin isn't working.

AviSynth plugins can be found all over. You can find a ton here. NOTE: If you find one that you think is cool, feel free to tell me about it and I'll add it to this guide.

Cool Plugins: Yadif (used for deinterlacing)

Adding Commentary With AviSynth[]

There are several ways to add your commentary to your game videos, and I personally use AviSynth. My process is pretty simple: I do my audio editing in Audacity, combining my voice (and the voices of my co-commentators) with the game audio (which I usually extract from my videos using VirtualDub) and save it all as a single .wav file.

Now, to add it to your video, it's time to introduce a new function, AudioDub:

AudioDub(clip video_clip, clip audio_clip)

This function takes the audio from the second clip and puts it over the video from the first clip. This is what your script will look like:

clip = AviSource("myvideo.avi")
audio = WavSource("myaudio.wav")
AudioDub(clip,audio)

That's all you need. Note that you use WavSource to import .wav files.

Interesting thing to note: If the video is longer than the audio, it just ends early and inserts silence. If the audio is longer than the video, the clip will end when the video ends, but the audio information will still exist. So what if you have this hilarious one liner at the end of your video, but you just don't have time to say it in your video? Save it in your .wav as you'd like it to be timed in your video, and take note of how long after your video it goes. Now make a minor change to your script:

clip= AviSource("myvideo.avi")
audio= WavSource("myaudio.wav")
AudioDub(clip,audio)+BlankClip(clip, 30)

BlankClip produces a black clip with the exact same dimensions, framerate, and other stuff as the specified clip. I'll go over it later, but the number in the second argument is the number of frames this clip lasts for, so estimate how many frames it'll take for your piercing wit to shine through and change the number accordingly. You can just open your script in a video player and listen to the end to make sure you didn't have too little or too much blank screen at the end. If your voice cuts off just add some frames, and if there's an awkward silence before the end of the video, take some away.

(Pokecapn points out: Having audio longer than video can screw up YouTube encoding, so try to avoid having an audio track that's longer than your video. I don't usually see problems when the video is slightly longer, but it's best to try to get as close a match as you can. Just pad the video with a blankclip or delete extraneous audio as necessary.)

Quick Aside 3: AlignedSplice and UnalignedSplice[]

You might have noticed that I used + to connect those two clips instead of ++. This is because each of these calls a different Splice function. + uses UnalignedSplice, while ++ uses AlignedSplice.

What's the difference? Well, our buddy Xenoveritas whipped up this handy explanation. It even has pictures!

Xenoveritas posted: Let's Explain the Difference Between AlignedSplice and UnalignedSplice First off, the + and ++ operators are actually shortcuts for UnalignedSplice and AlignedSplice respectively.

In other words, "clip1 + clip2" is identical to "UnalignedSplice(clip1, clip2)", and "clip1 ++ clip2" is identical to "AlignedSplice(clip1, clip2)".

So that's where AlignedSplice and UnalignedSplice come into play.

The difference is fairly simple: AlignedSplice will pad or trim the audio of the first clip to match the video length, while UnalignedSplice will not.

OK, so that may sound confusing, but can be made easier to understand with pretty pictures. For this example, let's take the following two clips:

clip1 Avisynth clip1

clip2 Avisynth clip2

Both of these clips are clips where the video and audio are different lengths. In clip1, the video is longer than the audio, while in clip2, the audio is longer than the video.

AlignedSplice will either pad or trim the audio of the first clip so that it matches the length of the video. So let's use it to join first clip1 and clip2, and then clip2 and clip1:

AlignedSplice clip1 ++ clip2 Avisynth clip1 as clip2

As we can see, silence was inserted after clip1's audio to make it as long as the video before adding clip2 as-is. If we do it the other way around:

AlignedSplice clip2 ++ clip1 Avisynth clip2 as clip1

Note that audio was removed from clip2 (it's the dotted box) to make the audio match the video length before adding clip1 to the end.

UnalignedSplice, on the other hand, will not alter the audio length, instead appending the audio and video streams separately. So let's repeat the above, this time using UnalignedSplice:

UnalignedSplice clip1 + clip2 Avisynth clip1 us clip2

This time the silence is missing, and the audio from clip2 slide into the video for clip1. If these were recorded files where the audio desynced between video files, this may be exactly what we want - the audio in clip2 may be the missing audio from clip1.

From completeness sake, let's also do the reverse:

UnalignedSplice clip2 + clip1 Avisynth clip2 us clip1

It's basically the same thing - again, audio from clip2 is used during video from clip1. And again, this may be exactly what's needed when combining two videos together from a recorded source - just in the case where the audio in the first clip is longer than the video in the first clip.

So hopefully this explains the difference between the two, and why you'll generally want to use + (UnalignedSplice) when joining clips from FRAPS back together.

Miscellaneous (Other cool internal filters)[]

BlankClip[]

This creates an entirely blank clip for you to do what you'd like with. It can take a lot of arguments specifying all sorts of things about it, but the easiest thing to do is just provide it with a single clip as an argument. It'll just create a blank clip that has the same information as the clip you provided, so you don't have to tell it framerate or dimensions or all that dumb stuff. Then you can just add the length (in frames) as the second argument. See the Adding Commentary With AviSynth section for an example.

Overlay[]

Say you want to put one clip on top of another. Why? I don't know, let's say you're playing a game with your feet and have video to prove it (completely hypothetically, of course). You want the two videos to play at the same time, and the easiest way to do that is resize the video of your feet and do a picture-in-picture with the game and your feet. Overlay can do that. It can do lots of other cool things, too, figure them out yourself.

The important arguments in that jumble are (clip, overlay, x, and y). I really hope clip and overlay are obvious by this point, but x and y determine the position of your overlay. Think of your main clip as the x,y coordinate plane, except the starting point is the top-left corner. Oh, and y gets larger as it goes down. Blame computer science. Anyway, your x and y coordinates determine where the top-left corner of your overlay video will go. So if you use 0,0 as your x and y arguments, it will be in the top left corner of your main video. If you use 5,10, the overlay video be shifted 5 pixels to the right and 10 pixels down. Play around with it and you'll see how it works.

DelayAudio[]

This does pretty much exactly what it says: delays the audio by the number of seconds you input. This is useful to you if you have unsynced audio that stays more or less constantly ahead or behind your video, rather than getting further and further away from where it should be. Not a super common problem, but AviSynth can fix it in one line, so points to AviSynth.

It takes two arguments, clip and seconds. seconds is a float, which means you can put in decimals to get a more exact numbers, like 2.5 seconds or 3.2748375 seconds, if you're a nerd with aspergers. Giving it a positive value shifts the audio forward, and giving it a negative value shifts it backwards. Very simple, really.

NOTE: I should probably add stuff like resize filters here, but I don't tend to use it, so I don't really know what to recommend. Anyone can feel free to help me out, or recommend other internal filters for me to add here.

Return Values (or How the last Variable is Messing Your Script Up)[]

NOTE: This is a slightly more advanced topic, because it delves into a slightly more computer science-y subject, which is why I'm putting it near the end. However, if you're comfortable with the rest of the material in this tutorial, this section will be useful for errors you're not sure about.

Let's discuss return values. In short, these are what your script plays when you ask to view it in a player. They are the reason why this script will play clip1 and make absolutely no mention of clip2:

clip1= AviSource("clip1.avi")
clip2= AviSource("clip2.avi")
clip1

Try it with two of your own videos. Notice how I put clip1 as the final line of the video, and that's what played. But why wouldn't the first bit of code play both clips? We mentioned them both, right? Well, that's where the return value of your script comes in.

A return statement specifies what video our script returns (what it plays). To make this a little clearer, let's change the script slightly, to this:

clip1= AviSource("clip1.avi")
clip2= AviSource("clip2.avi")
return clip1

Open it and it does the exact same thing as the last script. return is what we call a keyword in AviSynth. Basically it's a special word that does something on its own (and can't be a variable, so don't try to name any variables return). What it does is stop the script right when it's and cough up whatever you specify after it. In our example, we wanted it to return clip1, so it did.

Your return statement should be the final line in your code (other than functions you specify, like speedup), because AviSynth won't even try to read lines you put after it. For example, try this:

clip1= AviSource("clip1.avi")
clip2= AviSource("clip2.avi")
return clip1
Trim(clip1, 0, 500)

All of our previous experience tells us this gives us the first 500 frames, but nope, we get the full clip, because the script's return value is clip1. It doesn't care what we did afterwards. In fact, it doesn't even care if we put it before:

clip1= AviSource("clip1.avi")
clip2= AviSource("clip2.avi")
Trim(clip1, 0, 500)
return clip1

This still returns clip1 in all its glory. Well that's odd. But let's have some fun with this. Change your script to:

AviSource("clip1.avi")
Trim(0, 500)
return Crop(38,16,-42,-16) #these are just the numbers I used to crop Bounty Hunter, don't worry about them too much

Based on our last script, we'd expect that Trim to get lost, but open it up and you'll see that you have the first 500 frames, nice and weirdly cropped. Now what the hell is going on? Why is the return value so confusing?

The answer is the last variable. The last variable is a special variable in AviSynth that automatically changes itself line by line, based on what is on the line. Furthermore, it is provided as the clip argument when you don't specify one. That is, throughout this tutorial, every time you've done something like this:

AviSource("clip1.avi")
Trim(0, 500)

AviSynth interprets it like this:

AviSource("clip1.avi")
Trim(last, 0, 500)

Both of these do the same thing; you can omit the last variable for convenience. last is always set to your last line, unless you set a variable. This will be very important, and this is why you get an error if you do this:

clip1= AviSource("clip1.avi")
Trim(0, 500)

The last value is never set, so when you try to use Trim, it calls Trim(last,0,500). But last isn't anything, so it can't Trim last.

NOTE: Also important to note is that setting a variable doesn't actually change or erase the value of last. So if our script looks like this:

AviSource("clip2.avi")
clip1= AviSource("clip1.avi")
Trim(0, 500)

we'll just be trimming clip2.avi, and clip1 will be ignored completely, because last was assigned to clip2.avi in our first line and the second line did nothing to it. This can mess your script up if you don't understand it, ==so check if this is the reason your script doesn't look right when you open it in a video player before you ask us==.

That's cool, but what does last have to do with return values? Well, you know how we haven't been putting a return value on most of our scripts, but they've still been playing just fine? When you don't use a return statement, when AviSynth gets to the end of your script, it automatically returns whatever the last value happens to be. Therefore, when we do something like this:

AviSource("clip1.avi")
Trim(0, 500)
Crop(38,16,-42,-16)

We return the last value, which is set by the Crop line, which in turn used the last value set by Trim, and that used the value set bu our AviSource call. Most of the scripts we've made have been a big string of calls using the last variable, which changes its value every line you aren't setting a different variable. Then, at the very end, the script returns whatever last ended up being. Basically AviSynth reads the script like this:

last = AviSource("clip1.avi")
last = Trim(last, 0, 500)
last = Crop(last, 38,16,-42,-16)
return last

Easy, no?

IMPORTANT NOTE: There's one small caveat about returning the last variable automatically. If your final line sets a variable, like so:

AviSource("clip2.avi")
Trim(0, 500)
clip1 = AviSource("clip1.avi")

You're going to get an error saying that the return value is not a clip. When you set a variable, it messes with the auto-return a little bit, so that it doesn't automatically return anything.

This, however, works:

AviSource("clip2.avi")
Trim(0, 500)
clip1 = AviSource("clip1.avi")
return last

... But what the hell are you doing with clip1.avi if you're assigning it to a variable at the very end? There's literally no reason to do this, so don't.

Errors (And What The Heck They Mean)[]

Lastly, I'd like to give you some common errors you're definitely going to be seeing along the way. This will hopefully be a small directory of things AviSynth might tell you when you screw up.

Generally, when you get an error, the video will refuse to open, give you a general reason, and tell you exactly what line messed up. This can be really helpful or really confusing. These are some common errors:

Script error: expected a , or )

You messed up and forgot a comma or close parenthesis, used for separating arguments and denoting the end of arguments, respectively. This will give you the line this happened on, so find it and add it.

Script error: Invalid arguments to the function “DoWhatever()”

DoWhatever will be changed to whatever function you screwed up, of course. This means that you put in inadmissible arguments to the functions you tried to use. Like, say, if you did Trim(3, 27, 100). Trim has no idea what you're trying to tell it, so figure out why the arguments are incorrect.

The script's return value was not a video clip

Usually this is the result of you making your last line a variable declaration, which confuses AviSynth. If you get this error post your script in the Tech Support Fort and we'll tell you where you messed up.

Splice: One clip has audio and the other doesn't (not allowed)

Pretty self explanatory. You tried to add a video that didn't have sound to one that did. Fix that. If the clip without audio is supposed to be silent, then use the BlankClip function with the clip that has audio and the number of frames from the clip with no audio to produce a track of silence, and AudioDub that onto the clip with no audio. Example:

# splicedclip = clipwithaudio ++ clipwithnoaudio <- This line gives us the above error
silenceclip = BlankClip(clipwithaudio, FrameCount(clipwithnoaudio))
clipwithsilentaudio = AudioDub(clipwithnoaudio, silenceclip)
splicedclip = clipwithaudio ++ clipwithsilentaudio # No error!

Splice: Video formats don't match

You've tried to merge two video spaces that use different color spaces. This is fairly easy to fix: choose a color space, and convert both clips to it. The final color space you want to use is YV12, so generically, you'll want to change the clips to both be in YV12. So if the line failing is:

clip1 + clip2

Change it to:

clip1.ConvertToYV12() + clip2.ConvertToYV12()

AVISource autodetect: couldn't open file 'whatever.avi'

You gave it the wrong filepath, dummy. Fix that.

NOTE: I know there are other common errors, but I don't really know them off the top of my head, so if people can give me ones they see a lot, I'll add them (as well as add any I find). It would be really cool if someone could get pictures of the error messages, but I don't think it's that necessary.

Final Notes[]

If you've made it this far and can understand most of this, you've got a pretty good grasp on AviSynth now. Use it to make your videos more interesting and watchable without spending any extra money.

As you've probably notice, this guide has plenty of links to the AviSynth Wiki. It's an amazingly useful resource, if you know how to use it. It documents pretty much all of the internal filters and explains how they work, though it can get fairly technical at times. But don't let that scare you off.

Finally, if you see something that isn't in this guide, just ask us about it in the Tech Support Fort. We can usually at least give you an idea of how to do it (assuming it's possible to do, AviSynth isn't perfect, sadly), if not get you the code you need.


Alright, that's what I have so far. I know I didn't cover everything, but I feel like I addressed some of the more important things, and I'd be happy to add anything people say I should.

Right now the two biggest things I want to be in here are inserting images into videos and creating subtitles. With the former, the only way I've been able to figure out is a complete pain in the ass, and I haven't managed to do it for FRAPS video yet. I feel like I'm missing something, so if anyone knows a good way to put image into a video please tell me.

As for subtitles, I've just never done it, so I don't have a clue what to do. If someone else who uses AviSynth for subtitles would like to write a section for that, by all means do.

Anyway, I'm hoping this is a passable guide. My biggest worry is that it's too verbose, or that it goes a little too high level for beginners sometimes, so if anyone wants to try learning AviSynth from it and telling me what's wrong with it, please do.

For those of you who have a clue what you're doing, feel free to correct me about anything and ask me about adding anything you want.

Advertisement