Los gehts

Ganz kurz gesagt arbeitet AviSynth so: Zuerst erstellt man eine einfache Text-Datei (.txt) mit speziellen Befehlen darin, das ist dann das Skript. Diese Befehle erzeugen Verweise auf ein oder mehrere Videos und Filter, die man dafür verwenden möchte. Als nächstes wird eine Video-Anwendung wie z.B. VirtualDub, gestartet und damit die Skript-Datei geöffnet. Hier greift jetzt AviSynth ein. AviSynth öffnet die Videos, auf die verwiesen wurde, bearbeitet das Video mit den Filtern und gibt das Ergebnis zurück an die Video-Anwendung. Diese merkt aber gar nicht, dass im Hintergrund AviSynth arbeitet. Für die Anwendung sieht es so aus, als ob eine gefilterte AVI-Datei auf der Festplatte vorhanden ist.

Es gibt viel Neues und Wiederentdecktes in AviSynth2 (d.h. alle Versionen über 2.00). Diese Teile sind mit v2 gekennzeichnet.

Lineare Editierung / Schnitt:

Das einfachste, was mit AviSynth gemacht werden kann, ist die Verwendung als linearer Video-Editor. Das sind die Möglichkeiten, die auch mit VirtualDub möglich sind. Die Skripte dafür sind recht einfach, weil keine Variablen oder komplizierten Ausdrücke notwendig sind.

Zum Testen erzeugt man eine Datei test.avs (nochmal: das ist nur eine umbenannte Text-Datei) und schreibt folgende Zeile hinein:

Version

Wenn man nun diese Datei z.B. mit dem Windows Media Player öffnet, sieht man ein zehn Sekunden langes Video mit der Versionsnummer und einem Copyright von Avisynth.

Version nennt man auch Quell-Filter, das heisst, diese Funktion modifiziert nicht ein Video sondern erzeugt selber ein Video-Clip Der erste Befehl in einem Avisynth Skript wird immer ein Quell-Filter sein.

Jetzt kommt noch eine zweite Zeile zum Skript:

Version
ReduceBy2   # Verkleinere auf die Hälfte

Wenn man diese Datei nochmals im Media Player öffnet, sieht man wieder die Copyright-Meldung, jetzt allerdings halb so gross wie vorher.
ReduceBy2 ist ein Transformations-Filter, welches das vorhergehende Clip nimmt und in irgendeiner Weise umwandelt. Viele diese Filter können zu einer Filterkette zusammengehängt werden.
Noch eine Zeile dazu, um das Video am Schluss auf Schwarz auszublenden:

Version
ReduceBy2
FadeOut(15)   # ausblenden

Nach dem Wiederöffnen sollte das Video während den ersten 9 Sekunden gleich ausschauen wie vorher, und dann in der letzten Sekunde auf Schwarz blenden.
Das FadeOut filter verwendet ein numerisches Argument, mit dem die Anzahl der Bilder (frames) angegeben wird, die für das Ausblenden verwendet werden. Das Video, das von Version erzeugt wird, läuft mit 15fps, daher beginnt das Ausblenden eine Sekunde vor dem Ende..

Angenommen es dauert zu lange bis das Ausblenden beginnt. Man kann aber den Anfang wegschneiden. Das Clip, das Version erzeugt, ist 150 frames lang (15 fps mal 10 sec).
Avisynth beginnt die Numerierung der frames bei 0.
Daher haben die frames die Nummern 0 bis149. FadeOut hängt einen frame zusätzlich dran, daher gehen die frames nach diesem Skript von 0 to 150. Um die ersten 120 davon wegzulöschen, schreibt man dies:

Version
ReduceBy2
FadeOut(15)
Trim(120,150) # die ersten 8 Sekunden wegschneiden

Hier sieht man auch, wie man Kommentare verwenden kann.
Kommentare starten mit einem # Zeichen und sind immer die ganze Zeile lang. Sie werden von AviSynth völlig ignoriert.
Das Trim filter verwendet zwei Argumente, getrennt mit einem Beistrich: der erste und der letzte frame, die vom Clip verwendet werden sollen. Wenn man als letzten Frame 0 einsetzt, bedeutet das "Ende com Clip", daher hätte man auch schreiben können: Trim(120,0).

Die Frame-Nummern auf diese Art zu verfolgen ist sehr mühsam. Es ist wesentlich einfacher, ein halbfertiges Skript in VirtualDub zu öffnen, wo die frame-Nummer auch angezeigt wird. Man kann auch den eingebaute ShowFrameNumber filter verwenden, der auf jeden frame die frame-Nummer schreibt.

Im wirklichen Gebrauch ist das wichtigtes Quell-Fiter AVISource, womit eine AVI-Datei von der Festplatte geöffnet werden kann. Hier ein kleiner Test für die Datei "capture.avi", in dem die genannten Filter verwendet werden:

AVISource("d:\capture.avi")   # hier muss natürlich der wirkliche Datei- und Pfadname stehen
ReduceBy2
FadeOut(15)
Trim(120,0)

Man sieht, dass sogar ein einzeiliges Skript, das nur aus dem AVISource Befehl besteht, schon sinnvoll sein kann, um AVI-Dateien >2GB auch mit Applikationen öffnen zu können, die das eigentlich nicht unterstützen.


Nicht-Lineares Editieren:

Nun zum wirklich interessanten Teil. In ein Skript folgendes schreiben:

StackVertical(Version, Version)

Wenn man dieses Skript öffnet, ist das Ergebnis ein Video mit zweimal der Versions-Info übereinander gestellt..
Die Funktion StackVertical verwendet nicht Zahlen oder Zeichenfolgen als Argumente sondern Video-Clips. In diesem Skript wird das Version-Filter zweimal aufgerufen. Jedesmal gibt es eine separate Kopie des Version-Clips zurück. Diese zwei Clip werden an StackVertical übergeben, das sie dann zusammenfügt (ohne sich darum zu kümmern, woher die Eingangsclips kommen).

Eines der am meisten verwendeten Filter dieses Typs ist UnalignedSplice, diese Funktion fügt Clips (zeitlich) aneinander. So schaut ein Sript aus, das drei AVI-Dateien lädt und aneinander fügt:

UnalignedSplice(AVISource("d:\capture.00.avi"), AVISource("d:\capture.01.avi"), AVISource("d:\capture.02.avi"))

Beide Filter (StackVertical und UnalignedSplice) können mit nur zwei oder auch bis zu sechzig Argumenten verwendet werden.
Der Operator + kann als Abkürzung für UnalignedSplice verwendet werden.

Dieses Beispiel macht das gleiche als das vorhergehende:

AVISource("d:\capture.00.avi") + AVISource("d:\capture.01.avi") + AVISource("d:\capture.02.avi")

Für den Fall, das z.B. von einem Aufnahme-Programm die AVIs mit mehreren Segmenten, der Ton als separate WAV-Datei gespeichert wurde, kann so alles wieder in ein Video mit Ton kombiniert werden:

AudioDub(AVISource("d:\capture.00.avi")+AVISource("d:\capture.01.avi")+AVISource("d:\capture.02.avi"), WAVSource("d:\audio.wav"))


Syntax

Ausdrücke:

Ein AviSynth Skript besteht aus mehreren Zeilen die folgende Form haben:

variable_name = ausdruck

In diesem Beispiel wird ausdruck ausgewertet und das Ergebnis einer Variable variable_name zugewiesen.

In diesem Zusammenhang ist die Kurzform dafür wichtig:

ausdruck

In diesem Fall wird ausdruck ausgewertet und der speziellen Variable last zugewiesen.
Das ist das gleiche als

last = ausdruck

Das Ende eines Skripts schaut immer so aus:

return ausdruck

Hier wirdausdruck ausgewertet und als Rückgabewert des Skripts verwendet, d.h. als Video welches die Anwendung zu sehen bekommt, die die AVS-Datei öffnet.

Die einfachste Form eines Ausdrucks, der eine Funktion aufruft, ist:

Function(argumente)

Clip-Funktionen erzeugen als Ergebnis immer ein neues Clip (es wird also nicht das vorhandene Clip verändert).
argumente ist eine Liste von Funktions-Argumenten getrennt durch Beistriche. Diese Liste kann leer sein (was bedeutet, dass alle oder manche Argumente optional sein können).

Wenn die Filter-Funktion als erstes Argument ein Video-Clip erwartet und dieses Argument nicht angegeben wird, wird die spezielle Variable last verwendet.

Bei manchen AviSynth-Filter können auch "benannte Argumente" verwendet werden. Diese benannten Argumente können in einer beliebigen Reihenfolge angegeben werden,
und das Filter verwendet Standard (default)-Werte für nicht angegebene Argumente (benannte Argumente sind daher immer optional).
Das vereinfacht die Benutzung mancher Filter stark.

Man kann schreiben:

Subtitle("Hallo, Leute!", text_color=$00FF00, x=100, y=200)

statt

Subtitle("Hallo, Leute!", 100, 200, 0, 999999, "Arial", 24, $00FF00)

Eine alternative Syntax ("OOP-Notation") für Clip-Funktionen ist

ausdruck.funktion(argumente)

z.B.:
Version.ReduceBy2.FadeOut(15)

Das ist das gleiche als:

funktionen(ausdruck, argumente)

z.B.:
FadeOut(15, ReduceBy2(Version))

was man sich vorstellen kann als Funktion angwendet auf ausdruck.
Ein Nachteil dieser OOP-Notation ist, dass sie nur für Filter verwendet werden kann, die ein einzelnes Video-Clip-Argument haben und nicht mit Filtern, die mehrere Argumente erwarten.

Alle AviSynth-Funktionen erzeugen eine fest definierte Anzahl an frames, auch die framerate wird durch das Skript eindeutig bestimmt, auch wenn die Befehle sehr komplex aussehen.
AviSynth weiss nach dem Lesen des Skripts wie lange das erzeugte Video sein wird, welche framerate es hat und hat die komplette Schnittsequenz von allen Quell-Videos ermittelt. Dies geschieht beim Öffnen des Skripts. Nur das Filtern an sich geschieht zur Laufzeit auf Anforderung durch das Video-Programm.


Kommentare: AviSynth ignoriert alles ab einem # Zeichen bis zum Ende der Zeile.

Gross- und Kleinschreibung wird ignoriert: aViSouRCe ist das gleiche als AVISource.

Fortsetzen auf der nächsten oder von der vorherigen Zeile: \

Subtitle ("Test-Text")
Subtitle (            \
          "Test-Text")
Subtitle ( 
\         "Test-Text")


Variablen:

Ein Variablen-Name kann bis zu 50 Zeichen lang sein und aus Buchstaben, Ziffern und Unterstriche(_), aber keinen anderen Zeichen bestehen, weiters darf er nicht mit einer Ziffer beginnen.

Folgende Variablen-Typen können verwendet werden:

clip: ein Video-Clip das Video und / oder Audio enthält. Mindestens eine solche Variable muss verwendet und als Ergebnis zurückgegeben werden.
string: umgeben "Anführungsstrichen". Eine Zeichenkette kann alle Zeichen enthalten ausser Anführungsstrichen.
int: eine Ganzzahl, die als eine Folge von Ziffern eingegeben wird, optional mit einem + oder - amAnfang.
float: eine Fliesskomma-Zahl, eingegeben als Folge von Ziffern mit einem Punkt (.) innerhalb und optional einem + or -. Zum Beispiel wird +1. als float behandelt.
val: als Typ eines Funktionsarguments wo es egal ist, ob int oder float
bool : kann TRUE oder FALSE sein
hexadezimal-Werte: können mit einem vorgestellen $ eingegeben werden. Intern wird diese Variable als Ganzzahl behandelt. Manche Filter verwendet diese Schreibweise zur Angabe von Farbwerten. So ist z.B. $FF8800 ein Orange-Ton.

global: Definiert eine globale Variable, die von allen benutzer-definierten Funktionen und dem Hauptskript gemeinsam benutzt werden kann. v2

So schaut eine andere Version des Beispiels von oben aus, die besser handhabbar und leichter verständlich ist:

a = AVISource("d:\capture.00.avi")
b = AVISource("d:\capture.01.avi")
c = AVISource("d:\capture.02.avi")
sound_track = WAVSource("d:\audio.wav")

AudioDub(a+b+c, sound_track)


Operatoren:

Mit allen Typen von Operanden (clip, int, float, string, bool) kann verwendet werden:
== ist gleich
!= ist nicht gleich
|| oder
&& und

Nur mit numerischen Operanden (int, float):
+ Addieren
- Subtrahieren
* Multiplizieren
/ Dividieren
% Modulo (Rest)
>= grösser oder gleich als
<= kleiner oder gleich als
< kleiner als
> grösser als

AviSynth zerlegt Ausdrücke von rechts nach links, was zu ungewohnten Ergebnissen führen kann:


a = 10 - 5 - 5          ergibt 10 - (5 - 5) = 10 !
b = 100. / 2. / 4.      ergibt 100. / (2. / 4.) = 200 !

Mit Operanden vom Typ string:
+ Addieren (Zeichenketten zusammenhängen)

Mit Typ clip:
+ das gleiche wie die Funktion UnalignedSplice
++ das gleiche wie die Funktion AlignedSplice

Mit Operanden vom Typ bool:
?: bedingte Ausführung von Code:

b = (a==true) ? 1 : 2
Übersetzt in pseudo-basic:
wenn (a=true) dann b=1 sonst b=2


Funktionen

Skript-Funktionen:

Die Argumente und das Ergebnis dieser Funktionen sind nicht Clips, sondern andere Variablen, die im Skript verwendet werden.

Floor (float): Konvertiert von float zu int
Ceil (float): Konvertiert von float zu int
Round (float): Konvertiert von float zu int
Sin (float) v2
Cos (float) v2
Pi () v2
Log (float) v2
Exp (float) v2
Pow (float Basis, float Hochzahl) v2
Sqrt (float} v2
fabs (float) v2.07 Absolutwert für float Zahlen.
abs (integer) v2.07 Absolutwert für int Zahlen.
IsBool (var)
IsInt (var)
IsFloat (var)
IsString (var)
IsClip (var)
Defined (var): um optionale Parameter in benutzer-definierten Funktionen definieren zu können.
Default (x,d): ergibt x wenn Defined(x), d sonst.
String (float / int): Konvertiert eine Zahl in einen string. v2

Subtitle( "Clip Höhe ist " + String(last.height) )

Eval (string)
Apply (func-string,arg,...): Eval("f(x)") ist equivalent zu f(x) ist equivalent zu Apply("f", x))

Man kann Eval für sowas verwenden:

settings = "352, 288" Eval( "BicubicResize(" + settings + ")" )

Es kann auch der Text von einem anderen Skript importiert werden:
Import (Dateiname): verarbeitet den Inhalt von einem andern AviSynth Skript.

Für error-Meldungen und das Auffangen von falschen Benutzereingaben kann folgendes verwendet werden:
Assert (bool, string error-Meldung): error-Meldungen erzeugen
AssertEval (string)

Es gibt auch eine Funktion mit der man überprüfen kann, ob ein Error auftreten WIRD:

Try {
  AviSource("file.avi")
}
catch(error_meldung) {
   Blackness.Subtitle(error_meldung)
}

SteuerFunktionen:

SetMemoryMax(int): Setzt die maximale Speichergrösse, die AviSynth verwendet (in MB) v2
In manchen Versionen ist die Standardgrösse 5MB, was eher wenig ist. Wenn Probleme auftreten (besonders langsame Geschwindigkeit), sollte diese dieser Wert auf mindestens 32MB gesetzt werden.
SetWorkingDir(string): Setzt das Standard-Verzeichnis für AviSynth (normalerweise sonst das Verzeichnis in dem sich das Skript befindet) v2
Das kann vor allem für das einfache Laden von Quell-Clips verwendet werden und hat keine Auswirkung auf das automatische Laden der plugins. Das Ergebnis ist 0 wenn erfolgreich, sonst -1 (wenn z.B. der Pfad nicht existiert)


Clip-Eigenschaften:

Diese Funktionen haben als Argument ein Clip, als Rückgabewert eine Eigenschaft des Clips.

Width (clip) Breite
Height (clip) Höhe
Framecount (clip) Frame-Anzahl
Framerate (clip) Frame-Rate (Bilder pro Sekunde)
Audiorate (clip) Sample-Frequenz des Tons
Audiolength (clip) Länge des Audios
Audiochannels (clip) Anzahl der Kanäle
Audiobits (clip) Bitanzahl
IsRGB (clip) Videoformat ist RGB
IsYUY2 (clip) Videoformat ist YUY2
IsFieldBased (clip) Video ist fieldbased (interlaced)
IsFrameBased (clip) Video ist framebased (progressive)
GetParity (clip) welches field (Halbbild) wird zuerst angezeigt (even/odd)

Nicht vergessen: die Clip-Eigenschaften können auch mit der impliziten Variablen LAST oder mit der OOP-Notation verwendet werden:
BilinearResize(Width/2, Height/2) ist das gleich wie BilinearResize(Width(Last)/2, Height(Last)/2) ist das gleich wie BilinearResize(Last.Width / 2, Last.Height / 2)


Benutzer-Definierte Funktionen:

Man kann auch selber Funktionen definieren. Das kann am besten anhand eines Beispiels erklärt werden:

Function NTSC2PAL( clip c) {
    Assert(c.height == 480, "NTSC2PAL: input clip must have 480 scan lines")
    Bob(c, height=576)
    return Weave()
}

Sogar rekursive Funktionen können definiert werden.

function TRANSITION(clip clip, int start,        int expo, int overlap)
{
   return ( start >= clip.framecount-expo ? 
   \   Trim(clip,start,0) : 
   \   Dissolve(Trim(clip,start,start+expo-1),
   \      TRANSITION(clip,start+expo,expo,overlap),
   \      overlap 
   \      )
}


Funktionen mit mehr als einem Quell-Clip

Manche Funktionen kombinieren zwei oder mehrere Clips auf verschiedene Art. Wie der Video-Inhalt berechnet wird, ist bei den jeweiligen Funktionen beschrieben, hier ist eine Zusammenfassung welche Eigenschaften das Ergebnis-Clip haben wird.

Das Quell-Clip muss immer das gleiche Farbformat und - mit Ausnahme von Layer - auch die gleichen Abmessungen.

frame-rate
frame-Anzahl
audio Inhalt
audio sampling rate
AlignedSplice, UnalignedSplice

vom ersten Clip

Summe aller Clips
siehe Filter-Beschreibung
vom ersten Clip
Dissolve
Summer aller Clips minus der Überlappung
siehe Filter-Beschreibung
MergeLuma, MergeChroma
vom ersten Clip
der letzte Frame vom kürzeren Clip wird bis zum Ende wiederholt
vom ersten Clip
Layer
Subtract
vom längeren Clip
StackHorizontal, StackVertical
Interleave
(fps vom ersten Clip)
x
(Anzahl der Clips)
2x frame-Anzahl vom längeren Clip

Wie man sehen kann, sind die Funktionen nicht völlig symmetrisch sondern nehmen manche Eigenschaften vom ERSTEN Clip.


Plugins

Mit diesen Funktionen können externe Filter zu AviSynth hinzugefügt werden.

LoadPlugin ("dateiname"[,...])

Lädt ein oder mehrere externe AviSynth plugins (DLLs).


LoadVirtualDubPlugin ("dateiname","filtername", preroll)

So wird ein plugin geladen, das für VirtualDub geschrieben wurde. "dateiname" ist der Name der .vdf-Datei. Nach dem Aufruf dieser Funktion kann das Filter mit "filtername" in AviSynth benutzt werden. VirtualDub Filter unterstützen nur das RGB32-Farbformat. Wenn das Video in einem anderen Format vorliegt, muss man ConvertToRGB32 verwenden (ConvertToRGB reicht nicht).

Das Ergebnis mancher Filter hängt von vorhergehenden frames ab, für diese muss preroll mindestens die Anzahl der frames sein, die das Filter zum Auffüllen seiner internen Speicher benötigt.


LoadVFAPIPlugin ("filename","filtername")

So können VFAPI plugins (TMPGEnc import plugins) verwendet werden.


Plugin autoload und and name precedence v2

Es ist möglich, alle plugins und Skripte mit benutzer-definierten Funktionen oder globalen Variablen in einem Verzeichnis zu speichern, aus dem dann alle Dateien mit den Endungen .AVS and .DLL beim Starten von AviSynth geladen werden (dynamisch wenn vom Skript wirklich benötigt).

Skripte in diesem Verzeichnis sollten nur Funktions-Definitionen und globale Variable, aber nicht den Teil der Videobearbeitung beinhalten (also kein AviSource,...), sonst können seltsame Fehler auftreten. Auch sollten keine anderen Dateien in dieses Verzeichnis gespeichert werden.

Der Verzeichnisname ist in der registry gespeichert. Man kann eine .REG-Datei mit folgendem Inhalt doppelklicken, um den Pfad zu setzen (natürlich vorher den wirklichen Pfad einsetzen):

REGEDIT4


[HKEY_LOCAL_MACHINE\SOFTWARE\Avisynth]
"PluginDir"="c:\\programme\\avisynth\\plugins"
       

Die Reihenfolge in der gleichnamige Funktionen aufgerufen werden ist: v2
1. Funktionen aus externen plugins (haben immer die höchste Priorität)
2. benutzer-defininierte Funktionen
3. eingebaute Funktionen

Innerhalb dieser Gruppen hat die am letzten geladenen Funktion Vorrang.