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")) |
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) |
Das ist das gleiche als:
funktionen(ausdruck, argumente) |
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 |
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: |
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: |
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.
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