Mit AviSynth Untertitel zentriert auf Video ausgeben (Infotext)

Mi, 28.04.2010 - 18:21 -- Daniel Espendiller

Zum Ausgeben eines Begrüßungstextes soll auf einem TV / LCD ein Video ausgegeben werden, über dem ein sich wechselnder Text gelegt wird. Es sollen mehrere Textobjekte hintereinander abgespielt werden können, die alle paar Sekunden animiert wechseln. Eine Videobearbeitungssoftware kommt nicht in Frage, da sich der Text mehrmals täglich ändern soll.
Zur Umsetzung eignet sich AviSynth, es ist quasi eine Programmiersprache zur Videobearbeitung. Die Videoausgabe werden hierzu in echt Zeit gerendert und direkt in einem Videoplayer ausgegeben, am besten nimmt man hierfür den Windows Media Player. Die AviSynth Skriptsprache ist recht mächtig, so können Videos geschnitten, zusammengefügt werden, Effekte eingefügt werden, Farbkorrekturen gemacht werden und so weiter.

Installation

Neben AviSynth brauchen wir noch das Untertitel Plugin VSFilter.dll (Download), welches wir in unserem Skript nachladen. Dazu einfach die Datei in den %windir%\system32 Ordner packen, damit haben wir die Datei in einem Suchpfad und sie wird direkt gefunden. Natürlich können wir auch direkt den Pfad zur DLL angeben. Weiter brauchen wir einen Codec der nicht zu viel CPU-Leistung frist. Dazu nimmt man am besten den freien XVID. Wir können übrigens keine Player nehmen, die bereits Codecs enthalten (z.B. VLC), da AviSynth DirectShow von Windows nutzt.

Videos

Seine Videos sollte man etwas aufbereiten. Da die Videos in Echtzeit gerendert werden, muss man auf seine CPU achten. Auflösungen über >720 sind mit Vorsichtig zu genießen. Als Codec bietet sich wie erwähnt XVID an. Wer mehrere Videos zusammenhängen will muss penibel darauf achten, das die Videos identische Formate haben (Auflösung, FPS, Audio, ...). Zum Einfachen anpassen nutze ich meinen kleinen VideoConverter.
Testen: Die Videos müssen sich mit dem Windows Media Player abspielen lassen, nur so kann man sie später in AviSynth auch nutzen.

Untertitel missbrauchen

Ich konnte keine direkte Video-Effekte innerhalb von AviSynth finden die gezielt die gewünschte Funktionen erlauben. Also missbrauchen wir etwas die Untertitel Funktionen. Normalweise werden sie bekanntlich im unteren Bereich eines Videos angezeigt. Es gibt mehre Standard-Formate zum Einbinden von Untertitel. Besonders gut zum Designen und Positionieren bleibt uns nur Advanced SSA (.ass), alle anderen Formate fallen flach.
Eine Vorlagendatei befindet sich unten, wer die Textfarbe, Textgröße oder sonstiges ändern will, kann ja mal etwas rumspielen. Viel interessanter sind für uns mehr die Ausgaben der Textobjekte. Wie bei Untertiteln üblich setzt man eine Zeitangabe von wann bis wann ein bestimmter Text angezeigt werden soll. Zur Generierung nutze ich ein kleines PHP-Skript. Da wir innerhalb der Untertitel nicht wissen wie lange ein Video läuft, generieren wir einfach munter Texte bis wir meinen, dass wir genug haben :).

Abspielen

Zur Wiedergabe unseres Videoskriptes brauchen wir einem Player, der DirectShow nutzt. Hierzu bietet sich der Windows Media Player oder Mediaplayer Classic an. Das Einrichten einer Endlosschleife lässt in den Programmen meistens einstellen. Zum Abspielen auf einem TV und einem daran angeschlossen PC nutze ich eine Weboberfläche. So kann von jedem PC im Netzwerk die Wiedergabe am TV remote verändert und steuern. Die komplette Geschichte würde hier den Rahmen sprengen, deswegen hier den relevanten Teil zum Starten des Media Players auf dem Remote-PC per PHP über einen Webserver:

$WshShell = new COM("WScript.Shell");
#$oExec = $WshShell->Run($root.$pfad."\\mplayerc.exe /play ".$root.$pfad."\\video.avs", 3, false);
$oExec = $WshShell->Run("wmplayer.exe /play ".$root.$pfad."\\video.avs /fullscreen", 3, false);

Untertitel Vorlage

Achtung: Eventuell Videogröße anpassen, sonst sehen die Schriften sehr seltsam aus.


[Script Info]
Title: Laufschrift Demo
Original Editing: katjarella
ScriptType: v4.00+
Collisions: Normal
PlayResX: 720
PlayResY: 576
PlayDepth: 0
Timer: 100.0000
WrapStyle: 0

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,65,&H00FFFFFF,&H00555555,&H00555555,&H00555555,1,0,0,0,100,100,0,0,1,0,3,8,20,20,30,0

[Events]
Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:07.00,Default,,0000,0000,0000,,{\fad(1400,1400}{\be1}\N\N\N\N\NHello\NWorld{\fs20\b0}
Dialogue: 0,0:00:07.00,0:00:14.00,Default,,0000,0000,0000,,{\fad(1400,1400}{\be1}\N\N\N\N\NThis is a\Nnice Trailer{\fs20\b0}

AviSynth Datei (video.avs)

Hier findet die eigentliche Generierung des Videos statt. Es werden zwei Video zusammengefügt, eventuell die Helligkeit des Videos etwas verringert (Text kann besser gelesen werden) und schließlich unsere gefakten Untertitel geladen.


#load the subtitle addin, put this in the system32 folder
LoadPlugin("VSFilter.dll")

#load some video, we combine two videos, they must have the same resolution and fps
#since this is a avi file we need the codec, mustly xvid
avisource("D:\20100203_132254_neu.avi") + avisource("D:\20100203_132254_neu.avi")

#we can also use directshow input but this is very complicate
#DirectShowSource("D:\20100203_132254_neu1.mp4") + DirectShowSource("D:\20100203_132254_neu1.mp4")

#reduced brightness so we can better read text input / subtitles
#Tweak(bright=-100,cont=1.2)

#finally load the subtitle text
TextSub("text.ass")

Untertitel generieren (text.ass)

Dieses PHP Skript geniert uns eine text.ass, die wie dann in AviSynth als Untertitel nutzen können.

#Example text array
$split = array("\r\n\r\n\r\n\r\n\r\nHello\r\nWorld","\r\n\r\n\r\n\r\n\r\nThis is a\r\nnice Trailer");

#show time for each object
$showsec=7;

#some variables; we can make it better
$out='';
$currentsec=0;

for($i=0;$i<120;$i++) {
foreach ($split as $line) {
#convert linebreaks
$line = str_replace("\r\n","\N",$line);

#use subtitle item template
$out.=str_replace(array("%start%","%ende%","%text%"),array(date("i:s", $currentsec),date("i:s", $currentsec+$showsec),$line),ass_template('line'))."\n";
$currentsec += $showsec;
}
}

#output
echo ass_template('header').$out;

function ass_template($typ) {
$ass = array();

$ass['header'] = '[Script Info]
Title: Laufschrift Demo
Original Editing: katjarella
ScriptType: v4.00+
Collisions: Normal
PlayResX: 720
PlayResY: 576
PlayDepth: 0
Timer: 100.0000
WrapStyle: 0

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,65,&H00FFFFFF,&H00555555,&H00555555,&H00555555,1,0,0,0,100,100,0,0,1,0,3,8,20,20,30,0

[Events]
Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text
';

$ass['line'] = 'Dialogue: 0,0:%start%.00,0:%ende%.00,Default,,0000,0000,0000,,{\fad(1400,1400}{\be1}%text%{\fs20\b0}';

return $ass[$typ];
}