Dvb wiki script/Programmieranleitung
Vom DVB zur DVD, ein Wikibuch: Übersicht - Der Weg - Die Helferprogramme - Das Script - Installation - Bedienungsanleitung - Programmieranleitung |
In diesem Artikel wird näher darauf eingegangen, wie das Script aufgebaut ist und warum es so funktioniert, wie es funktioniert. Beschrieben wird dies an Hand der Scriptversion 0.8.0.
Inhaltsverzeichnis
- 1 Vorbereitungen
- 2 Die Funktionen
- 3 Hauptprogramm
- 4 Links
Vorbereitungen
Voreinstellungen
hauptverzeichnis=~/dvb_wiki_script ini_verz=~/.dvb_wiki_script aufnahme=~/DVB/Aufnahme druckschablonen=~/DVB/Druckschablonen videoclips=~/DVB/Videoclips speed=8 dvdgroesse=4600000000
Mit Hilfe dieser Variablen werden vom Benutzer veränderbare Einstellungen verwaltet.
- hauptverzeichnis: Das Hauptverzeichnis muß sich im persönlichen Verzeichnis des Nutzters befinden ( ~/ )
- ini_verz: In diesem versteckten Verzeichnis werden die Pfade zu den Helferprogrammen gespeichert.
- aufnahme: Hier sucht das Script nach Futter
- druckschablonen: In diesem Ordner werden die Schablonen für den DVD-Direktdruck erwartet
- videoclips: Speicherort für Videoclips. Dieses Verzeichnis dient auch als Grundlage einer Playlist für mplayer.
- speed: Diese Geschwindigkeit wird maximal zum Brennen der DVD verwendet
- dvdgroesse: An Hand dieser Größe wird entschieden, ob das Bearbeitungsergebnis auch auf eine einzige DVD passt.
Verzeichnisstruktur erstellen
mkdir $hauptverzeichnis 2>/dev/null
- mkdir: Es wird ein Verzeichnis erstellt
- $hauptverzeichnis: Der Verzeichnispfad wird aus der Variablen $hauptverzeichnis geholt ( z.B.: dvb_wiki_script )
- 2>/dev/null: Eventuelle Meldungen des Befehls mkdir werden ins Nirwana umgeleitet
Das Anlegen der weiteren Verzeichnisse erfolgt analog
Erkennung der Helferprogramme
Mit dieser Routine wird nachgesehen, ob die notwendigen Helferprogramme installiert sind. Und das funktioniert so:
Namen der notwendigen Helferprogramme
hilfsprogramm=( mplex dvdauthor ProjectX.jar normalize ffmpeg growisofs )
Die benötigten Helferprogramme werden als Array in der Variablen $hilfsprogramm abgelegt.
Suchschleife
for var in ${hilfsprogramm[*]} do ..... done
Für jedes Element (var) im Array, also für jedes Helferprogramm wird die Suchschleife zwischen do und done einmal durchlaufen
Ini-Datei anlegen
touch $ini_verz/$var
- touch: So noch nicht vorhanden, wird eine leere Datei erzeugt
- $ini_verz/$var: und zwar im Initialisierungsverzeichnis. Die Datei erhält dann den Namen der gerade aktuellen Schleifenvariablen (z.B. mplex)
Pfad lesen
hilfsvar=`cat $ini_verz/$var`
Mit Hilfe von cat wird der Inhalt dieser Datei, die den Pfad zu dem entsprechenden Helferprogramm enthalten sollte (z.B. /usr/bin), in die Variable hilfsvar kopiert.
Helferprogramm vorhanden?
if [ ! -e "$hilfsvar/$var" ]
Wenn das in der Variablen angegebene Helferprogramm (also im Beispiel /usr/bin/mplex) nicht existiert, oder wenn beim ersten Scriptlauf einfach noch nichts drinsteht in diesen Variablen
then ..... fi
dann geht zwischen then und fi die eigentliche Suche los:
Programmsuche
gefundene_pfade=`find /bin $HOME /opt /usr ! -path "$HOME/.*" -type f -name $var ! -printf "%h " 2>/dev/null`
- find: Suche
- -type f: ein normales Programm
- -name $var: mit dem Namen, der in var enthalten ist (also im Beispiel mplex)
- /bin $HOME /opt /usr: Die Suche beschränkt sich auf diese Pfade
- ! -path "$HOME/.*: und läßt dabei die versteckten Verzeichnisse im home-Verzeichnis aus.
- -printf "%h ": Vom Suchergebnis wird der Pfad genommen (Beispiel: /usr/bin )
- gefundene_pfade=: und in diese Variable geschrieben.
Wieviele Versionen des Helferprogramms gibt es?
pfadzahl=`echo "$gefundene_pfade" | wc -w`
- echo "$gefundene_pfade": Von dem, was in der Variablen $gefundene_pfade steht
- wc -w werden die Worte gezählt (und damit die Anzahl der gefundenen Pfade).
- pfadzahl=: diese Anzahl wird in der Variablen $pfadzahl zwischengespeichert.
Was wird damit gemacht?
case "$pfadzahl" in
In Abhängigkeit von der Anzahl der gefundenen Pfade passiert folgendes:
- 0): Das Programm wurde nicht gefunden. Nach einem Hinweis wird das Script beendet . Das fehlende Helferprogramm muß installiert werden..
- 1): Das Programm existiert genau einmal. Der dazugehörige Pfad wird in das Ini-Verzeichnis geschrieben.
- *): Das Programm existiert mehr als einmal.
Es wird nachgefragt (kdialog --combobox), welcher der Pfade verwendet werden soll. Dieser Pfad wird dann ins Ini-Verzeichnis geschrieben.
Zuweisung der Helferprogramme zu Variablen
# Hilfsprogramme laden mplex=`cat $ini_verz/mplex`/mplex
- `cat $ini_verz/mplex`: Aus dem Ini-Verzeichnis wird der Pfad zum Helferprogramm gelesen ( /usr/bin ).
- /mplex: Der Name des Helferprogramms wird hinzugefügt.
- mplex=: Das Ergebnis wird in die Variable $mplex geschrieben ( im Beispiel: /usr/bin/mplex)
Damit kann definiert ein bestimmtes Helferprogramm aufgerufen werden, auch wenn es auf der Festplatte in verschiedenen Versionen öfter vorkommt.
Initialisierungsdatei für ProjectX erzeugen
Die X.ini enthält folgende Einstellungen (ProjectX muß in der CVS-Version b28 oder größer installiert sein, damit alle Optionen wirksam werden)
- Application.Agreement=1: Ja zur Lizenz
- Application.Language=de: PJX startet auf deutsch
- Application.ActiveDirectory=$hauptverzeichnis/screenshots: Damit kommen die Screenshots dahin, wohin sie sollen
- CollectionPanel.Preview.SliderWidth=0: Der Vorschau-Slider bekommt dieselbe Breite wie das Vorschaufenster (gibt es erst ab Version b28)
- WindowPosition.Main.Width=9999: Die Breite des PJX-Fensters wird maximiert (sinnvoll erst ab Version b28)
- WindowPosition.Main.Y=0: Das Fenster wird ab dem Bildschirmrand gezeichnet
- optionPanel.NormalLog=0: Es wird keine Log-Datei geschrieben (die würde bloß stören)
- OptionPanel.CloseOnEnd=1: Nachdem PJX fertig ist, beendet es sich selber
Die X.ini wird im Hauptverzeichnis angelegt, von wo sie bei Bedarf von ProjectX geladen wird.
TIP
Werden im PJX-Fenster irgendwelche Einstellungen verändert, so werden diese Änderungen nicht in die X.ini übernommen. Das wurde absichtlich
so programmiert, damit man immer einen definierten Ausgangszustand hat.
Wird hier eine Speicherung gewünscht, kann dies durch einen zusätzlichen Eintrag in die X.ini erfolgen. Dann steht man allerdings vor dem Problem, oft
nicht zu wissen, mit welchen Einstellungen PJX denn nun tatsächlich startet. Da es mir immer wieder so ging, kann ich nur raten, die Speicherung ausgeschalten
zu lassen.
Playlist für mplayer
Erzeugen der Playlist
find $videoclips/* > ~/.mplayer/playlist
- find $videoclips/*: Die im Clipordner gespeicherten Videoclips werden gesucht.
- ~/.mplayer/playlist: Ihre Pfade werden in dieser Textdatei gespeichert.
Damit ist eine von mplayer verwendbare Playlist erzeugt worden
Abspielen der Playlist
TIP
Diese Wiedergabeliste kann mit folgendem Befehl abgespielt werden:
mplayer -xy 1280 -playlist ~/.mplayer/playlist -shuffle -vf pp=lb -fixed-vo
- mplayer: Aufruf von mplayer.
- -xy 1280: Grösse des Ausgabefensters. Es genügt die Angabe der horizontalen Pixelzahl, die vertikale Anzahl der Bildpunkte wird dann automatisch eingestellt.
- ~/.mplayer/playlist: Hier ist die Wiedergabeliste gespeichert.
Alle Angaben, die nach der Playlist kommen, beziehen sich auf die komplette Wiedergabeliste, nicht auf ein einzelnes Lied aus der Liste.
- -shuffle: Die Auswahl der Videoclips erfolgt nach dem Zufallsprinzip.
- -vf pp=lb: Einschalten eines linearen Deinterlace-Filters.
- -fixed-vo: Alle Clips werden in einem einzigen Fenster abgespielt.
Diesen Befehl habe ich in eine Desktop-Datei eingegeben, mit der ich die Wiedergabe starte.
Die Playlist und die Tonspuren
Sind im Stream mehrere Tonspuren vorhanden, wird mit dem eben erwähnten Befehl die erste Spur abgespielt. Welches die erste Spur ist, kann an verschiedenen Stellen beeinflusst weren:
- kaffeine: Bei den Einstellungen der gefundenen DVB-Programme läßt sich die Reihenfolge der Audio-PIDs festlegen.
- mplex: Beim Multiplexen läßt sich ebenfalls die Reihenfolge der Audio-Tracks im Stream festlegen. Im DVB-Script zum Beispiel wird als erste Tonspur AC3 (so vorhanden) verwendet.
Auch in mplayer kann eine Auswahl getroffen werden, welche Tonspur zum Zuge kommt:
-aid 128
Dieser Parameter sorgt in der Regel dafür, daß der AC3-Ton wiedergegeben wird.
Löschen der temporären Verzeichnisse
rm -r -- $hauptverzeichnis/tmp1/* 2>/dev/null
- rm -r: Lösche rekursiv
- $hauptverzeichnis/tmp1/*: alle Dateien und Verzeichnisse im Ordner $hauptverzeichnis/tmp1
TIP
Das rekursive Löschen kann, unbedacht angewendet, zu Problemen führen, da das angegebene Verzeichnis selbst ebenfalls gelöscht wird. Deshalb im obigen Befehl der Abschluss /*. Damit bleibt tmp1 selbst unangetastet, nur der Inhalt wird gelöscht. Vorsicht also bei Experimenten mit dem Befehl rm.
Der doppelte Bindestrich nach rm -r schließt den Löschbefehl ab. Alles, was nun kommt, wird nicht mehr als Option interpretiert. Das wurde aus folgendem Grund in den Befehl eingebaut:
Würde die Variable $hauptverzeichnis nur den Buchstaben f enthalten, dann würde die Bash dieses f als weitere Option für den Löschbefehl interpretieren. Aus dem noch relativ unbedenklichen rm -r würde ein hochgefährliches rm -rf. Denn dieser Befehl, als root angewendet, kann unter Umständen die komplette Festplatte löschen!
Die Funktionen
Abbruch
benutzerabbruch ()
echo "Abbruch durch den Benutzer"
Diese Meldung wird über die Konsole ausgegeben
programmende
Dann wird die Funktion programmende () aufgerufen.
funktionsabbruch ()
echo "$1"
Der in $1 gespeicherte Text erscheint im Konsolenfenster.
programmende
Danach wird die Funktion programmende () aufgerufen.
TIP
Beim Aufruf einer Funktion können dieser Argumente übergeben werden. Das erste Argument kann innerhalb der Funktion dann über die Variable $1 aufgerufen werden.
Beispiel:
funktionsabbruch "Heute scheint die Sonne"
Der "Sonnentext" wird der Funktion bei ihrem Aufruf als Argument übergeben und steht dann dort in der Variablen $1 für weitere Schandtaten zur Verfügung.
programmende ()
echo "Ende"
Im Konsolenfester wird der Text Ende angezeigt
kdialog --msgbox "Programmende"
- kdialog: Es wird ein KDE-Dialogfenster geöffnet,
- --msgbox: das als Info-Fenster formatiert ist.
- "Programmende": Im Fenster wird die Meldung Programmende angezeigt
Nach dem Drücken auf den OK-Knopf im kdialog-Fenster wird mit
exit
das Script beendet.
auswahl_hauptmenue=`kdialog --caption "Hauptmenue" --geometry 200x250+500+400 --radiolist "Bitte einen Aufgabenbereich wählen" \
- kdialog: Das KDE-Dialog-Programm
- --caption "Hauptmenue": öffnet ein Fenster, das den Namen "Hauptmenue" trägt
- --geometry 200x250+500+400: und diese Größe und Position hat
- --radiolist: als Liste mit Radio-Buttons
- "Bitte einen Aufgabenbereich wählen": Das wird gefragt.
- auswahl_hauptmenue=`...`: In dieser Variablen wird die zur Antwort gehörende Nummer gespeichert.
Diese Nummer wird dann später vom Hauptprogramm ausgewertet.
1 "VIDEO-DVD" on \ 2 "TS-Stream" off \ 3 "Videoclips" off \ 8 "DVD bedrucken" off`
Der per Default aktivierte Eintrag der Liste wird durch das on festgelegt.
if [ $? != 0 ] then benutzerabbruch fi
Wenn im Auswahlfenster auf Abbrechen gedrückt wird, dann wird das Script beendet.
TIP
Der Rückgabewert von kdialog ist abhängig davon, welcher Knopf gedrückt wurde. Wird zum Beispiel OK gedrückt, dann ist der Wert Null. In jedem anderen Fall ist er ungleich Null.
Dieser Rückgabewert steht in der Variablen $? und kann so ausgewertet werden.
Diese Funktionen sind genauso programmiert wie die Funktion hauptmenue (). Der Unterschied ist, daß die Kennzahlen in der Variablen was_tun gespeichert werden.
Auswahl Quelldateien
filmauswahl_dvd ()
Die Variable $brenn_pfad wird von growisofs benötigt. In ihr steht die zu brennende DVD-Stuktur.
case $was_tun in 11) brenn_pfad=$hauptverzeichnis/dvdstruktur ;; 12) brenn_pfad=$hauptverzeichnis/dvdstruktur ;; 21) brenn_pfad=$hauptverzeichnis/tmp1 ;; 22) brenn_pfad=$hauptverzeichnis/tmp1 ;; esac
In Abhängigkeit von den Aufgaben (und damit vom Inhalt der Variablen $was_tun) wird die Variable $brenn_pfad mit den erforderlichen Daten gefüttert.
quelldatei=`kdialog --caption "Filmauswahl" --geometry 600x500-0+0 --getopenfilename ${aufnahme_pfad}`
- kdialog: Das KDE-Dialog-Programm
- --caption "Filmauswahl": öffnet ein Fenster, das den Namen "Filmauswahl" trägt
- --geometry 600x500-0+0: und diese Größe und Position hat
- --getopenfilename: Es wird ein KDE-Fenster geöffnet, in dem aus einer Liste von Dateien ausgewählt werden kann
- ${aufnahme_pfad}: Es werden die Dateien in diesem Pfad zur Auswahl angeboten.
- quelldatei=`..`': Die ausgewählte Datei wird in die Variable $quelldatei geschrieben.
verzeichnisauswahl_dvd ()
case $was_tun in 13) verzeichnistyp="*_dvd" ;; 23) verzeichnistyp="*_ts" ;; esac
Die Variable $verzeichnistyp wird mit dem String *_dvd bzw. *_ts belegt.
anzahl_der_sicherungen=`find $hauptverzeichnis/sicherung/$verzeichnistyp -maxdepth 0 -type d | wc -l`
Die Anzahl der gesicherten Arbeitsergebnisse (*_dvd oder *_ts) wird ermittelt und zwischengespeichert.
hilfsverzeichnis=`find $hauptverzeichnis/sicherung/$verzeichnistyp -maxdepth 0 -type d`
Die Namen der gesicherten Arbeitsergebnisse (*_dvd oder *_ts) werden ermittelt und zwischengespeichert.
case $anzahl_der_sicherungen in
In Abhängigkeit der Anzahl der gesicherten Arbeitsverzeichnisse ergeben sich folgende Möglichkeiten:
- Anzahl 0: Das Script wird nach einem Hinweis beendet, da keine passene Sicherung zum Brennen gefunden wurde
- Anzahl 1: Die gefundene Sicherung wird zur Weiterverarbeitung in die Variable $verzeichnis geschrieben.
- Anzahl *: Die gewünschte Sicherung wird mit kdialog ausgewählt und zur Weiterverarbeitung in die Variable $verzeichnis geschrieben.
brenn_pfad=$verzeichnis
Die ausgewählte Sicherung wird in die Variable brenn_pfad geschrieben. Damit erhält growisofs die Info, was zu brennen ist.
Eingangsverarbeitung
pjx_demux_gui ()
java -jar $pjx -demux -gui -ini $hauptverzeichnis/X.ini -out $hauptverzeichnis/tmp1 -name film "$quelldatei"
- java -jar: Es wird ein Java-Programm gestartet
- ${pjx}: und zwar das Programm ProjectX (z.B.: ~/ProjectX/ProjectX.jar)
- -demux: Der mpeg-Stream wird demultiplext
- -gui: PJX startet mit einer graphischen Oberfläche
- -ini $hauptverzeichnis/X.ini: PJX verwendet diese Initialisierungsdatei
- -out $hauptverzeichnis/tmp1: Hierhin wird das Bearbeitungsergebnis geschrieben
- -name film: Die Ausgabedatei erhält den Basisnamen "film"
- $quelldatei:Dieser Stream wird verarbeitet
audio_video_summe=`du -bc $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2 $hauptverzeichnis/tmp1/*.m2v | cut -f1 | tail -n 1`
- du: Bashprogramm, welches den Platzverbrauch von Dateien schätzt
- -b: Ausgabe der Größe in Bytes
- -c: Erzeugen einer Gesamtsumme (-b und -c sind zusammen gefasst nach -bc.)
- $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2 $hauptverzeichnis/tmp1/*.m2v: Alle mp2-, ac3- und Videodateien gehen in die Größenermittlung ein.
- tail -n 1: Nur die letzte Zeile dessen, was "du" ausgeben will, wird auch tatsächlich ausgegeben (nämlich unsere Gesamtgrösse)
- cut -f1: Von dieser letzten Zeile wird nur das erste Feld ausgegeben, also die reine Zahl
- audio_video_summe=`....`: Diese Groesse wird in die Variable audio_video_summe geschrieben
Und was soll das Ganze? Na, ganz einfach! Wir haben damit die ermittelt, wie groß das ist, was wir später auf die DVD brennen wollen. Und an Hand dieser Grösse können wir nun erkennen, ob das Bearbeitungsergebnis überhaupt auf die DVD passt.
if [ $audio_video_summe -ge $dvdgroesse ] then kdialog --error "Das Bearbeitungsergebnis wird zu groß für eine DVD" programmende fi
Wenn das Bearbeitungsergebnis grösser ist als das in dvdgroesse enthaltene Fassungsvermögen der DVD, dann brauchen wir gar nicht weiter machen. In diesem Fall wird das Script mit einem Hinweis abgebrochen.
pjx_ts_gui ()
java -jar $pjx -tots -gui -split 4300 -ini $hauptverzeichnis/X.ini -out $hauptverzeichnis/tmp1 -name film "$quelldatei"
- java -jar: Es wird ein Java-Programm gestartet
- ${pjx}: und zwar das Programm ProjectX (z.B.: ~/ProjectX/ProjectX.jar)
- -tots: Der Film wird zum TS-File gewandelt
- -gui: PJX startet mit einer graphischen Oberfläche
- -split 4300: Bei 4300 Mbyte wird die Aufnahme gesplittet (mehr passt nicht auf eine DVD drauf)
- -ini $hauptverzeichnis/X.ini: PJX verwendet diese Initialisierungsdatei
- -out $hauptverzeichnis/tmp1: Hierhin wird das Bearbeitungsergebnis geschrieben
- -name film: Die Ausgabedatei erhält den Basisnamen "film"
- $quelldatei:Dieser Stream wird verarbeitet
mpeg1_input ()
$ffmpeg -i "$quelldatei" $hauptverzeichnis/tmp1/film.mp2 -vcodec copy $hauptverzeichnis/tmp1/film.m1v
- ${ffmpeg}: Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg),
- -i ${quelldatei}: um diesen Video-Clip zu demultiplexen
Bearbeitung
normalisieren ()
EXKURS
Meine schon etwas in die Jahre gekommene Stereoanlage zeichnet sich noch dadurch aus, daß ein großer Drehknopf zur Lautstärkeregelung vorhanden ist. Und den kann man aufdrehen, bis buchstäblich die Wände wackeln (4 x 70 W Sinus können ganz schön Dampf machen). Aber irgendwann ist Schluß. Nein, nicht daß die Nachbarn sich
beschweren würden. Der Regler ist vielmehr am Rechtanschlag angelangt und die Anlage liefert die maximal mögliche Lautstärke.
Auch die Audio-Files, mit denen wir hier im Script herumjonglieren, kennen einen maximal möglichen Pegel. Der ist nämlich denn erreicht, wenn die Bytes, welche die Lautstärke im Digitalsignal kennzeichnen ihre Maximalwerte erhalten (z.B.: FFFF bei 4 Byte, mehr geht einfach nicht, es sei denn, man macht ein fünftes Byte auf).
Fernsehsender beanspruchen für sich eine gewisse Individualität. Manchmal kommt es mir so vor, daß diese Individualität dadurch zum Ausdruck gebracht wird, daß jeder Sender sein Programm mit einer anderen Lautstärke ausstrahlt. Das ist schon beim Zappen unangenehm. Noch unerfreulicher wird diese Tatsache jedoch, wenn die mühsam aufgenommenen Videoclips mit Hilfe einer Wiedergabeliste abgespielt werden sollen. Denn bei jedem zweiten Stück ist ein Griff zum Lautstärkeregler notwendig. Beim einen Lied versteht man kaum, was aus den Lautsprechern kommt, beim nächsten Mal brüllt es einen geradezu aus dem Sessel heraus.
Ein PCM-Signal auf einen definierten Lautstärkepegel zu bringen, ohne die Dynamik selbst zu verändern, wird "normalisieren" genannt.
Mit dem in dieser Funktion verwendeten Befehl "normalize" wird die lauteste Stelle in dem Audio-File "film.mp2.wav" auf -12dBfs (also 12dB unter "full scale") gebracht. Der Rest wird entsprechend mitgezogen. Aber, wie gesagt, ohne Verlust an Dynamik.
Das Normalisieren funktioniert nur mit PCM-Files. eine komprimierte Datei (mp2) muß erst zu PCM (wav) decodiert werden.
Beim mp3-Format wird übrigens eine andere Strategie zum Normalisieren angewandt, und zwar eine ohne Umcodierverluste. Hier bleibt das ursprünliche File erhalten. Lediglich in den Header wird die Information geschrieben, um wieviel die Lautstärke angepasst werden müsste. Der Player wertet diesen Header dann aus und regelt entsprechend die Lautstärke beim Abspielen des Files. Die Voraussetzung ist hier sebstverständlich ein Player, der dies Auswertung auch verarbeiten kann.
Dies nur zur Information, daß es noch eine Welt ausßerhalb von mp2 gibt.
Und noch etwas gibt es. Und das nennt sich ac3, zu Deutsch "Dolby digital"
Ton-Dateien vorbereiten
mv $hauptverzeichnis/tmp1/film.mp2 $hauptverzeichnis/tmp2 rm -- $hauptverzeichnis/tmp1/*.mp2
Die zu normalisierende Tondatei wird nach tmp2 verschoben. Anschließend werden alle(!) mp2-files in tmp1 gelöscht.
mp2 decodieren
$ffmpeg -i $hauptverzeichnis/tmp2/film.mp2 $hauptverzeichnis/tmp2/film.mp2.wav
Aus mp2 wird mit Hilfe von ffmpeg wav.
normalisieren
$normalize $hauptverzeichnis/tmp2/film.mp2.wav
Das wav-File wird normalisiert. Es überschreibt sich dabei selbst mit dem Ergebnis.
encodieren zu mp2
$ffmpeg -i $hauptverzeichnis/tmp2/film.mp2.wav -acodec mp2 -ab 192k $hauptverzeichnis/tmp1/film.mp2
Aus der wav-Datei wird wieder ein mp2-File gemacht.
- ${ffmpeg}: Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg)
- -i $hauptverzeichnis/tmp2/film.mp2.wav: Dieses PCM-file
- -acodec mp2: wird zu einem mp2-File encodiert,
- -ab 192k: welches eine Audio-Bitrate von 192k erhält (mp2-Standard)
- $hauptverzeichnis/tmp1/film.mp2: Das Ergebnis findet man dann hier
ac3_behalten ()
if [ ! -e $hauptverzeichnis/tmp1/*.ac3 ] then funktionsabbruch "Der Clip enthält keinen AC3-Ton. Das Script wird nun beendet." fi
Sinn dieser Funktion ist es, ausschließlich die ac3-Tondateien für die Weiterverarbeitung zu selektieren. Dazu wird nachgesehen, ob in $hauptverzeichnis/tmp1 irgend etwas mit der Endung .ac3 existiert. Ist das nicht der Fall, so wird das Script nach einem Hinweis beendet.
rm -- $hauptverzeichnis/tmp1/*.mp2
Gibt es allerdings ac3-Tonfiles, dann werden alle mp2-Files gelöscht. Und ratet einmal, was dann übrig bleibt.
mp2_behalten ()
Das Gleiche wie oben, nur werden hier die mp2-Tondateien behalten.
multiplexen ()
Mit mplex wird aus den getrennten Bild- und Ton-Dateien ein mpg-File gemacht, welches für das spätere Authoring mit dvdauthor schon vorbereitet ist.
Vorbereiten der Dateien
- mpeg1_video=: Es wird eine leere Variabe mpeg1_video erzeugt
- mpeg1_video=`find $hauptverzeichnis/tmp1 | grep "m1v"`: In diese Variable werden die Namen der Dateien geschrieben, die sich in tmp1 befinden und ein "m1v" im Namen haben.
Dasselbe geschieht mit den Variablen mpeg2_video, mp2_audio und ac3_audio. Ist im tmp_pfad keine Datei vorhanden, die das angegebene Bitmuster enthält, dann bleibt die entsprechende Variable leer.
Das eigentliche Multiplexen
$mplex -v1 -f8 -o $hauptverzeichnis/tmp1/film.mpg $mpeg1_video $mpeg2_video $ac3_audio $mp2_audio
- ${mplex}: Aufruf von mplex (z.B.: /usr/bin/mplex)
- -v1: Fortschrittsanzeige (beim Befehl mplex leider nicht so sehr fortschrittlich)
- -f8: Format zur späteren Erzeugung einen DVD
- -o $hauptverzeichnis/tmp1/film.mpg: Das ist das Ergebnis
- ${mpeg1_video} ${mpeg2_video} ${mp2_audio} ${ac3_audio}: In diesen Variablen stehen die Pfade zu den Dateien, die multiplext werden. Leere Variablen werden von mplex einfach ignoriert.
if [ ! -e $hauptverzeichnis/tmp1/film.mpg ] then funktionsabbruch "Es konnte keine Datei multiplext werden!" fi
Wenn nicht multiplext wurde, weil es zum Beispiel nichts zu multiplexen gab, dann existiert es auch keine mpg-Datei in tmp1. In diesem Fall wird das Programm beendet.
Hier wird der einfachste Fall einer DVD-Struktur erzeugt (ohne DVD-Menue).
$dvdauthor -o $hauptverzeichnis/dvdstruktur -t $hauptverzeichnis/tmp1/film.mpg
- ${dvdauthor}: Programmaufruf von dvdauthor (z.B.: /usr/bin/dvdauthor)
- -o $hauptverzeichnis/dvdstruktur: Das Ergebnis wird hier zu finden sein
- -t: Es wird 1 Titel erzeugt (Ordner AUDIO_TS: leer / Ordner VIDEO_TS: Inhalt ifo-files und vob-files)
- $hauptverzeichnis/tmp1/film.mpg: Diese mpg-Datei wird als Eingangsdatei verwendet
$dvdauthor -o $hauptverzeichnis/dvdstruktur -T
- -o $hauptverzeichnis/dvdstruktur: Im Ordner $hauptverzeichnis/dvdstruktur/VIDEO_TS
- -T: werden noch folgende Dateien erzeugt: VIDEO_TS.BUP und VIDEO_TS.IFO
Brennen
brennen_video_dvd ()
Mit dieser Funktion wird die fertige DVD-Struktur auf DVD kopiert. Das Ergebnis ist eine Video-DVD
$growisofs -speed=$speed -dvd-compat -Z /dev/dvd -dvd-video $brenn_pfad
- ${growisofs}: Programmaufruf von growisofs (z.B. /usr/bin/growisofs)
- -speed=$speed: maximale Geschwindigkeit, mit der gebrannt werden darf
- -dvd-compat: Schließt nach dem Brennen die DVD ab, um maximale Kompatibilität zu gewährleisten
- -Z /dev/dvd: Den ersten Satz Daten auf die DVD brennen (,der in unserem Fall auch der einzige ist, nämlich die DVD-Struktur)
- -dvd-video: udf-Filesystem für Video-DVD's
- $brenn_pfad: Was hier drin steht, wird gebrannt
Bevor allerdings gebrannt werden kann, muß sich erst einmal eine leere DVD im Laufwerk befinden. Das können wir feststellen, indem wir in der DVD-Schublade nachsehen. Oder wir lassen das Script für uns nachgucken und starten growisofs im "Trockenlauf":
$growisofs -dry-run -speed=$speed -dvd-compat -Z /dev/dvd -dvd-video $brenn_pfad
An Hand des Rückgabewertes von growisofs kann erkannt werden werden, ob die DVD bereit ist, Daten aufzunehmen. Dieser Rückgabewert ist Null, wenn alles ok ist. Er wird über die Variable $? ausgewertet.
while [ $? != 0 ] do ...... done
Solange $? keine Null enthält, die DVD also nicht bereit ist, wird die Schleife zwischen do und done abgearbeitet:
kdialog --warningcontinuecancel "DVD nicht bereit"
KDE-Dialogbox mit Weiter- und Abbruchknopf
if [ $? != 0 ] then benutzerabbruch fi
Wenn der Rückgabewert von kdialog ungleich Null ist (wieder über $? zu erfragen), dann wurde der Abbruchknopf betätigt und das Script beendet sich. Wurde dagegen auf Weiter gedrückt, dann wird Null zurückgegeben und der nächste Trocklauf zur DVD-Erkennung startet. Ist die DVD endlich bereit, dann wird die while-Schleife wird verlassen und die DVD wird mit dem oben erwähnten Befehl gebrannt.
Nach Beendigung des Brennens beendet sich das Programm.
brennen_ts ()
Brennen der TS-Files als Daten-DVD
dvdzahl=`find ${brenn_pfad} -type f | wc -l`
- find ${brenn_pfad}: Der Pfad mit den zu brennenden Files wird durchsucht
- -type f: nach normalen Dateien
- wc -l: und es wird gezählt, wieviele Dateien das sind.
- dvdzahl=`....`: Diese Anzahl wird mit Hilfe der Substitution in die Variable $dvdzahl geschrieben
for((i=1; i<=${dvdzahl}; i++))
In dieser for-Schleife passiert nun folgendes: Es erfolgt der schon von brennen_dvd () bekannte Trockenlauf zur DVD-Erkennung. Ist die angeforderte DVD bereit, wird gebrannt:
$growisofs -speed=$speed -Z /dev/dvd -allow-limited-size -R -J $brenn_pfad/"film($((i-1)))[remux].ts"
- ${growisofs}: Programmaufruf für growisofs (z.B. /usr/bin/growisofs)
- -speed=$speed: maximale Geschwindigkeit, mit der gebrannt werden darf
- -Z /dev/dvd: Den ersten Satz Daten auf die DVD brennen (,der in unserem Fall auch der einzige ist, nämlich die TS-files)
- -allow-limited-size: Damit lassen sich Dateien bis zu 4,3GB brennen
- -R: Rock Ridge Erweiterung benutzen
- -J: Joliet-Extention benutzen (macht es leichter, die DVD unter Windows abzuspielen)
- $brenn_pfad/"film($((i-1)))[remux].ts: Diese Datei auf DVD brennen
Es werden in der for-Schleife solange DVDs angefordert, bis alle Daten gebrannt sind.
Sichern
sichern_dvd_struktur ()
Diese Funktion sichert die DVD-Struktur
sicherungsordner="$(date +%Y%m%d%H%M%S)_dvd"
Die Variable $sicherungsordner wir mit einem String gefüllt, der sich aus dem aktuellen Datum und der momentanen Uhrzeit zusammensetzt.
mkdir $hauptverzeichnis/sicherung/$sicherungsordner
Der Sicherungsordner wird angelegt
mv $hauptverzeichnis/dvdstruktur/* $hauptverzeichnis/sicherung/$sicherungsordner
und die DVD-Struktur in diesen Ordner verschoben.
funktionsabbruch "Datei gesichert nach $hauptverzeichnis/sicherung/$sicherungsordner. Programm beendet"
im Terminalfenster wird angezeigt, welche Datei wohin gesichert wurde. Danach wird das Script beendet.
sichern_ts ()
Diese Funktion sichert die TS-files
sicherungsordner=$(date +%Y%m%d%H%M%S)_ts
Die Variable $sicherungsordner wir mit einem String gefüllt, der sich aus dem aktuellen Datum und der momentanen Uhrzeit zusammensetzt.
mkdir ${sicherungs_pfad}/${sicherungsordner}
Der Sicherungsordner wird angelegt
mv $hauptverzeichnis/tmp1/*.ts $hauptverzeichnis/sicherung/$sicherungsordner
und das ts-file in diesen Ordner verschoben.
funktionsabbruch "Datei gesichert nach $hauptverzeichnis/sicherung/$sicherungsordner. Programm beendet"
im Terminalfenster wird angezeigt, welche Datei wohin gesichert wurde. Danach wird das Script beendet.
< sichern_clip ()
Diese Funktion speichert einen Videoclip
clipspeicher=`kdialog --title "$quelldatei" --getsavefilename $videoclips`
- kdialog: Programmaufruf für kdialog (z.B. /usr/bin/kdialog)
- --title "$quelldatei": Überschrift für das KDE-Fenster
- --getsavefilename: Generiert ein KDE-Fenster, in dem ein Zielverzeichnis zum Speichern ausgewählt werden kann. Auch der Name, den der zu speichernde Clip bekommen soll, wird angegeben.
- $videoclips: In dieses Verzeichnis wird bevorzugt gespeichert
- clipspeicher=`....`: Der gewählte Name und Speicherpfad steht dann in dieser Variable zur Verfügung
if [ $? != 0 ] then benutzerabbruch fi
Damit wird die Abbruchtaste des KDE-Dialogs ausgewertet.
if [ -e "$clipspeicher" ] then ...... fi
Existiert bereits ein Clip mit dem gleichen Namen, dann
kdialog --yesno "Dieser Clip ist schon gespeichert. Überschreiben?"
wird gefragt ob der Clip überschrieben werden darf.
if [ $? != 0 ] then sichern_clip fi
Wurde Nein gedrückt, dann wird die Funktion sichern_clip () erneut aufgerufen. Der Dialog beginnt dann von vorne. Wurde allerdings Ja gedrückt, dann wird die if-Abfrage verlassen.
mv $hauptverzeichnis/tmp1/film.mpg "$clipspeicher"
Der Videoclip wird gespeichert, wobei ein eventuell schon vorhandener Clip gleichen Namens überschrieben wird. Anschließend wird das Programm beendet mit einem Hinweis, welcher Clip gespeichert wurde.
Hauptprogramm
Mit Aufruf der Funktion hauptmenue () wird ein Aufgabenbereich gewählt. Entspechend dieses Aufgabenbereiches wird (über case) zu den Untermenues verzweigt.
Am Beispiel des Untermenues mit der Kennziffer 11 wird die Funktionsweise des Hauptprogramms gezeigt.
- filmauswahl: Das gewünschte Videofile wird geladen
- pjx_demux_gui: und mit ProjectX geschnitten und demultiplext
- multiplexen: Bild und Ton werden nun wieder gemultiplexed.
- authoring_ohne_menue: Vom mpg-file wird die DVD-Struktur erstellt,
- brennen_video_dvd: um danach als Video-DVD gebrannt zu werden.
- programmende: Der Name sagt alles.
Links
In der Artikelübersicht ist eine ausführliche Linkliste enthalten: vom DVB zur DVD: Vorstellung der Wiki-Artikel in dieser Serie
Vom DVB zur DVD, ein Wikibuch: Übersicht - Der Weg - Die Helferprogramme - Das Script - Installation - Bedienungsanleitung - Programmieranleitung |