Dvb wiki script/Programmieranleitung: Unterschied zwischen den Versionen

Aus Linupedia.org
Wechseln zu: Navigation, Suche
(Bis zum Ende)
(export VIDEO_FORMAT=PAL)
 
(19 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
{{Dvbscript navigationsbox}}
+
{{Dvbscript navigationsbox}}
In diesem Artikel wird näher darauf eingegangen, wie das Script aufgebaut ist und warum es so funktioniert, wie es funktioniert.
+
{{blau|
 +
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.}}
  
Dazu habe ich einen Ausdruck der Version 0.5.5 gemacht und dabei festgestellt, daß es ganz schön umfangreich geworden
 
ist, das was ich da programmiert habe. Es ist also an Zeit, zu Papier (bzw. auf den Bildschirm) zu bringen, was im Script im Einzelnen vor sich geht.
 
  
Dafür gibt es zwei Gründe. Zum einen soll der interessierte Nutzer in die Lage versetzt werden, das Script für sich selber zu erweitern bzw. zu ändern. Und
+
=Vorbereitungen=
zum anderen möchte ich selbst nachschauen können, warum ich Schritt x so programmiert habe und nicht anders (Purer Eigennutz also).
 
  
Greifen wir es also an und schauen uns zusammen den Aufbau des Scriptes an:
+
==<font color="maroon"> Voreinstellungen </font>==
  
==<font color="green"> Beschreibung </font>==
+
hauptverzeichnis=~/dvb_wiki_script
 +
ini_verz=~/.dvb_wiki_script
 +
 +
aufnahme=~/DVB/Aufnahme
 +
druckschablonen=~/DVB/Druckschablonen
 +
videoclips=~/DVB/Videoclips
 +
 +
speed=8
 +
dvdgroesse=4600000000
 +
 +
export VIDEO_FORMAT=PAL
 +
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.
 +
*''export'': Über die Umgebungsvariable VIDEO_FORMAT wird das Videoformat auf PAL festgelegt
  
In diesem Abschnitt stehen ein paar allgemeine Daten über das Script.
+
==<font color="maroon"> Verzeichnisstruktur erstellen </font>==
  
==<font color="green"> Evt. vom Benutzer anzupassen </font>==
+
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
  
Folgende Variablen können, wenn es sein muß, an die eigenen Gegebenheiten anpepasst werden
+
==<font color="maroon"> Erkennung der Helferprogramme </font>==
 +
Mit dieser Routine wird nachgesehen, ob die notwendigen Helferprogramme installiert sind. Und das funktioniert so:
  
*'''$basisverzeichnis''': Diese Variable enthält den Pfad zum sogenannten Basiverzeichnis. In diesem Verzeichnis werden vom Script weitere Arbeitsverzeichnisse angelegt.
+
===Namen der notwendigen Helferprogramme===
 +
hilfsprogramm=( mplex dvdauthor ProjectX.jar normalize ffmpeg growisofs xine requant_lxdvdrip )
 +
Die benötigten Helferprogramme werden als Array in der Variablen ''$hilfsprogramm'' abgelegt.
  
Um eine wilde Jongliererei mit Rechten zu umgehen, muß das Basisverzeichis im Heimatverzeichnis des Benutzers liegen. Existiert der Default-Pfad bereits
+
===Suchschleife===
und/oder wird er von anderen Anwendungen benutzt, muß in die Variable ein anderer Pfadname eingetragen werden.
+
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
  
Aber, wie gesagt, im Heimatverzeichnis bleiben!
+
====<font color="gray"> Ini-Datei anlegen </font>====
 +
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)
  
*'''$maxgroesse''': Diese Variable enthält die Anzahl der Bytes, die maximal auf eine DVD passen. Ist der Film größer, wird requantisiert.
+
====<font color="gray"> Pfad lesen </font>====
 +
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.
  
*'''$brenngeschwindigkeit''': In dieser Variablen steht die maximale Geschwindigkeit, mit der die DVD vom growisofs gebrannt wird.
+
====<font color="gray"> Helferprogramm vorhanden? </font>====
 +
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:
  
*'''$suchpfade''': In den hier enthaltenen Pfaden wird während der Installationsroutine nach den Helferprogrammen gesucht.
+
====<font color="gray"> Programmsuche </font>====
 +
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.
  
==<font color="green"> Fehlermeldungen abschalten </font>==
+
====<font color="gray"> Wieviele Versionen des Helferprogramms gibt es? </font>====
 +
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.
  
*'''exec 2>/dev/null''': Damit werden Meldungen auf dem Standard-Fehlerkanal ins Nirwana geschickt (Für Inbetriebnahme und Fehlersuche evt. auskommentieren).
+
====<font color="gray"> Was wird damit gemacht? </font>====
 +
case "$pfadzahl" in
 +
In Abhängigkeit von der Anzahl der gefundenen Pfade passiert folgendes:
  
Das Script ist so programmiert, daß Betriebs- und Fortschrittsmeldungen der einzelnen Funktionen in einem Konsolenfenster auf dem Bildschirm erscheinen (echo "...").
+
*''0)'': Das Programm wurde nicht gefunden. Nach einem Hinweis wird das Script beendet . Das fehlende Helferprogramm muß installiert werden..
Die Fehlermeldungen wurden mit obigem Befehl bewußt ausgeklammert, da die Ausgaben im Betrieb sonst schnell unübersichtlich 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.
  
Es gibt einige Programme, die auch Betriebsmeldungen über den Standard-Fehlerkanal senden. Um diese Meldungen trotzdem auf dem Bildschirm zu sehen, wurde für
+
==<font color="maroon"> Zuweisung der Helferprogramme zu Variablen </font>==
diese Programme der Fehlerkanal auf die Standardausgabe umgeleitet. Das erfolgt durch Anhängen von '''2>&1''' ans Ende des jeweiligen Programmaufrufs.
+
# 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.
  
==<font color="green"> Installationsroutine </font>==
+
==<font color="maroon"> Initialisierungsdatei für ProjectX erzeugen</font>==
 +
Die ''X.ini'' enthält folgende Einstellungen (ProjectX muß in der [[Projectx|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=$aufnahme'': Damit kommen die Screenshots dahin, wohin sie sollen
  
===<font color="olive"> Programmnamen </font>===
+
*''CollectionPanel.Preview.SliderWidth=0'': Der Vorschau-Slider bekommt dieselbe Breite wie das Vorschaufenster (gibt es erst ab Version b28)
  
Dies sind die Namen der Helferprogramme, die in einer indizierten Variablen abgelegt werden.
+
*''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
  
===<font color="olive"> Anlegen der notwendigen Verzeichnisse </font>===
+
*''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
  
Das Basisverzeichnis wird angelegt. Und im Basiverzeichnis werden folgende Arbeitsordner angelegt:
+
Die ''X.ini'' wird im Hauptverzeichnis angelegt, von wo sie bei Bedarf von ProjectX geladen wird.<br>
*'''dvd_aufnahme''': Hier wird zuerst nach den zu bearbeitenden Filmen gesucht.
+
{{blau|
*'''dvd_tmp''': Hier legen die Helferprogramme Zwischenergebnisse ab ab und suchen nach den Ergebnissen anderen Helferprogramme
+
'''TIP'''<br>
*'''dvd_struktur''': In diesem Ordner wird die fertige DVD-Struktur zwischengespeichert.
+
Werden im PJX-Fenster irgendwelche Einstellungen verändert, so werden diese Änderungen nicht in die ''X.ini'' übernommen. Das wurde absichtlich
*'''dvd-sicherung''': Hierhin werden fertige Arbeitsergebnisse gesichert, wenn das vom User so gewünscht wird.
+
so programmiert, damit man immer einen definierten Ausgangszustand hat.<br>
*'''default''': Hier stehen die Pfadnamen der Helferprogramme und die Initialisierungsdateien für ProjectX.
+
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
*'''screenshot''': Mit mplayer erstellte Screenshots der Filme / Clips, die ich dann zum Bedrucken der DVD verwende.
+
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.}}
  
===<font color="olive"> Programmerkennung </font>===
+
==<font color="maroon"> Playlist erzeugen </font>==
  
In dieser Routine wird nachgesehen, ob die notwendigen Helferprogramme installiert sind. Und das funktioniert so:
 
  
====Hauptschleife====
+
find $videoclips/* > $hauptverzeichnis/playlist
for ((i=0 ; i<9 ; i++))
+
*''find $videoclips/*'': Die im Clipordner gespeicherten Videoclips werden gesucht.
Diese Schleife wird neunmal durchlaufen, so oft also, wie Helferprogramme vorhanden sind.
+
*''$hauptverzeichnis/playlist'': Ihre Pfade werden in dieser Textdatei gespeichert.
 +
Damit ist eine Playlist erzeugt worden, die zum Beispiel von mplaxer oder von xine ausgewertet werden kann.
  
Alles folgende spielt sich in der Schleife ab.
+
Etwas mehr dazu steht in dem Wiki-Artikel [[playlist]]
  
====Default-Pfade lesen====
+
==<font color="maroon"> Löschen der temporären Verzeichnisse </font>==
  pfad[i]=`cat $basisverzeichnis/default/pfad[$i].txt`
+
  rm -r -- $hauptverzeichnis/tmp1/* 2>/dev/null
*'''$basisverzeichnis/default/pfad[$i].txt''': Der Inhalt dieser Datei (das ist der Pfad, wo das zugehöige Programm gefunden werden kann)
+
*''rm -r'': Lösche rekursiv
*'''cat''': wird gesendet (über die Standartausgabe)
+
*''$hauptverzeichnis/tmp1/*'': alle Dateien und Verzeichnisse im Ordner $hauptverzeichnis/tmp1
*''' pfad[i]=`...`''': an die Variable ${pfad[i]}
+
{{blau|
 +
'''TIP'''<br>
 +
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''.
  
Das i steht immer für die Nummer des Schleifendurchlaufs und damit dafür, welches Programm gerade gesucht wird.
+
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:<br>
 +
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!}}
  
====Helferprogramm vorhanden?====
 
if [ ! -e ${pfad[i]}/${name[i]} ]
 
Wenn das Programm nicht existiert,dann
 
  
====Programmsuche====
+
=Die Funktionen=
gefundene_pfade=`find ${suchpfade} -type f -name ${name[i]} -printf "%h "`
 
*'''find ${suchpfade}''': In den Suchpfaden suchen
 
*'''-type f''': nach einer normalen Datei
 
*'''-name ${name[i]}''': mit dem Namen, der in der Variablen ${name[i]} steht.
 
*'''-printf "%h "''': Von den gefundenen Dateien werden die Verzeichnisnamen ausgegeben
 
*''' gefundene_pfade=''': und in diese Variable geschrieben
 
  
====Wieviele Versionen des Helferprogramms gefunden?====
+
==<font color="maroon"> Abbruch </font>==
pfadanzahl=`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).
 
*'''pfadanzahl=''': diese Anzahl wird in die Variable $pfadanzahl geschrieben.
 
  
====Was wird damit gemacht?====
+
===benutzerabbruch ()===
  case "$pfadanzahl" in
+
  echo "Abbruch durch den Benutzer"
In Abhängigkeit der Anzahl der gefundenen Pfade passier folgendes:
+
Diese Meldung wird über die Konsole ausgegeben
 +
programmende
 +
Dann wird die Funktion ''programmende ()'' aufgerufen.
  
*'''0)''': Anzahl 0, das Programm wurde nicht gefunden.
+
===funktionsabbruch ()===
Nach einem Hinweis wird das Script beendet . Das Hfehlende Helferprogramm muß installiert werden..
+
echo "$1"
*'''1)''': Anzahl 1, das Programm existiert genau einmal.
+
Der in ''$1'' gespeicherte Text erscheint im Konsolenfenster.
Der dazugehörige Pfad wird in das Default-Verzeichnis geschrieben.
+
programmende
*'''*)''': Das Programm existiert mehr als einmal.
+
Danach wird die Funktion ''programmende ()'' aufgerufen.<br>
Es wird nachgefragt (kdialog --combobox), welcher der Pfade verwendet werden soll. Dieser Pfad wird dann ins Default-Verzeichnis geschrieben.
+
{{blau|
 +
'''TIP'''<br>
 +
Beim Aufruf einer Funktion können dieser Argumente übergeben werden. Das erste Argument kann innerhalb der Funktion dann über die Variable ''$1'' aufgerufen werden.<br>
 +
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.}}
  
Nachdem diese Routine neunmal erfolgreich durchlaufen ist, kann mit der eigentlichen Videobearbeitung begonnen werden.
+
===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.
  
==<font color="green"> Variablenzuweisungen </font>==
+
==<font color="maroon"> Aufgabenmenues </font>==
Diese Zuweisungen haben den Sinn, das Script besser lesbar zu machen. Im Script selbst wird dann ausschließlich mit diesen Variablen gearbeitet bzw. mit
 
in Variablen gespeicherten Pfaden. Durch diese Strategie kann das Script einfach an neue Gegebenheiten anpepasst werden. Es muß nicht lange im Code gesucht werden,
 
an welchen Stellen was geändert werden muß. Es braucht nur der Inhalt der entsprechenden Variablen ausgetauscht werden.
 
  
==<font color="green"> Konfiguration PJX </font>==
+
=== hauptmenue () ===
 +
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 \
 +
4 "Abspielen" off \
 +
8 "DVD bedrucken" off`
 +
Der per Default aktivierte Eintrag der Liste wird durch das ''on'' festgelegt.
  
Hier werden die Initialisierungsdateien festgelegt, in denen Einstellungen stehen, mit denen ProjectX startet:
+
if [ $? != 0 ]
 
+
then
===X.ini für Filmbearbeitung===
+
benutzerabbruch
 
+
fi
Die X.ini.film enthält folgende Einstellungen:
+
Wenn im Auswahlfenster auf Abbrechen gedrückt wird, dann wird das Script beendet.
 
 
*'''Application.Agreement=1''': Ja zur Lizenz
 
*'''Application.Language=de''': PJX startet auf deutsch<br>
 
 
 
*'''WindowPosition.Main.Heigh/Width''': Größe des PJX-Fensters
 
*'''WindowPosition.Main.X/Y''': Position des Fensters (hier rechts oben)<br>
 
 
 
*'''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
 
 
 
===X.ini für Videoclips===
 
 
 
Die X.ini.clip enthält zusäthlich:
 
 
 
*'''AudioPanel.decodeMPGAudio=1''': Die mpeg-audio-Dateien werden zu .wav decodiert (Für's spätere Normalisieren des Tons notwendig)
 
 
 
Diese beiden X.ini's werden im Default-Verzeichnis abgelegt, von wo sie bei Bedarf geladen werden.
 
 
 
Werden im PJX-Fenster irgendwelche Einstellungen verändert, so werden diese Änderungen nicht in die jeweilige X.ini übernommen. Das wurde absichtlich
 
so programmiert, damit man immer einen definierten Ausgangszustand hat.<br>
 
Wird hier eine Speicherung gewünscht, kann dies durch einen zusätzlichen Eintrag in die X.ini's 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.
 
 
 
==<font color="green"> Funktionen </font>==
 
 
 
Diese Funktionen werden vom Hauptprogrmm nach Bedarf aufgerufen und bilden das eigentliche Gerüst des Scriptes. Wird von einer Funktion erwartet, daß sie einen
 
Wert an das Hauptprogramm übergeben soll, dann wird das durch den Befehl "echo Variable" am Ende der Funktion realisiert.
 
 
 
===<font color="olive"> del_ordner () </font>===
 
  
*'''rm''': Die Inhalte des Ordners $tmp_pfad werden gelöscht. Ebenso die Inhalte der im dvd_strukturpfad enthaltenen Ordner AUDIO_TS und VIDEO_TS.
+
{{blau|
*'''rmdir''': Die Ordner AUDIO_TS und VIDEO_TS selbst werden gelöscht
+
'''TIP'''<br>
 +
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.}}
  
Damit ist ein definierter Ausgangszustand hergestellt.
+
=== untermenues ===
 +
Diese Funktionen sind genauso programmiert wie die Funktion ''hauptmenue ()''. Der Unterschied ist, daß die Kennzahlen in der Variablen ''was_tun'' gespeichert werden.
  
===<font color="olive"> fehler () </font>===
+
==<font color="maroon"> Auswahl Quelldateien </font>==
if [ ! -e ${tmp_pfad}/film.mpg ]
 
Wenn keine Datei film.mpg im Ordner ${tmp_pfad} existiert, wurde auch nichts multiplext. Es muß also irgendwo ein Fehler passiert sein.
 
  
nach einem Hinweis auf diesen Fehler (mit kdialog) wird das Script beendet.
+
=== 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.
  
===<font color="olive"> aktionenauswahl </font>()===
+
  quelldatei=`kdialog --caption "Filmauswahl" --geometry 600x500-0+0 --getopenfilename ${aufnahme_pfad}`
  was_tun=`kdialog --caption "Videobearbeitung" --geometry 500x300-0+0 --radiolist "Was soll also getan werden?"
+
*''kdialog'': Das KDE-Dialog-Programm
*'''kdialog''': Das KDE-Dialog-Programm
+
*''--caption "Filmauswahl"'': öffnet ein Fenster, das den Namen "Filmauswahl" trägt
*'''--caption "Videobearbeitung"''': öffnet ein Fenster, das den Namen "Videobearbeitung" trägt
+
*''--geometry 600x500-0+0'': und diese Größe und Position hat
*'''--geometry 500x300-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
*'''--radiolist''' als Liste mit Radio-Buttons
+
*''${aufnahme_pfad}'': Es werden die Dateien in diesem Pfad zur Auswahl angeboten.  
*'''"Was soll also getan werden?"''': Das wird gefragt.
+
*''quelldatei=`..`''': Die ausgewählte Datei wird in die Variable ''$quelldatei'' geschrieben.
*'''was_tun=`...`''': In diese Variable wird die Nummer der Antwort geschrieben.
 
  
Diese Nummer wird dann später vom Hauptprogramm ausgewertet werden.
+
=== 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.
  
===<font color="olive"> filmauswahl () </font>===
+
==<font color="maroon"> Eingangsverarbeitung </font>==
quelldatei=`kdialog --caption "Filmauswahl" --geometry 500x500-0+0 --getopenfilename ${aufnahme_pfad}`
 
*'''kdialog''': Das KDE-Dialog-Programm
 
*'''--caption "Filmauswahl"''': öffnet ein Fenster, das den Namen "Filmauswahl" trägt
 
*'''--geometry 500x300-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.
 
if [ $? != 0 ]
 
then
 
exit
 
Wenn im Dialogfenster auf den Button Abbrechen gedrückt wurde, wird das Script beendet.
 
  
===<font color="olive"> verzeichnisauswahl() </font>===
+
=== pjx_demux_gui () ===
  verzeichnis=`kdialog --caption "Verzeichnisauswahl" --geometry 500x500-0+0 --getexistingdirectory ${sicherungs_pfad}`
+
  java -jar $pjx -demux -gui -ini $hauptverzeichnis/X.ini -out $hauptverzeichnis/tmp1 -name film "$quelldatei"
*'''kdialog''': Das KDE-Dialog-Programm
+
*''java -jar'': Es wird ein Java-Programm gestartet
*'''--caption "Verzeichnisauswahl"''': öffnet ein Fenster, das den Namen "Verzeichnisauswahl" trägt
+
*''${pjx}'': und zwar das Programm ProjectX (z.B.: ~/ProjectX/ProjectX.jar)
*'''--geometry 500x500-0+0''': und diese Größe und Position hat
+
*''-demux'': Der mpeg-Stream wird demultiplext
*'''--getexistingdirectory''': Es wird ein KDE-Fenster geöffnet, in dem aus einer Liste von Verzeichnissen ausgewählt werden kann
+
*''-gui'': PJX startet mit einer graphischen Oberfläche
*'''${sicherungs_pfad}''': Es werden die Verzeichnisse in diesem Pfad zur Auswahl angeboten.
+
*''-ini $hauptverzeichnis/X.ini'': PJX verwendet diese Initialisierungsdatei
*'''verzeichnis=`...`''': Die ausgewählte Datei wird in die Variable $verzeichnis geschrieben.
+
*''-out $hauptverzeichnis/tmp1'': Hierhin wird das Bearbeitungsergebnis geschrieben
  if [ $? != 0 ]
+
*''-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
 
  then
  exit
+
kdialog --error "Das Bearbeitungsergebnis wird zu groß für eine DVD"
Wenn im Dialogfenster auf den Button Abbrechen gedrückt wurde, wird das Script beendet.
+
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.
  
===<font color="olive"> pjx_demux_gui () </font>===
+
=== pjx_ts_gui () ===
  java -jar ${pjx} -demux -gui -ini ${default_pfad}/X.ini.film -out ${tmp_pfad} -name film "$quelldatei" 1>/dev/null
+
  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
+
*''java -jar'': Es wird ein Java-Programm gestartet
*'''${pjx}''': und zwar das Programm ProjectX (z.B.: ~/ProjectX/ProjectX.jar)
+
*''${pjx}'': und zwar das Programm ProjectX (z.B.: ~/ProjectX/ProjectX.jar)
*'''-demux''': Der mpeg-Stream wird demultiplext
+
*''-tots'': Der Film wird zum TS-File gewandelt
*'''-gui''': PJX startet mit graphischer oberfläche (notwendig nur, wenn mit PJX geschnitten werden soll)
+
*''-gui'': PJX startet mit einer graphischen Oberfläche
*'''-ini ${default_pfad]/X.ini.film''': mit dieser Initialisierungsdatei wird PJX gestartet.
+
*''-split 4300'': Bei 4300 Mbyte wird die Aufnahme gesplittet (mehr passt nicht auf eine DVD drauf)
*'''-out $tmp_pfad''': Hierhin wird das Bearbeitungsergebnis geschrieben
+
*''-ini $hauptverzeichnis/X.ini'': PJX verwendet diese Initialisierungsdatei
*'''-name film''': Die Ausgabedatei erhält den Basisnamen "film"
+
*''-out $hauptverzeichnis/tmp1'': Hierhin wird das Bearbeitungsergebnis geschrieben
*'''$quelldatei''':Dieser Stream wird verarbeitet
+
*''-name film'': Die Ausgabedatei erhält den Basisnamen "film"
*'''1>/dev/null''': Alles, was ich an Ausgeben auf dem Bildschirm nicht sehen will, wird ins Leere geschickt.
+
*''$quelldatei'':Dieser Stream wird verarbeitet
  
===<font color="olive"> pjx_ts_gui () </font>===
+
=== mpeg1_input () ===
  java -jar ${pjx} -tots -gui -split 4300 -ini ${default_pfad}/X.ini.film -out ${tmp_pfad} -name film "$quelldatei" 1>/dev/null
+
  $ffmpeg -i "$quelldatei" $hauptverzeichnis/tmp1/film.mp2 -vcodec copy $hauptverzeichnis/tmp1/film.m1v
*'''java -jar''': Es wird ein Java-Programm gestartet
+
*''${ffmpeg}'': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg),
*'''${pjx}''': und zwar das Programm ProjectX (z.B.: ~/ProjectX/ProjectX.jar)
+
*''-i ${quelldatei}'': um diesen Video-Clip zu demultiplexen
*'''-tots''': Der Film wird zum TS-File gewandelt
 
*'''-gui''': PJX startet mit graphischer oberfläche (notwendig nur, wenn mit PJX geschnitten werden soll)
 
*'''-split 4300''': Bei 4300 Mbyte wird die Aufnahme gesplittet (mehr passt nicht auf eine DVD drauf)
 
*'''-ini ${default_pfad]/X.ini.film''': mit dieser Initialisierungsdatei wird PJX gestartet.
 
*'''-out $tmp_pfad''': Hierhin wird das Bearbeitungsergebnis geschrieben
 
*'''-name film''': Die Ausgabedatei erhält den Basisnamen "film"
 
*'''$quelldatei''':Dieser Stream wird verarbeitet
 
*'''1>/dev/null''': Alles, was ich an Ausgeben auf dem Bildschirm nicht sehen will, wird ins Leere geschickt.
 
  
===<font color="olive"> pjx_clip () </font>===
+
==<font color="maroon"> Bearbeitung </font>==
java -jar ${pjx} -demux -gui  -ini ${default_pfad}/X.ini.clip -out ${tmp_pfad} -name film "$quelldatei" 1>/dev/null
 
*'''-ini ${default_pfad]/X.ini.clip''': mit dieser Initialisierungsdatei wird PJX gestartet. In ihr festgelegt wird, daß das mpg-audio zu einer wav-Datei decodiert wird.
 
Alle anderen Optionen wie bei "pjx_demux_gui ()"
 
  
===<font color="olive"> mpeg1_input () </font>===
+
=== requantisieren () ===
${ffmpeg} -i "${quelldatei}" ${tmp_pfad}/film.mp2.wav -vcodec copy ${tmp_pfad}/film.m1v
 
*'''${ffmpeg}''': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg),
 
*'''-i ${quelldatei}''': um diesen Video-Clip zu verarbeiten
 
*'''${tmp_pfad}/film.mp2.wav''': Der Ton des Clips wird decodiert zu einem wav-file.
 
*'''-vcodec copy''': Das Videofile wird nicht verändert, sondern nur demultiplext
 
*'''${tmp_pfad}/film.m1v''': und ist dann hier zu finden
 
 
 
===<font color="olive"> requantisieren () </font>===
 
  
 +
{{blau|
 
Jetzt gibt es, oh Schreck, etwas Mathematik. Mathe ist nicht nur etwas, mit dem viele Normal-Sterbliche, egal welchen Alters, auf Kriegsfuß stehen. Mathe ist auch
 
Jetzt gibt es, oh Schreck, etwas Mathematik. Mathe ist nicht nur etwas, mit dem viele Normal-Sterbliche, egal welchen Alters, auf Kriegsfuß stehen. Mathe ist auch
 
etwas, mit dem die Bash nicht so ohne weiteres umgehen kann, wäre da nicht ein kleines eingebautes Tool mit dem Namen "bc". Mit diesem Tool hat die Bash einen
 
etwas, mit dem die Bash nicht so ohne weiteres umgehen kann, wäre da nicht ein kleines eingebautes Tool mit dem Namen "bc". Mit diesem Tool hat die Bash einen
Zeile 247: Zeile 310:
 
Es macht wenig Sinn, ein Audiofile verkleinern zu wollen. Ein Videofile mit seinen etlichen GByte Größe bietet hier mehr Aussicht auf Erfolg.
 
Es macht wenig Sinn, ein Audiofile verkleinern zu wollen. Ein Videofile mit seinen etlichen GByte Größe bietet hier mehr Aussicht auf Erfolg.
  
Die Formel, nach der wir den Requantisierungsfaktor berechnen, lautet so:
+
Die Formel, nach der wir den Requantisierungsfaktor berechnen, lautet so:}}
 
  Requantifizierungsfaktor = ("Größe des Videofiles" / ("Was auf die DVD maximal passt" - "Summe aller Audiofiles"))*1,04
 
  Requantifizierungsfaktor = ("Größe des Videofiles" / ("Was auf die DVD maximal passt" - "Summe aller Audiofiles"))*1,04
 +
{{blau|
 
Wieso diese Formel gerade so lautet, darf der geneigte Leser selber zu ergründen versuchen. Eine kleine Denksportaufgabe ist mit Sicherheit nicht die
 
Wieso diese Formel gerade so lautet, darf der geneigte Leser selber zu ergründen versuchen. Eine kleine Denksportaufgabe ist mit Sicherheit nicht die
 
Schlechteste aller Freizeitbeschäftigungen. Ich verrate nur soviel, daß der Faktor 1,04 dafür da ist, die Verwaltung des Dateisystems auf der DVD zu
 
Schlechteste aller Freizeitbeschäftigungen. Ich verrate nur soviel, daß der Faktor 1,04 dafür da ist, die Verwaltung des Dateisystems auf der DVD zu
berücksichtigen (Die einzelnen Ordner brauchen ja schließlich auch Platz).
+
berücksichtigen (Die einzelnen Ordner brauchen ja schließlich auch Platz).}}
  
 
Schauen wir uns also eine Umsetzung dieser Formel in der Bash an:
 
Schauen wir uns also eine Umsetzung dieser Formel in der Bash an:
  
====videogroesse====
+
====<font color="gray"> videogroesse </font>====
  videogroesse=`du -bc ${tmp_pfad}/*.m2v | cut -f1 | tail -n 1`
+
  videogroesse=`du -bc $hauptverzeichnis/tmp1/*.m2v | cut -f1 | tail -n 1`
*'''du''': Bashprogramm, welches den Platzverbrauch von Dateien schätzt
+
*''du'': Bashprogramm, welches den Platzverbrauch von Dateien schätzt
*'''-b''': Ausgabe der Größe in Bytes
+
*''-b'': Ausgabe der Größe in Bytes
*'''-c''': Erzeugen einer Gesamtsumme (-b und -c sind zusammen gefasst nach -bc. dieses bc ist allerdings nicht identisch mit dem oben angepriesenen gleichnamigen Tachenrechner. Der kommt nachher noch)
+
*''-c'': Erzeugen einer Gesamtsumme (-b und -c sind zusammen gefasst nach -bc. dieses bc ist allerdings nicht identisch mit dem oben angepriesenen gleichnamigen Tachenrechner. Der kommt nachher noch)
*'''${tmp_pfad}/*.m2v''': Alle Dateien im tmp_pfad, deren Name auf .m2v endet, gehen in die Größenermittlung ein.
+
*''$hauptverzeichnis/tmp1/*.m2v'': Alle Dateien im tmp1, deren Name auf .m2v endet, 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)
+
*''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
+
*''cut -f1'': Von dieser letzten Zeile wird nur das erste Feld ausgegeben, also die reine Zahl
*'''videogroesse=`....`''': Diese Groesse wird in die Variable $videogroesse geschrieben
+
*''videogroesse=`....`'': Diese Groesse wird in die Variable $videogroesse geschrieben
  
====audiosumme====
+
====<font color="gray"> audiosumme </font>====
  audio_summe=`du -bc ${tmp_pfad}/*.ac3 ${tmp_pfad}/*.mp2 | cut -f1 | tail -n 1`
+
  audio_summe=`du -bc $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2 | cut -f1 | tail -n 1`
*'''du''': Bashprogramm, welches den Platzverbrauch von Dateien schätzt
+
*''du'': Bashprogramm, welches den Platzverbrauch von Dateien schätzt
*'''-b''': Ausgabe der Größe in Bytes
+
*''-b'': Ausgabe der Größe in Bytes
*'''-c''': Erzeugen einer Gesamtsumme (-b und -c sind zusammen gefasst nach -bc. dieses bc ist allerdings nicht identisch mit dem oben angepriesenen gleichnamigen Tachenrechner. Der kommt nachher noch)
+
*''-c'': Erzeugen einer Gesamtsumme (-b und -c sind zusammen gefasst nach -bc. dieses bc ist allerdings nicht identisch mit dem oben angepriesenen gleichnamigen Tachenrechner. Der kommt nachher noch)
*'''${tmp_pfad}/*.ac3 ${tmp_pfad}/*.mp2''': Alle Dateien im tmp_pfad, deren Name auf .ac3 oder .mp2 endet, gehen in die Größenermittlung ein.
+
*''$hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2'': Alle Dateien im tmp1, deren Name auf .ac3 oder .mp2 endet, 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)
+
*''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
+
*''cut -f1'': Von dieser letzten Zeile wird nur das erste Feld ausgegeben, also die reine Zahl
*'''audio_summe=`....`''': Diese Groesse wird in die Variable $audio_summe geschrieben
+
*''audio_summe=`....`'': Diese Groesse wird in die Variable $audio_summe geschrieben
  
====audio_video_summe====
+
====<font color="gray"> requantisierungsfaktor </font>====
  audio_video_summe=`du -bc ${tmp_pfad}/*.ac3 ${tmp_pfad}/*.mp2 ${tmp_pfad}/*.m2v | cut -f1 | tail -n 1`
+
requantisierungsfaktor=`echo "scale=8 ; ${videogroesse}/$((dvdgroesse-audio_summe))*1.04" | bc`
 +
*''bc'': Nun ist er endlich da, unser Taschenrechner
 +
*''${videogroesse}/$((dvdgroesse-audio_summe))*1.04'': Diese Formel wird ausgerechnet
 +
*''scale=8'': auf 8 Nachkommastellen genau
 +
*''echo'': und der Nachwelt zu Verfügung gestellt,
 +
*''requantisierungsfaktor=`....`'': indem es in diese Variable geschrieben wird
 +
 
 +
====<font color="gray"> Die Requantisierung </font>====
 +
cat $hauptverzeichnis/tmp1/film.m2v | requant_lxdvdrip $requantisierungsfaktor $videogroesse > $hauptverzeichnis/tmp1/film.requant
 +
*''cat'': Schreibe
 +
*''$hauptverzeichnis/tmp1/film.m2v'': diese Datei
 +
*''|'': mit Hilfe eine pipe
 +
*''requant_lxdvdrip'': in den Eingang von dem Requantisierungs-Tool
 +
*''$requantisierungsfaktor'': Es wird mit diesem Faktor requantisiert
 +
*''$videogroesse'': Soviel Bytes werden requantisiert
 +
*''>'': Das Ergebnis wird geschrieben
 +
*''$hauptverzeichnis/tmp1/film.requant'':in diese Datei
 +
mv $hauptverzeichnis/tmp1/film.requant $hauptverzeichnis/tmp1/film.m2v
 +
Die Datei film.requant wird zu film.m2v umbenannt. Diese Namensänderung ist notwendig, da die Funktion "multiplex ()" das Videofile unter dem Namen film.m2v
 +
erwartet.
 +
 
 +
====<font color="gray"> audio_video_summe </font>====
 +
  audio_video_summe=`du -bc $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2 $hauptverzeichnis/tmp1/*.m2v | cut -f1 | tail -n 1`
 
Das Prinzip sollte nun bekannt sein. Das Ergebnis ist die Groesse der Summe aller Video- und Audiofiles und findet sich in der Variablen $audio_video_summe wieder
 
Das Prinzip sollte nun bekannt sein. Das Ergebnis ist die Groesse der Summe aller Video- und Audiofiles und findet sich in der Variablen $audio_video_summe wieder
  
====requantisierungsfaktor====
+
====<font color="gray"> Muß requantisiert werden? </font>====
requantisierungsfaktor=`echo "scale=8 ; ${videogroesse}/$((maxgroesse-audio_summe))*1.04" | bc`
 
*'''bc''': Nun ist er endlich da, unser Taschenrechner
 
*'''${videogroesse}/$((maxgroesse-audio_summe))*1.04''': Diese Formel wird ausgerechnet
 
*'''scale=8''': auf 8 Nachkommastellen genau
 
*'''echo''': und der Nachwelt zu Verfügung gestellt,
 
*'''requantisierungsfaktor=`....`''': indem es in diese Variable geschrieben wird
 
  
====Muß requantisiert werden?====
+
  if [ $audio_video_summe -ge $dvdgroesse ] ; then
  if [ $audio_video_summe -ge $maxgroesse ] ; then
 
 
Wenn die Summe der Audio- und Videofiles größer ist als das, was auf die DVD drauf passt, dann wird die requantisiert.
 
Wenn die Summe der Audio- und Videofiles größer ist als das, was auf die DVD drauf passt, dann wird die requantisiert.
  
====Die Requantisierung====
+
=== normalisieren () ===
${tcrequant} -d2 -i ${tmp_pfad}/film.m2v -o ${tmp_pfad}/film.requant -f ${requantisierungsfaktor}
 
*'''${tcrequant}''': Aufruf von tcrequant (z.B.: /usr/bin/tcrequant)
 
*'''-d2''': Den Bearbeitungsfortschritt anzeigen
 
*'''-i ${tmp_pfad}/film.m2v''': Dieses Videofile wird requantisiert
 
*'''-o ${tmp_pfad}/film.requant''': Das ist das Ergebnis der Requantisierung
 
*'''-f ${requantisierungsfaktor}''':Mit diesem Faktor wird requantisiert
 
mv ${tmp_pfad}/film.requant ${tmp_pfad}/film.m2v
 
Die Datei film.requant wird zu film.m2v umbenannt. Diese Namensänderung ist notwendig, da die Funktion "multiplex ()" das Videofile unter dem Namen film.m2v
 
erwartet.
 
 
 
===<font color="olive"> normalisieren () </font>===
 
  
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
+
{{blau|
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
+
'''EXKURS'''<br>
 +
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.
 
beschweren würden. Der Regler ist vielmehr am Rechtanschlag angelangt und die Anlage liefert die maximal mögliche Lautstärke.
  
Zeile 313: Zeile 382:
  
 
Fernsehsender beanspruchen für sich eine gewisse Individualität. Manchmal kommt es mir so vor, daß diese Individualität dadurch zum Ausdruck gebracht wird,
 
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
+
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.
aufgenommenen Videoclips mit Hilfe einer Wiedergabeliste abgespielt werden. 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
+
''Ein PCM-Signal auf einen definierten Lautstärkepegel zu bringen, ohne die Dynamik selbst zu verändern, wird "normalisieren" genannt.''
mitgezogen. Aber, wie gesagt, ohne Verlust an Dynamik.
 
  
${normalize} -v ${tmp_pfad}/film.mp2.wav
+
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.
*'''${normalize}''': Aufruf des Befehls normalize (z.B.: /usr/bin/normalize)
 
*'''-v''': Bearbeitungsfortschritt anzeigen
 
*'''{tmp_pfad}/film.mp2.wav''': Diese Audio-Datei wird normalisiert und dabei durch das Bearbeitungsergebnis ersetzt
 
  
 
Das Normalisieren funktioniert nur mit PCM-Files. eine komprimierte Datei (mp2) muß erst zu PCM (wav) decodiert werden.
 
Das Normalisieren funktioniert nur mit PCM-Files. eine komprimierte Datei (mp2) muß erst zu PCM (wav) decodiert werden.
Zeile 333: Zeile 394:
 
und regelt entsprechend die Lautstärke beim Abspielen des Files. Die Voraussetzung ist hier sebstverständlich ein Player, der dies Auswertung auch verarbeiten
 
und regelt entsprechend die Lautstärke beim Abspielen des Files. Die Voraussetzung ist hier sebstverständlich ein Player, der dies Auswertung auch verarbeiten
 
kann.
 
kann.
 +
 
Dies nur zur Information, daß es noch eine Welt ausßerhalb von mp2 gibt.
 
Dies nur zur Information, daß es noch eine Welt ausßerhalb von mp2 gibt.
  
Da der Ton von Fersehprogrammen aber im mp2 Verfahren codiert ist (AC3 lassen wir hier einmal außen vor), müssen wir den ober beschriebenen verlustbehafteten
+
Und noch etwas gibt es. Und das nennt sich ac3, zu Deutsch "Dolby digital"}}
Weg mit normalize gehen. Aber keine Angst, die Verluste sind nicht so groß, daß sie stören würden. Der mit einem normal arbeitenden Gehör ausgestattete
 
Mitteleuropäer wird zufrieden sein mit der Qualität des Bearbeitungsergebnisses.
 
  
===<font color="olive"> encode2mp2 () </font>===
+
====<font color="gray"> Ton-Dateien vorbereiten </font>====
Aus einer wav Datei wird ein mp2-file gemacht.
+
  mv $hauptverzeichnis/tmp1/film.mp2 $hauptverzeichnis/tmp2
  ${ffmpeg} -i ${tmp_pfad}/film.mp2.wav -acodec mp2 -ab 192k ${tmp_pfad}/film.mp2
+
rm -- $hauptverzeichnis/tmp1/*.mp2
*'''${ffmpeg}''': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg)
+
Die zu normalisierende Tondatei wird nach ''tmp2'' verschoben. Anschließend werden alle(!) mp2-files in ''tmp1'' gelöscht.
*'''-i ${tmp_pfad}/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)
 
*'''${tmp_pfad}/film.mp2''': Das Ergebnis findet man dann hier
 
  
===<font color="olive"> multiplexen () </font>===
+
====<font color="gray"> mp2 decodieren </font>====
 +
$ffmpeg -i $hauptverzeichnis/tmp2/film.mp2 $hauptverzeichnis/tmp2/film.mp2.wav
 +
Aus mp2 wird mit Hilfe von ffmpeg wav.
 +
 
 +
====<font color="gray"> normalisieren </font>====
 +
$normalize $hauptverzeichnis/tmp2/film.mp2.wav
 +
Das wav-File wird normalisiert. Es überschreibt sich dabei selbst mit dem Ergebnis.
 +
 
 +
====<font color="gray"> encodieren zu mp2 </font>====
 +
$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.
 
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====
+
====<font color="gray"> Vorbereiten der Dateien </font>====
*'''mpeg1_video=''': Es wird eine leere Variabe mpeg1_video erzeugt
+
*''mpeg1_video='': Es wird eine leere Variabe mpeg1_video erzeugt
*'''mpeg1_video=`find ${tmp_pfad} | grep "m1v"`''': In diese Variable werden die Namen der Dateien geschrieben, die sich im tmp_pfad befinden und ein "m1v" im Namen haben.
+
*''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_viedo, mp2_audio und ac3_audio. Ist im tmp_pfad keine Datei vorhanden, die das angegebene Bitmuster enthält, dann bleibt
+
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.
die entsprechende Variable leer.
+
 
 +
====<font color="gray"> Das eigentliche Multiplexen </font>====
 +
$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.
  
====Das eigentliche Multiplexen====
+
  if [ ! -e $hauptverzeichnis/tmp1/film.mpg ]
  ${mplex} -v1 -f8 -o ${tmp_pfad}/film.mpg ${mpeg1_video} ${mpeg2_video} ${mp2_audio} ${ac3_audio}
+
then
*'''${mplex}''': Aufruf von mplex (z.B.: /usr/bin/mplex)
+
funktionsabbruch "Es konnte keine Datei multiplext werden!"
*'''-v1''': Fortschrittsanzeige (beim Befehl mplex leider nicht so sehr fortschrittlich)
+
fi
*'''-f8''': Format zur späteren Erzeugung einen DVD
+
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.
*'''-o ${tmp_pfad}/film.mpg''': Das Ergebnis
 
*'''${mpeg1_video} ${mpeg2_video} ${mp2_audio} ${ac3_audio}''': die Eingangsdateien, die multiplext werden, enthalten in den angegebenen Variablen. Eine leere Variable wird von mplex ignoriert.
 
Anschließend werden mit "rm" die nun nicht mehr benötigten Eingangsdateien gelöscht.
 
  
===<font color="olive"> authoring_ohne_menue () </font>===
+
=== authoring_ohne_menue () ===
 
Hier wird der einfachste Fall einer DVD-Struktur erzeugt (ohne DVD-Menue).
 
Hier wird der einfachste Fall einer DVD-Struktur erzeugt (ohne DVD-Menue).
  ${dvdauthor} -o ${dvdstruktur_pfad} -t ${tmp_pfad}/film.mpg 2>&1
+
  $dvdauthor -o $hauptverzeichnis/dvdstruktur -t $hauptverzeichnis/tmp1/film.mpg
*'''${dvdauthor}''': Programmaufruf von dvdauthor (z.B.: /usr/bin/dvdauthor)
+
*''${dvdauthor}'': Programmaufruf von dvdauthor (z.B.: /usr/bin/dvdauthor)
*'''-o ${dvdstruktur_pfad}''': Das Ergebnis wird hier zu finden sein
+
*''-o $hauptverzeichnis/dvdstruktur'': Das Ergebnis wird hier zu finden sein
*'''-t''': Es wird ein Titel erzeugt (Ordner AUDIO_TS: leer / Ordner VIDEO_TS: Inhalt ifo-files und vob-files)
+
*''-t'': Es wird 1 Titel erzeugt (Ordner AUDIO_TS: leer / Ordner VIDEO_TS: Inhalt ifo-files und vob-files)
*'''${tmp_pfad}/film.mpg''': Diese mpg-Datei wird als Eingangsdatei verwendet
+
*''$hauptverzeichnis/tmp1/film.mpg'': Diese mpg-Datei wird als Eingangsdatei verwendet
  ${dvdauthor} -o ${dvdstruktur_pfad} -T
+
  $dvdauthor -o $hauptverzeichnis/dvdstruktur -T
*'''-o ${dvdstruktur_pfad}''': In diesem Ordner: ${dvdstruktur_pfad}/VIDEO_TS  
+
*''-o $hauptverzeichnis/dvdstruktur'': Im Ordner ''$hauptverzeichnis/dvdstruktur/VIDEO_TS ''
*'''-T''': werden noch folgende Dateien erzeugt: VIDEO_TS.BUP und VIDEO_TS.IFO
+
*''-T'': werden noch folgende Dateien erzeugt: VIDEO_TS.BUP und VIDEO_TS.IFO
  
===<font color="olive"> brennen_video_dvd () </font>===
+
==<font color="maroon"> Brennen </font>==
 +
 
 +
=== brennen_video_dvd () ===
 
Mit dieser Funktion wird die fertige DVD-Struktur auf DVD kopiert. Das Ergebnis ist eine Video-DVD
 
Mit dieser Funktion wird die fertige DVD-Struktur auf DVD kopiert. Das Ergebnis ist eine Video-DVD
  ${growisofs} -speed=${brenngeschwindigkeit} -dvd-compat -Z /dev/dvd -dvd-video ${brenn_pfad} 2>&1
+
  $growisofs -speed=$speed -dvd-compat -Z /dev/dvd -dvd-video $brenn_pfad
*'''${growisofs}''': Programmaufruf von growisofs (z.B. /usr/bin/growisofs)
+
*''${growisofs}'': Programmaufruf von growisofs (z.B. /usr/bin/growisofs)
*'''-speed=${brenngeschwindigkeit}''': maximale Brenngeschwindigkeit
+
*''-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
+
*''-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)
+
*''-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
+
*''-dvd-video'': udf-Filesystem für Video-DVD's
*'''${brenn_pfad}''': Was hier drin steht, wird gebrannt
+
*''$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.
  
===<font color="olive"> brennen_ts () </font>===
+
Nach Beendigung des Brennens beendet sich das Programm.
 +
 
 +
=== brennen_ts () ===
 
Brennen der TS-Files als Daten-DVD
 
Brennen der TS-Files als Daten-DVD
 
  dvdzahl=`find ${brenn_pfad} -type f | wc -l`
 
  dvdzahl=`find ${brenn_pfad} -type f | wc -l`
*'''find ${brenn_pfad}''': Der Pfad mit den zu brennenden Files wird durchsucht
+
*''find ${brenn_pfad}'': Der Pfad mit den zu brennenden Files wird durchsucht
*'''-type f''': nach normalen Dateien
+
*''-type f'': nach normalen Dateien
*'''wc -l''': und es wird gezählt, wieviele Dateien das sind
+
*''wc -l'': und es wird gezählt, wieviele Dateien das sind.
*'''dvdzahl=`....`''': Diese Anzahl wird mit Hilfe der Substitution in die Variable $dvdzahl geschrieben
+
*''dvdzahl=`....`'': Diese Anzahl wird mit Hilfe der Substitution in die Variable ''$dvdzahl'' geschrieben
 
  for((i=1; i<=${dvdzahl}; i++))
 
  for((i=1; i<=${dvdzahl}; i++))
In dieser If-Schleife wird so oft eine neue DVD angefordert, bis alle Dateien gebrannt sind.
+
In dieser for-Schleife passiert nun folgendes:
kdialog --msgbox "Bitte DVD Nr.: $i einlegen"
+
Es erfolgt der schon von ''brennen_dvd () '' bekannte Trockenlauf zur DVD-Erkennung. Ist die angeforderte DVD bereit, wird gebrannt:
Aufforderung , eine neue DVD bzw. die nächste DVD zum Brennen einzulegen
+
  $growisofs -speed=$speed -Z /dev/dvd -allow-limited-size -R -J $brenn_pfad/"film($((i-1)))[remux].ts"
  ${growisofs} -speed=${brenngeschwindigkeit} -Z /dev/dvd -allow-limited-size -R -J ${brenn_pfad}/"film($((i-1)))"* 2>&1
+
*''${growisofs}'': Programmaufruf für growisofs (z.B. /usr/bin/growisofs)
*'''${growisofs}''': Programmaufruf für growisofs (z.B. /usr/bin/growisofs)
+
*''-speed=$speed'': maximale Geschwindigkeit, mit der gebrannt werden darf
*'''-speed=${brenngeschwindigkeit}''': maximale Brenngeschwindigkeit
+
*''-Z /dev/dvd'': Den ersten Satz Daten auf die DVD brennen (,der in unserem Fall auch der einzige ist, nämlich die TS-files)
*'''-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
*'''-allow-limited-size''': Damit lassen sich Dateien bis zu 4,3GB brennen
+
*''-R'': Rock Ridge Erweiterung benutzen
*'''-R''': Rock Ridge Erweiterung benutzen
+
*''-J'': Joliet-Extention benutzen (macht es leichter, die DVD unter Windows abzuspielen)
*'''-J''': Joliet-Extention benutzen (macht es leichter, die DVD unter Windows abzuspielen)
+
*''$brenn_pfad/"film($((i-1)))[remux].ts'': Diese Datei auf DVD brennen
*'''${brenn_pfad}/"film($((i-1)))''': Diese Datei auf DVD brennen
+
Es werden in der for-Schleife solange DVDs angefordert, bis alle Daten gebrannt sind.
  
===<font color="olive"> sichern_struktur () </font>===
+
 
 +
==<font color="maroon"> Sichern </font>==
 +
 
 +
=== sichern_dvd_struktur () ===
 
Diese Funktion sichert die DVD-Struktur
 
Diese Funktion sichert die DVD-Struktur
  sicherungsordner=$(date +%Y%m%d%H%M%S)
+
  sicherungsordner="$(date +%Y%m%d%H%M%S)_dvd"
In diesen Sicherungsordner wird die DVD-Struktur geschrieben. Der Name des Ordner wird aus dem aktuellen Datum und der momentanen Uhrzeit generiert.
+
Die Variable ''$sicherungsordner'' wir mit einem String gefüllt, der sich aus dem aktuellen Datum und der momentanen Uhrzeit zusammensetzt.
  mkdir ${sicherungs_pfad}/${sicherungsordner}
+
  mkdir $hauptverzeichnis/sicherung/$sicherungsordner
Hiermit wird der Sicherungsordner angelegt
+
Der Sicherungsordner wird angelegt
  mv ${dvdstruktur_pfad}/* ${sicherungs_pfad}/${sicherungsordner}
+
  mv $hauptverzeichnis/dvdstruktur/* $hauptverzeichnis/sicherung/$sicherungsordner
mv verschiebt die DVD-Struktur in den 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.
  
===<font color="olive"> sichern_ts () </font>===
+
=== sichern_ts () ===
 
Diese Funktion sichert die TS-files
 
Diese Funktion sichert die TS-files
  sicherungsordner=$(date +%Y%m%d%H%M%S)
+
  sicherungsordner=$(date +%Y%m%d%H%M%S)_ts
In diesen Sicherungsordner wird die DVD-Struktur geschrieben. Der Name des Ordner wird aus dem aktuellen Datum und der momentanen Uhrzeit generiert.
+
Die Variable ''$sicherungsordner'' wir mit einem String gefüllt, der sich aus dem aktuellen Datum und der momentanen Uhrzeit zusammensetzt.
 
  mkdir ${sicherungs_pfad}/${sicherungsordner}
 
  mkdir ${sicherungs_pfad}/${sicherungsordner}
Hiermit wird der Sicherungsordner angelegt
+
Der Sicherungsordner wird angelegt
  mv ${tmp_pfad}/*.ts ${sicherungs_pfad}/${sicherungsordner}
+
  mv $hauptverzeichnis/tmp1/*.ts $hauptverzeichnis/sicherung/$sicherungsordner
mv verschiebt die TS-files in den 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.
  
===<font color="olive"> clip_speichern () </font>===
+
===< sichern_clip () ===
 
Diese Funktion speichert einen Videoclip
 
Diese Funktion speichert einen Videoclip
  clipspeicher=`kdialog --title "$quelldatei" --getsavefilename /Videoclips/Archiv`
+
  clipspeicher=`kdialog --title "$quelldatei" --getsavefilename $videoclips`
*'''kdialog''': Programmaufruf für kdialog (z.B. /usr/bin/kdialog)
+
*''kdialog'': Programmaufruf für kdialog (z.B. /usr/bin/kdialog)
*'''--title "$quelldatei"''': Überschrift für das KDE-Fenster
+
*''--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.
+
*''--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/Archiv''': In dieses Verzeichnis wird bevorzugt gespeichert
+
*''$videoclips'': In dieses Verzeichnis wird bevorzugt gespeichert
*'''clipspeicher=`....`''': Der gewählte Name und Speicherpfad steht dann in dieser Variable zur Verfügung
+
*''clipspeicher=`....`'': Der gewählte Name und Speicherpfad steht dann in dieser Variable zur Verfügung
  mv ${tmp_pfad}/film.mpg ${clipspeicher}
+
  if [ $? != 0 ]
Der Clip wird an den vorhin ausgewählten Ort gespeichert
+
  then
 
+
benutzerabbruch
===<font color="olive"> abspielen () </font>===
+
  fi
  cd ${screenshot_pfad}
+
Damit wird die Abbruchtaste des KDE-Dialogs ausgewertet.
Macht den Screenshot-Pfad zum aktuellen Verzeichnis
+
if [ -e "$clipspeicher" ]
  ${mplayer} -vf screenshot -geometry 100%:0% dvd://1 -dvd-device ${brenn_pfad} 1>/dev/null
+
then
*'''${mplayer}''': Aufruf von mplayer (z.B.: /usr/bin/mplayer)
+
......
*'''-vf screenshot''': Lädt das Viedofilter "screenshot" Damit lassen sich über eine bestimmte Tastenkombination Screenshots des abgespielten Films im aktuellem Verzeichnis ablegen.
+
fi
*'''-geometry 100%:0%''': An dieser Stelle wird das Fenster von mplayer angezeigt
+
Existiert bereits ein Clip mit dem gleichen Namen, dann
*'''dvd://1''': Eine DVD wird abgespielt, wobei sich die abzuspielenden Dateien
+
kdialog --yesno "Dieser Clip ist schon gespeichert. Überschreiben?"
*'''-dvd-device ${brenn_pfad}''': in diesem Pfad befinden
+
wird gefragt ob der Clip überschrieben werden darf.
 
+
if [ $? != 0 ]
==<font color="green"> Hauptprogramm </font>==
+
then
Mit dem Scriptstart startet dieses Hauptprogramm. Von ihm werden alle Funktionen je nach Bedarf aufgerufen.
+
sichern_clip
 
+
fi
*'''del_ordner''': Die Funktion zum Löschen der Arbeitsordner wird aufgerufen.
+
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.
*'''was_tun=`aktionenauswahl`''': Über die Funktion "aktionenauswahl" wird das gewünschte Szenario ausgewählt. Die dazugehörige Nummer wird in die Variable $was_tun geschrieben.
+
mv $hauptverzeichnis/tmp1/film.mpg "$clipspeicher"
*'''case $was_tun in''': Im gerade ausgewählten Szenario werden nun die einzelnen Programmschritte (Funktionen) aufgerufen
+
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.
 
 
==<font color="green"> Szenario 1 </font>==
 
 
 
===<font color="olive"> brenn_pfad=${dvdstruktur_pfad} </font>===
 
Damit kann später das, was im DVD-Strukturpfad steht, gebrannt werden
 
 
 
===<font color="olive"> filmauswahl </font>===
 
*'''Aktion''': Auswahl des zu bearbeitendes Films
 
*'''Input''': Über KDE-Fenster ausgewählte Eingangsdatei
 
*'''Output''': $quelldatei
 
 
 
===<font color="olive"> pjx_demux_gui </font>===
 
*'''Aktion''': Aufruf des Programms ProjectX zum Schneiden und Demultiplexen
 
*'''Input''': $quelldatei
 
*'''Output''': $dvd_tmp/film.m2v und/oder $dvd_tmp/*.mp2 und/oder $dvd_tmp/*.ac3
 
 
 
===<font color="olive"> requantisieren </font>===
 
*'''Aktion''': Requantisieren der Videodatei, wenn es notwendig sein sollte
 
*'''Input''': $dvd_tmp/film.m2v und/oder $dvd_tmp/*.mp2 und/oder $dvd_tmp/*.ac3, $maxgroesse
 
*'''Output''': ${tmp_pfad}/film.m2v
 
 
 
===<font color="olive"> multiplexen </font>===
 
*'''Aktion''': Multiplexen der seperaten Audio- und Videofiles
 
*'''Input''': $dvd_tmp/film.m2v und/oder $dvd_tmp/*.mp2 und/oder $dvd_tmp/*.ac3
 
*'''Output''': ${tmp_pfad}/film.mpg
 
 
 
===<font color="olive"> fehler </font>===
 
*'''Aktion''': Programmabbruch, wenn nicht multiplext werden konnte
 
*'''Input''':${tmp_pfad}/film.mpg
 
*'''Output''': exit
 
 
 
===<font color="olive"> authoring_ohne_menue </font>===
 
*'''Aktion''': Erzeugen der DVD-Struktur
 
*'''Input''':${tmp_pfad}/film.mpg
 
*'''Output''':${dvdstruktur_pfad}
 
 
 
===<font color="olive"> abspielen </font>===
 
*'''Aktion''': Abspielen des Videos zur Kontrolle mit Option auf das Speichern eines Screenshots
 
*'''Input''': ${brenn_pfad}
 
*'''Output''': Bildschirm / ${screenshot_pfad}
 
 
 
===<font color="olive"> brennen_video_dvd </font>===
 
*'''Aktion''': Brennen der Video-DVD
 
*'''Input''': ${brenn_pfad}
 
*'''Output''': DVD
 
 
 
==<font color="green"> Szenario 2 </font>==
 
Identisch mit Szenario 1 bis einschließlich "authoring_ohne_menue". Danach geht's weiter mit
 
 
 
===<font color="olive"> sichern_struktur </font>===
 
*'''Aktion''': Sichern der DVD-Struktur
 
*'''Input''': ${dvdstruktur_pfad}
 
*'''Output''': ${sicherungs_pfad}/${sicherungsordner}
 
 
 
==<font color="green"> Szenario 3 </font>==
 
 
 
===<font color="olive"> brenn_pfad=`verzeichnisauswahl` </font>===
 
*'''Aktion''': In "verzeichnisauswahl" wird der aktuelle Brennpfad festgelegt
 
*'''Input''': Über KDE-Fenster ausgewählter Pfad
 
*'''Output''': $verzeichnis
 
 
 
===<font color="olive"> abspielen </font>===
 
*'''Aktion''': Abspielen des Videos zur Kontrolle mit Option auf das Speichern eines Screenshots
 
*'''Input''': ${brenn_pfad}
 
*'''Output''': Bildschirm / ${screenshot_pfad}
 
 
 
===<font color="olive"> brennen_video_dvd </font>===
 
*'''Aktion''': Brennen der Video-DVD
 
*'''Input''': ${brenn_pfad}
 
*'''Output''': DVD
 
 
 
==<font color="green"> Szenario 4 </font>==
 
 
 
===<font color="olive"> brenn_pfad=${tmp_pfad}` </font>===
 
Damit kann später das, was im tmp_pfad steht, gebrannt werden
 
 
 
===<font color="olive"> filmauswahl </font>===
 
*'''Aktion''': Auswahl des zu bearbeitendes Films
 
*'''Input''': Über KDE-Fenster ausgewählte Eingangsdatei
 
*'''Output''': $quelldatei
 
 
 
===<font color="olive"> pjx_ts_gui </font>===
 
*'''Aktion''': Aufruf des Programms ProjectX zum Schneiden und Wandeln zum TS-Stream
 
*'''Input''': $quelldatei
 
*'''Output''': $dvd_tmp/*.ts
 
 
 
===<font color="olive"> brennen_ts </font>===
 
*'''Aktion''': Brennen der TS-files auf eine oder mehrere DVD's
 
*'''Input''': $dvd_tmp/*.ts
 
*'''Output''': DVD
 
 
 
==<font color="green"> Szenario 5 </font>==
 
 
 
===<font color="olive"> filmauswahl </font>===
 
*'''Aktion''': Auswahl des zu bearbeitendes Films
 
*'''Input''': Über KDE-Fenster ausgewählte Eingangsdatei
 
*'''Output''': $quelldatei
 
 
 
===<font color="olive"> pjx_ts_gui </font>===
 
*'''Aktion''': Aufruf des Programms ProjectX zum Schneiden und Wandeln zum TS-Stream
 
*'''Input''': $quelldatei
 
*'''Output''': $dvd_tmp/*.ts
 
 
 
===<font color="olive"> sichern_ts </font>===
 
*'''Aktion''': Sichern der TS-files
 
*'''Input''': ${tmp_pfad}/*.ts
 
*'''Output''': ${sicherungs_pfad}/${sicherungsordner}
 
 
 
==<font color="green"> Szenario 6 </font>==
 
 
 
===<font color="olive"> brenn_pfad=`verzeichnisauswahl` </font>===
 
*'''Aktion''': In "verzeichnisauswahl" wird der aktuelle Brennpfad festgelegt
 
*'''Input''': Über KDE-Fenster ausgewählter Pfad
 
*'''Output''': $verzeichnis
 
 
 
===<font color="olive"> brennen_ts </font>===
 
*'''Aktion''': Brennen der TS-files auf eine oder mehrere DVD's
 
*'''Input''': $dvd_tmp/*.ts
 
*'''Output''': DVD
 
  
==<font color="green"> Szenario 7 </font>==
+
==<font color="maroon"> Abspielen </font>==
  
===<font color="olive"> filmauswahl </font>===
+
===playlist_abspielen_shuffle ()===
*'''Aktion''': Auswahl des zu bearbeitendes Films
+
nohup $xine -P $hauptverzeichnis/playlist -a 1 -l=shuffle &
*'''Input''': Über KDE-Fenster ausgewählte Eingangsdatei
+
*''$xine:'' Audruf von xine als Videoplayer
*'''Output''': $quelldatei
+
*''-P $hauptverzeichnis/playlist:'' Diese Wiedergabeeliste wird abgespielt
 +
*''-a 1:'' und dabei die Tonspur 1 verwendet (hier AC3)
 +
*''-l=shuffle:'' die Wiedergabeliste wird in zufälliger Reihenfolge abgespielt.
 +
*''&:'' Startet xine als Hintergrundprozess
 +
*''nohup:'' Sorgt dafür, daß die Playlist weiterläuft, auch wenn das aufrufende Script beendet wird
  
===<font color="olive"> pjx_clip </font>===
+
=Hauptprogramm=
*'''Aktion''': Aufruf des Programms ProjectX zum Schneiden und Demultiplexen. Der Ton wird dabei zu einem wav-file decodiert.
 
*'''Input''': $quelldatei
 
*'''Output''': $dvd_tmp/film.m2v und/oder $dvd_tmp/*.wav und/oder $dvd_tmp/*.ac3 (ac3-Datei wird später gelöscht)
 
  
===<font color="olive"> normalisieren </font>===
+
==<font color="maroon"> Hauptmenue </font>==
*'''Aktion''': Ton auf eine definierte lautstärke bringen
+
Mit Aufruf der Funktion hauptmenue () wird ein Aufgabenbereich gewählt. Entspechend dieses Aufgabenbereiches wird (über case) zu den Untermenues verzweigt.
*'''Input''': ${tmp_pfad}/film.mp2.wav
 
*'''Output''': ${tmp_pfad}/film.mp2.wav
 
  
===<font color="olive"> encode2mp2 </font>===
+
==<font color="maroon"> Untermenues </font>==
*'''Aktion''': Audio-wav-file encodieren zu mp2
 
*'''Input''': ${tmp_pfad}/film.mp2.wav
 
*'''Output''': ${tmp_pfad}/film.mp2
 
  
===<font color="olive"> multiplexen </font>===
+
Am Beispiel des Untermenues mit der Kennziffer 11 wird die Funktionsweise des Hauptprogramms gezeigt.
*'''Aktion''': Multiplexen der seperaten Audio- und Videofiles
 
*'''Input''': $dvd_tmp/film.m2v und/oder $dvd_tmp/*.mp2 und/oder $dvd_tmp/*.ac3
 
*'''Output''': ${tmp_pfad}/film.mpg
 
  
===<font color="olive"> fehler </font>===
+
*''filmauswahl'': Das gewünschte Videofile wird geladen
*'''Aktion''': Programmabbruch, wenn nicht multiplext werden konnte
+
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
*'''Input''': ${tmp_pfad}/film.mpg
+
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
*'''Output''': exit
+
*''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.
  
===<font color="olive"> clip_speichern </font>===
+
=Links=
*'''Aktion''': Den Videoclip speichern
 
*'''Input''': KDE-Auswahlfenster / ${tmp_pfad}/film.mpg
 
*'''Output''': ${clipspeicher}
 
  
==<font color="green"> Szenario 8 </font>==
+
In der Artikelübersicht ist eine ausführliche Linkliste enthalten: [[vom DVB zur DVD: Vorstellung der Wiki-Artikel in dieser Serie]]
Identisch mit Szenario 7 bis auf die Funktion pjx_clip. Diese wird ersetzt durch
 
  
===<font color="olive"> mpeg1_input </font>===
 
*'''Aktion''': mpeg1-Video  demultiplexen. Dabei den Ton zu einem wav-file decodieren
 
*'''Input''': $quelldatei
 
*'''Output''': ${tmp_pfad}/film.mp2.wav und ${tmp_pfad}/film.m1v
 
  
 
{{Dvbscript navigationsbox}}
 
{{Dvbscript navigationsbox}}
 
----
 
----
 
[[Multimedia|Zurück zur Multimedia-Übersicht]]
 
[[Multimedia|Zurück zur Multimedia-Übersicht]]
[[Category:Multimedia]]
+
[[Category:DVB-Weiterverarbeitung]]

Aktuelle Version vom 9. Januar 2011, 14:50 Uhr

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

Vorbereitungen

Voreinstellungen

hauptverzeichnis=~/dvb_wiki_script
ini_verz=~/.dvb_wiki_script

aufnahme=~/DVB/Aufnahme
druckschablonen=~/DVB/Druckschablonen
videoclips=~/DVB/Videoclips

speed=8
dvdgroesse=4600000000

export VIDEO_FORMAT=PAL

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.
  • export: Über die Umgebungsvariable VIDEO_FORMAT wird das Videoformat auf PAL festgelegt

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 xine requant_lxdvdrip )

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=$aufnahme: 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 erzeugen

find $videoclips/* > $hauptverzeichnis/playlist
  • find $videoclips/*: Die im Clipordner gespeicherten Videoclips werden gesucht.
  • $hauptverzeichnis/playlist: Ihre Pfade werden in dieser Textdatei gespeichert.

Damit ist eine Playlist erzeugt worden, die zum Beispiel von mplaxer oder von xine ausgewertet werden kann.

Etwas mehr dazu steht in dem Wiki-Artikel playlist

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.

Aufgabenmenues

hauptmenue ()

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 \
	4	"Abspielen" 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.

untermenues

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

requantisieren ()

Jetzt gibt es, oh Schreck, etwas Mathematik. Mathe ist nicht nur etwas, mit dem viele Normal-Sterbliche, egal welchen Alters, auf Kriegsfuß stehen. Mathe ist auch etwas, mit dem die Bash nicht so ohne weiteres umgehen kann, wäre da nicht ein kleines eingebautes Tool mit dem Namen "bc". Mit diesem Tool hat die Bash einen Taschenrechner.Und genau so einen Rechner brauchen wir in dieser Funktion.

Der Sinn dessen, was wir hier tun, ist es, einen Film so zu stauchen, daß er auf eine einzelne DVD passt. Dieses Stauchen wollen wir, etwas eleganter, Requantisieren nennen. Und der "Stauchfaktor", also um wieviel mal das Ausgangsmaterial kleiner gemacht werden soll, bekommt von uns den Namen "Requantisierungsfaktor".

Es macht wenig Sinn, ein Audiofile verkleinern zu wollen. Ein Videofile mit seinen etlichen GByte Größe bietet hier mehr Aussicht auf Erfolg.

Die Formel, nach der wir den Requantisierungsfaktor berechnen, lautet so:

Requantifizierungsfaktor = ("Größe des Videofiles" / ("Was auf die DVD maximal passt" - "Summe aller Audiofiles"))*1,04

Wieso diese Formel gerade so lautet, darf der geneigte Leser selber zu ergründen versuchen. Eine kleine Denksportaufgabe ist mit Sicherheit nicht die Schlechteste aller Freizeitbeschäftigungen. Ich verrate nur soviel, daß der Faktor 1,04 dafür da ist, die Verwaltung des Dateisystems auf der DVD zu berücksichtigen (Die einzelnen Ordner brauchen ja schließlich auch Platz).

Schauen wir uns also eine Umsetzung dieser Formel in der Bash an:

videogroesse

videogroesse=`du -bc $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. dieses bc ist allerdings nicht identisch mit dem oben angepriesenen gleichnamigen Tachenrechner. Der kommt nachher noch)
  • $hauptverzeichnis/tmp1/*.m2v: Alle Dateien im tmp1, deren Name auf .m2v endet, 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
  • videogroesse=`....`: Diese Groesse wird in die Variable $videogroesse geschrieben

audiosumme

audio_summe=`du -bc $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2 | 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. dieses bc ist allerdings nicht identisch mit dem oben angepriesenen gleichnamigen Tachenrechner. Der kommt nachher noch)
  • $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2: Alle Dateien im tmp1, deren Name auf .ac3 oder .mp2 endet, 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_summe=`....`: Diese Groesse wird in die Variable $audio_summe geschrieben

requantisierungsfaktor

requantisierungsfaktor=`echo "scale=8 ; ${videogroesse}/$((dvdgroesse-audio_summe))*1.04" | bc`
  • bc: Nun ist er endlich da, unser Taschenrechner
  • ${videogroesse}/$((dvdgroesse-audio_summe))*1.04: Diese Formel wird ausgerechnet
  • scale=8: auf 8 Nachkommastellen genau
  • echo: und der Nachwelt zu Verfügung gestellt,
  • requantisierungsfaktor=`....`: indem es in diese Variable geschrieben wird

Die Requantisierung

cat $hauptverzeichnis/tmp1/film.m2v | requant_lxdvdrip $requantisierungsfaktor $videogroesse > $hauptverzeichnis/tmp1/film.requant
  • cat: Schreibe
  • $hauptverzeichnis/tmp1/film.m2v: diese Datei
  • |: mit Hilfe eine pipe
  • requant_lxdvdrip: in den Eingang von dem Requantisierungs-Tool
  • $requantisierungsfaktor: Es wird mit diesem Faktor requantisiert
  • $videogroesse: Soviel Bytes werden requantisiert
  • >: Das Ergebnis wird geschrieben
  • $hauptverzeichnis/tmp1/film.requant:in diese Datei
mv $hauptverzeichnis/tmp1/film.requant $hauptverzeichnis/tmp1/film.m2v

Die Datei film.requant wird zu film.m2v umbenannt. Diese Namensänderung ist notwendig, da die Funktion "multiplex ()" das Videofile unter dem Namen film.m2v erwartet.

audio_video_summe

audio_video_summe=`du -bc $hauptverzeichnis/tmp1/*.ac3 $hauptverzeichnis/tmp1/*.mp2 $hauptverzeichnis/tmp1/*.m2v | cut -f1 | tail -n 1`

Das Prinzip sollte nun bekannt sein. Das Ergebnis ist die Groesse der Summe aller Video- und Audiofiles und findet sich in der Variablen $audio_video_summe wieder

Muß requantisiert werden?

if [ $audio_video_summe -ge $dvdgroesse ] ; then

Wenn die Summe der Audio- und Videofiles größer ist als das, was auf die DVD drauf passt, dann wird die requantisiert.

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.

authoring_ohne_menue ()

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.

Abspielen

playlist_abspielen_shuffle ()

nohup $xine -P $hauptverzeichnis/playlist -a 1 -l=shuffle &
  • $xine: Audruf von xine als Videoplayer
  • -P $hauptverzeichnis/playlist: Diese Wiedergabeeliste wird abgespielt
  • -a 1: und dabei die Tonspur 1 verwendet (hier AC3)
  • -l=shuffle: die Wiedergabeliste wird in zufälliger Reihenfolge abgespielt.
  • &: Startet xine als Hintergrundprozess
  • nohup: Sorgt dafür, daß die Playlist weiterläuft, auch wenn das aufrufende Script beendet wird

Hauptprogramm

Hauptmenue

Mit Aufruf der Funktion hauptmenue () wird ein Aufgabenbereich gewählt. Entspechend dieses Aufgabenbereiches wird (über case) zu den Untermenues verzweigt.

Untermenues

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



Zurück zur Multimedia-Übersicht