Dvb wiki script/Programmieranleitung: Unterschied zwischen den Versionen

Aus Linupedia.org
Wechseln zu: Navigation, Suche
(Bearbeitungsbaustein hinzugefügt, da die Anpassung an die neue Scriptversion etwas heftiger ausfallen wird.)
(Fertig! Angepasst an die Scriptversion 0.8.0)
Zeile 1: Zeile 1:
{{UnderConstruction}}
 
'''Die Programmieranleitung wird angepasst an die neue Scriptversion.'''
 
 
 
{{Dvbscript navigationsbox}}
 
{{Dvbscript navigationsbox}}
 
{{blau|
 
{{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.7.0.}}
+
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.}}
 
 
=Die Funktionen=
 
 
 
==<font color="maroon"> Für's Austesten </font>==
 
 
 
=== stop () ===
 
Ist für Fehlersuche und Debugging gedacht und hält das Script an der gewünschten Stelle an.
 
 
 
==<font color="maroon"> Initialisierung </font>==
 
 
 
=== basisverzeichnis_festlegen () ===
 
In der versteckten Datei ~/.dvb_wiki_script_arbeitsverzeichnis.txt wird der Pfad zum Basisverzeichnis gespeichert. In diesem Basisverzeichnis befinden sich die Arbeitsordner des Scripts. Ist diese Textdatei nicht vorhanden, ist das ein Indiz dafür, daß das Script zum ersten Mal ausgeführt wird.
 
if [ ! -e ~/.dvb_wiki_script_arbeitsverzeichnis.txt ]
 
Wenn die Textdatei nicht vorhanden ist, das Script also zum ersten Mal Läuft, dann
 
hilfsverzeichnis=`kdialog --caption "Name des Arbeitsverzeichnisses" --inputbox ~/ dvb_wiki_script`
 
Frage nach dem gewünschten Basisverzeichnis
 
*''kdialog'': KDE-Dialogbox
 
*''--caption "Name des Arbeitsverzeichnisses"'': mit dem Titel "Name des Arbeitsverzeichnissses"
 
*''--inputbox'': welche als Eingabebox verwendet wird
 
*''~/'': In der Box wird der Pfad zum persönlichen Heimatverzeichnis als Beschreibung angezeigt
 
*''dvb_wiki_script'': Als Standardeingabe wird "dvb_wiki_script" festgelegt
 
*''hilfsverzeichnis'': In diese Variable wird die Eingabe gespeichert
 
if [ $? = 0 ]
 
Wenn die Eingabe mit "OK" bestätigt wurde, dann
 
basisverzeichnis=~/`echo $hilfsverzeichnis | tr -d " "`
 
werden eventuelle Leerzeichen aus der Eingabe entfernt (tr -d " ")und das Ergebnis in die Variable "basisverzeichnis" geschrieben
 
if [ -e ${basisverzeichnis} ]
 
Existiert bereits ein "basisverzeichnis" an dem gewünschten Ort, dann
 
kdialog --passivepopup "Verzeichnis existiert schon! Bitte neu wählen" 3
 
basisverzeichnis_festlegen
 
erfolgt ein Hinweis auf diese Tatsache. Nach drei Sekunden verschwindet die Popupbox und es wird die Funktion "basisverzeichnis_festlegen" erneut aufgerufen.
 
else
 
Gibt es das Verzeichnis noch nicht
 
kdialog --passivepopup "Die Verzeichnisstruktur wird in folgendem Arbeitsverzeichnis erstellt: ${basisverzeichnis}"
 
echo ${basisverzeichnis} > ~/.dvb_wiki_script_arbeitsverzeichnis.txt
 
wird angezeigt, wo das Basisverzeichnis angelegt wird. Anschließend wird der Inhalt der Variable "basisverzeichnis", also der Pfad zum Basisverzeichnis in die versteckte Textdatei geschrieben.
 
kdialog --passivepopup "Abbruch durch den Benutzer. Das Script wird nun beendet." 3
 
exit
 
Wurde in der Eingabebox auf Abbrechen gedrückt, wird das Script nach einem Hinweis beendet.
 
  
=== string_basisverzeichnis_testen () ===
+
=Vorbereitungen=
  
Diese Funktion überprüft, ob der festgelegte Pfad zum Basisverzeichnis auch korrekt interpretiert werden kann. Dazu wird nachgesehen, ob im String Leerzeichen, Sterne oder Tilden enthalten sind. Ebenso wird überprüft, ob die Datei, die diesen Pfad zwischenspeichert nicht nur vorhanden ist, sondern, daß ob auch was drinsteht.
+
==<font color="maroon"> Voreinstellungen </font>==
  
Im gesamten Script werden die Löschanweisungen durch einen doppelten Bindestrich abgeschlossen (z.B. rm -r -- ${irgendein_Verzeichnis}). Der doppelte Bindestrich bedeutet: Der Befahl mit allen Optionen ist abgeschlossen. Was folgt, darf nicht mehr als weitere Option interpretiert werden.
+
hauptverzeichnis=~/dvb_wiki_script
 +
ini_verz=~/.dvb_wiki_script
 +
 +
aufnahme=~/DVB/Aufnahme
 +
druckschablonen=~/DVB/Druckschablonen
 +
videoclips=~/DVB/Videoclips
 +
 +
speed=8
 +
dvdgroesse=4600000000
 +
Hier 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. dort findet man auch die X.ini für ProjectX.
 +
*''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 der 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.
  
Der Sinn des Ganzen liegt darin, zu verhindern, daß die Bash ungewollt  aus dem rm -r  ein rm -rf macht, was fatale Folgen haben könnte. Zusätzlich verhindert das Überpüfen des Strings, daß Dateien / Verzeichnisse gelöscht werden, die eigentlich hätten erhalten bleiben sollen.
+
==<font color="maroon"> Verzeichnisstruktur erstellen </font>==
  
  if [ -s ~/.dvb_wiki_script_arbeitsverzeichnis.txt ]
+
  mkdir $hauptverzeichnis 2>/dev/null
then
+
*''mkdir'': Es wird ein Verzeichnis erstellt
Wenn in der Hilfsdatei, die den Pfad zum Arbeitsverzeichnis enthält, irgendetwas drin steht, dann
+
*''$hauptverzeichnis'': Der Verzeichnispfad wird aus der Variablen ''hauptverzeichnis'' geholt ( default: dvb_wiki_script )
grep -e " " -e "*" -e "~" ~/.dvb_wiki_script_arbeitsverzeichnis.txt
+
*''2>/dev/null'': Eventuelle Meldungen des Befehls ''mkdir'' werden ins Nirwana umgeleitet
Schaue nach, ob da ein Stern, eine Tilde oder ein Leerzeichen dabei ist.
+
Das Anlegen der weiteren Verzeichnisse erfolgt analog
if [ $? = 0 ]
 
then
 
kdialog --error "Basisverzeichnis enthält unerlaubte Zeichen! Bitte Installation überprüfen!"
 
exit
 
Wenn eines dieser Zeichen vorhanden ist, dann sage uns: so geht es nicht und beende das Script
 
fi
 
Wenn keines dieser Zeichen vorhanden ist, dann kann normal weitergehen. Die Videobearbeitung kann beginnen.
 
else
 
kdialog --error "String Basisverzeichnis leer! Bitte Installation überprüfen!"
 
exit
 
In diesem Fall war die Hilfsdatei leer oder nicht vorhanden
 
 
 
=== arbeitsverzeichnisse_erstellen () ===
 
basisverzeichnis=`cat ~/.dvb_wiki_script_arbeitsverzeichnis.txt`
 
Der Pfad zum Basisverzeichnis wird aus der versteckten Testdatei gelesen und in die Variable "basisverzeichnis" geschrieben.
 
if [ ! -e ${basisverzeichnis} ] ; then mkdir ${basisverzeichnis} ; fi
 
Nun wird das Basisverzeichnis mit mkdir angelegt. Die if-Abrage dient nur zur Vermeidung von Fehlermeldungen, die auftreten würden, wenn das anzulegende Verzeichnis schon existiert, was ja ab dem zweiten Scriptlauf der Fall ist.
 
 
 
Anschließend werden die einzelnen Arbeitsverzeichnisse angelegt:
 
*''dvd_aufnahme'': Hier wird zuerst nach den zu bearbeitenden Filmen gesucht.
 
*''dvd_tmp'': Hier legen die Helferprogramme Zwischenergebnisse ab und suchen nach den Ergebnissen anderen Helferprogramme
 
*''dvd_struktur'': In diesem Ordner wird die fertige DVD-Struktur zwischengespeichert.
 
*''dvd-sicherung'': Hierhin werden fertige Arbeitsergebnisse gesichert, wenn das vom User so gewünscht wird.
 
*''default'': Hier stehen die Pfadnamen der Helferprogramme und die Initialisierungsdateien für ProjectX.
 
*''screenshot'': Mit kaffeine erstellte Screenshots der Filme / Clips, die ich dann zum Bedrucken der DVD verwende.
 
 
 
=== programmerkennung () ===
 
  
 +
==<font color="maroon"> Erkennung der Helferprogramme </font>==
 
In dieser Routine wird nachgesehen, ob die notwendigen Helferprogramme installiert sind. Und das funktioniert so:
 
In dieser Routine wird nachgesehen, ob die notwendigen Helferprogramme installiert sind. Und das funktioniert so:
  
====<font color="gray"> Hauptschleife </font>====
+
===Namen der notwendigen Helferprogramme===
  for ((i=0 ; i<9 ; i++))
+
  hilfsprogramm=( mplex dvdauthor ProjectX.jar normalize ffmpeg growisofs )
Diese Schleife wird neunmal durchlaufen, so oft also, wie Helferprogramme vorhanden sind.
+
Die benötigten Helferprogramme werden als Array in der Variablen ''hilfsprogramm'' abgelegt.
  
Alles folgende spielt sich in der Schleife ab.
+
===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
  
====<font color="gray"> Default-Pfade lesen </font>====
+
====<font color="gray"> Ini-Datei anlegen </font>====
  pfad[i]=`cat $basisverzeichnis/default/pfad[$i].txt`
+
  touch $ini_verz/$var
*''$basisverzeichnis/default/pfad[$i].txt'': Der Inhalt dieser Datei (das ist der Pfad, wo das zugehöige Programm gefunden werden kann)
+
*''touch'': So noch nicht vorhanden, wird eine leere Datei erzeugt
*''cat'': wird gesendet (über die Standartausgabe)
+
*''$ini_verz/$var'': und zwar im Initialisierungsverzeichnis. Die Datei erhält dann den Namen der gerade aktuellen Schleifenvariablen (z.B. mplex)
*'' pfad[i]=`...`'': an die Variable ${pfad[i]}
 
  
Das i steht immer für die Nummer des Schleifendurchlaufs und damit dafür, welches Programm gerade gesucht wird.
+
====<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. In ''$hilfsvar'' steht also der Pfad zu dem Helferprogramm, dessen Name in ''$var'' steht.
  
 
====<font color="gray"> Helferprogramm vorhanden? </font>====
 
====<font color="gray"> Helferprogramm vorhanden? </font>====
  if [ ! -e ${pfad[i]}/${name[i]} ]
+
  if [ ! -e "$hilfsvar/$var" ]
Wenn das Programm nicht existiert,dann
+
Wenn die in den Variablen angegebene Datei (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 nach dem Helferprogramm los
  
 
====<font color="gray"> Programmsuche </font>====
 
====<font color="gray"> Programmsuche </font>====
  gefundene_pfade=`find ${suchpfade} -type f -name ${name[i]} -printf "%h "`
+
  gefundene_pfade=`find /bin $HOME /opt /usr ! -path "$HOME/.*" -type f -name $var ! -printf "%h " 2>/dev/null`
*''find ${suchpfade}'': In den Suchpfaden suchen
+
*''find'': Suche
*''-type f'': nach einer normalen Datei
+
*''-type f'': ein normales Programm
*''-name ${name[i]}'': mit dem Namen, der in der Variablen ${name[i]} steht.
+
*''-name $var'': mit dem Namen, der in ''var'' enthalten ist (also im Beispiel mplex)
*''-printf "%h "'': Von den gefundenen Dateien werden die Verzeichnisnamen ausgegeben
+
*''/bin $HOME /opt /usr'': Die Suche beschränkt sich auf diese Pfade
*'' gefundene_pfade='': und in diese Variable geschrieben
+
*''! -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="gray"> Wieviele Versionen des Helferprogramms gefunden? </font>====
 
====<font color="gray"> Wieviele Versionen des Helferprogramms gefunden? </font>====
  pfadanzahl=`echo "$gefundene_pfade" | wc -w`
+
  pfadzahl=`echo "$gefundene_pfade" | wc -w`
 
*''echo "$gefundene_pfade"'': Von dem, was in der Variablen $gefundene_pfade steht
 
*''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).
 
*''wc -w'' werden die Worte gezählt (und damit die Anzahl der gefundenen Pfade).
*''pfadanzahl='': diese Anzahl wird in die Variable $pfadanzahl geschrieben.
+
*''pfadzahl='': diese Anzahl wird in der Variablen $pfadzahl zwischengespeichert.
  
 
====<font color="gray"> Was wird damit gemacht? </font>====
 
====<font color="gray"> Was wird damit gemacht? </font>====
  case "$pfadanzahl" in
+
  case "$pfadzahl" in
 
In Abhängigkeit der Anzahl der gefundenen Pfade passiert folgendes:
 
In Abhängigkeit der Anzahl der gefundenen Pfade passiert folgendes:
  
Zeile 127: Zeile 87:
 
Nach einem Hinweis wird das Script beendet . Das fehlende Helferprogramm muß installiert werden..
 
Nach einem Hinweis wird das Script beendet . Das fehlende Helferprogramm muß installiert werden..
 
*''1)'': Anzahl 1, das Programm existiert genau einmal.
 
*''1)'': Anzahl 1, das Programm existiert genau einmal.
Der dazugehörige Pfad wird in das Default-Verzeichnis geschrieben.
+
Der dazugehörige Pfad wird in das Ini-Verzeichnis geschrieben.
 
*''*)'': Das Programm existiert mehr als einmal.
 
*''*)'': Das Programm existiert mehr als einmal.
Es wird nachgefragt (kdialog --combobox), welcher der Pfade verwendet werden soll. Dieser Pfad wird dann ins Default-Verzeichnis geschrieben.
+
Es wird nachgefragt (kdialog --combobox), welcher der Pfade verwendet werden soll. Dieser Pfad wird dann ins Ini-Verzeichnis geschrieben.
  
Nachdem diese Routine neunmal erfolgreich durchlaufen ist, ist die Funktion beendet und es geht mit der im Hauptprogramm folgenden Funktion weiter
+
==<font color="maroon"> Zuweisung der Helferprogramme zu Variablen </font>==
 +
# 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.
  
=== variablenzuweisungen () ===
+
==<font color="maroon"> Initialisierungsdatei für ProjectX erzeugen</font>==
Diese Zuweisungen haben den Sinn, das Script besser lesbar zu machen. Im Script selbst wird dann zum größten Teil mit diesen Variablen gearbeitet bzw. mit
+
Die X.ini.film enthält folgende Einstellungen (Voraussetzung ist ProjectX in der CVS-Version b28 oder größer)
in Variablen gespeicherten Pfaden. Durch diese Strategie kann das Script einfach an neue Gegebenheiten anpepasst werden. Es muß nicht lange im Code gesucht werden,
+
*''Application.Agreement=1'': Ja zur Lizenz
an welchen Stellen was geändert werden muß. Es braucht nur der Inhalt der entsprechenden Variablen ausgetauscht werden.
+
*''Application.Language=de'': PJX startet auf deutsch
 +
*''Application.ActiveDirectory=$hauptverzeichnis/screenshots'': Damit kommen die Screenshots dahin, wohin sie sollen
  
=== konfiguration () ===
+
*''CollectionPanel.Preview.SliderWidth=0'': Der Vorschau-Slider bekommt dieselbe Breite wie das Vorschaufenster
  
====<font color="gray"> X.ini für Filmbearbeitung </font>====
+
*''WindowPosition.Main.Width=9999'': Die Breite des PJX-Fensters wird maximiert
 
+
*''WindowPosition.Main.Y=0'': Das Fenster wird ab dem Bildschirmrand gezeichnet
Die X.ini.film enthält folgende Einstellungen:
 
 
 
*''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.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
 
*''OptionPanel.CloseOnEnd=1'': Nachdem PJX fertig ist, beendet es sich selber
  
Die X.ini wird im Default-Verzeichnis abgelegt, von wo sie bei Bedarf von ProjectX geladen wird.
+
Die X.ini wird im Initialisierungsverzeichnis abgelegt, von wo sie bei Bedarf von ProjectX geladen wird.
  
 
Werden im PJX-Fenster irgendwelche Einstellungen verändert, so werden diese Änderungen nicht in die X.ini übernommen. Das wurde absichtlich
 
Werden im PJX-Fenster irgendwelche Einstellungen verändert, so werden diese Änderungen nicht in die X.ini übernommen. Das wurde absichtlich
Zeile 161: Zeile 122:
 
zu lassen.
 
zu lassen.
  
==<font color="maroon"> Verwaltung / Löschen </font>==
+
==Playlist für mplayer erzeugen==
 +
find $videoclips/* > ~/.mplayer/playlist
 +
*''find $videoclips/*'': Die im Clipordner gespeicherten Videoclips werden gesucht.
 +
*''~/.mplayer/playlist'': Deren Pfade werden in diese Textdatei gespeichert
 +
Damit ist eine von mplayer verwendbare Playlist erzeugt worden
  
=== loeschen_temporaere_arbeitsordner () ===
+
==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
 +
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''.
  
*''rm'': Die Inhalte der Ordners ${basisverzeichnis}/dvd_tmp und ${basisverzeichnis}/dvd_tmp1 werden gelöscht.
+
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>
*''rm -r'': Der Ordner ${basisverzeichnis}/dvd_struktur enthält Verzeichnisse, die wiederum Dateien enthalten und muß des halb rekursiv gelöscht werden.
+
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!
  
=== loeschen_dvd_sicherung () ===
 
  
*''loeschordner="dvd_sicherung"'': Variable die in der folgenden Anzeigefunktion benötigt wird
+
=Die Funktionen=
*''anzeige_was_wird_geloescht'': Die aufgerufene Funktion tut genau das, was im Funktionsnamen steht
 
*''wirklich'': In dieser Funktion muß das Löschen noch einmal bestätigt werden
 
*''rm -r'': Und schließlich wird der Inhalt des Ordners dvd_sicherung gelöscht
 
  
=== loeschen_dvd_screenshot () ===
+
==<font color="maroon"> Abbruch </font>==
  
*''loeschordner="dvd_screenshot"'': Variable die in der folgenden Anzeigefunktion benötigt wird
+
===benutzerabbruch ()===
*''anzeige_was_wird_geloescht'': Die aufgerufene Funktion tut genau das, was im Funktionsnamen steht
+
echo "Abbruch durch den Benutzer"
*''wirklich'': In dieser Funktion muß das Löschen noch einmal bestätigt werden
+
Diese Meldung wird über die Konsole ausgegeben
*''rm'': Und schließlich wird der Inhalt des Ordners dvd_screenshot gelöscht
+
programmende
 +
Die Funktion programmende () wird aufgerufen
  
=== basisverzeichnis_aendern () ===
+
===funktionsabbruch ()===
 +
echo "$1"
 +
Es wird der in $1 gespeicherte Text über die Konsole ausgegeben.
 +
programmende
 +
Die Funktion programmende () wird aufgerufen
  
*''kdialog --msgbox'': Hinweis auf das, was nun geschieht
+
In der Variablen $1 ist das gespeichert, was der Funktion bei ihrem Aufruf als Argument übergeben wurden. Beispiel:
*''wirklich'': In dieser Funktion muß das Löschen noch einmal bestätigt werden
+
funktionsabbruch "Heute scheint die Sonne"
*''rm'': Damit wird die versteckte Textdatei ~/.dvb_wiki_script_arbeitsverzeichnis.txt gelöscht
+
Der "Sonnentext" wird der Funktion bei ihrem Aufruf übergeben und steht dann dort in der Variablen $1 für weitere Schandtaten zur Verfügung.
Das hat zur Folge, daß beim nächsten Scriptstart ein neues Basisverzeichnis angelegt werden muß
 
  
=== deinstallation () ===
+
===programmende ()===
 
+
echo "Ende"
*''kdialog --msgbox'': Hinweis auf das, was nun geschieht
+
Im Konsolenfester wird der Text ''Ende'' angezeigt
*''wirklich'': In dieser Funktion muß das Löschen noch einmal bestätigt werden
+
kdialog --msgbox "Programmende"
*''rm / rmdir'': Der Basisordner samt Inhalten und die versteckte Textdatei werden gelöscht
+
*''kdialog'': Es wird ein KDE-Dialogfenster fenster geöffnet,
Damit ist das Script deinstalliert.
+
*''--msgbox'': das als Info-Fenster formatiert ist.
 
+
*''"Programmende""'': Im Fenster wird die Meldung ''Programmende'' angezeigt
=== anzeige_was_wird_geloescht () ===
+
Nach dem Drücken auf den OK-Knopf im kdialog-Fenster wird mit
 
+
exit
*''cd'': Es wird in das Verzeichnis gewechselt, das gelöscht werden soll
+
das Script beendet.
*''ordnerinhalt=`ls -d1 * `'': Der Inhalt des Verzeichnisses wird in die Hilfsvariable $ordnerinhalt geschrieben
 
*''kdialog --msgbox'': Und auf dem Bildschirm zur Anzeige gebracht.
 
 
 
=== wirklich () ===
 
 
 
*''kdialog --yesno'': Es wird gefragt, ob wirklich gelöscht werden soll
 
*''if [ $? != 0 ]'': Bei "Nein" als Antwort wird nach einem Hinweis das Script beendet
 
  
 
==<font color="maroon"> Aufgabenmenues </font>==
 
==<font color="maroon"> Aufgabenmenues </font>==
Zeile 216: Zeile 178:
 
*''--radiolist'' als Liste mit Radio-Buttons
 
*''--radiolist'' als Liste mit Radio-Buttons
 
*''"Bitte einen Aufgabenbereich wählen"'': Das wird gefragt.
 
*''"Bitte einen Aufgabenbereich wählen"'': Das wird gefragt.
*''auswahl_hauptmenue`...`'': In diese Variable wird die Nummer der Antwort geschrieben.
+
*''auswahl_hauptmenue=`...`'': In diese Variable wird die Nummer der Antwort geschrieben.
 +
Diese Nummer wird dann später vom Hauptprogramm ausgewertet.<br>
 +
Der per default aktivierte Eintrag der List wird durch das ''on'' festgelegt.
  
Diese Nummer wird dann später vom Hauptprogramm ausgewertet.
 
 
  if [ $? != 0 ]
 
  if [ $? != 0 ]
 
  then
 
  then
  kdialog --passivepopup "Abbruch durch den Benutzer. Das Script wird nun beendet." 3
+
  benutzerabbruch
exit
 
 
  fi
 
  fi
 
Wenn im Auswahlfenster auf Abbrechen gedrückt wird, dann wird das Script beendet.
 
Wenn im Auswahlfenster auf Abbrechen gedrückt wird, dann wird das Script beendet.
  
 
=== untermenue_video_dvd () ===
 
=== untermenue_video_dvd () ===
Diese Funktion arbeitet analog zum Hauptmenue mit dem Untrscheid, daß die Antwortnummer in die Variable was_tun gespeichert wird.
+
Diese Funktion arbeitet analog zum Hauptmenue mit dem Unterscheid, daß die Antwortnummer in die Variable was_tun gespeichert wird.
  
=== untermenue_ts () ===
+
Die weiteren Untermenues funktionieren ebenso.
Siehe Funktion untermenue_video_dvd ()
 
  
=== untermenue_videoclip () ===
+
==<font color="maroon"> °Auswahl Quelldateien </font>==
Siehe Funktion untermenue_video_dvd ()
 
 
 
=== untermenue_direktdruck () ===
 
Siehe Funktion untermenue_video_dvd ()
 
 
 
=== untermenue_verwaltung () ===
 
Siehe Funktion untermenue_video_dvd ()
 
 
 
==<font color="maroon"> Auswahl der Eingangsdateien </font>==
 
  
 
=== filmauswahl_dvd () ===
 
=== filmauswahl_dvd () ===
Die Variable brenn_pfad wird mit dem Inhalt der Variablen ${dvdstruktur_pfad} belegt. Danach wird die Funktion filmauswahl () aufgerufen.
+
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 Brennpfad mit den erforderlichen Daten gefüttert.
  
=== filmauswahl_ts () ===
 
Die Variable brenn_pfad wird mit dem Inhalt der Variablen ${tmp_pfad} belegt. Danach wird die Funktion filmauswahl () aufgerufen.
 
 
=== filmauswahl () ===
 
 
  quelldatei=`kdialog --caption "Filmauswahl" --geometry 600x500-0+0 --getopenfilename ${aufnahme_pfad}`
 
  quelldatei=`kdialog --caption "Filmauswahl" --geometry 600x500-0+0 --getopenfilename ${aufnahme_pfad}`
 
*''kdialog'': Das KDE-Dialog-Programm
 
*''kdialog'': Das KDE-Dialog-Programm
Zeile 259: Zeile 214:
  
 
=== verzeichnisauswahl_dvd () ===
 
=== verzeichnisauswahl_dvd () ===
Die Variable $verzeichnistyp wird mit dem String *_dvd belegt. Dieser String wird zur Dateisuche mit find in der nun aufgerufenen Funktion verzeichnisauswahl () benötigt.
+
case $was_tun in
 
+
13) verzeichnistyp="*_dvd" ;;
=== verzeichnisauswahl_ts () ===
+
23) verzeichnistyp="*_ts" ;;
Die Variable $verzeichnistyp wird mit dem String *_ts belegt. Dieser String wird zur Dateisuche mit find in der nun aufgerufenen Funktion verzeichnisauswahl () benötigt.
+
esac
 
+
Die Variable $verzeichnistyp wird mit dem String ''*_dvd'' bzw. ''*_ts'' belegt. Dieser String wird zur Dateisuche mit find in der nun aufgerufenen Funktion verzeichnisauswahl () benötigt.
=== verzeichnisauswahl() ===
+
  anzahl_der_sicherungen=`find $hauptverzeichnis/sicherung/$verzeichnistyp -maxdepth 0 -type d | wc -l`
  anzahl_der_sicherungen=`find $sicherungs_pfad/$verzeichnistyp -maxdepth 0 -type d | wc -l`
 
 
Die Anzahl der gesicherten Arbeitsergebnisse (*_dvd oder *_ts) wird ermittelt und zwischengespeichert.
 
Die Anzahl der gesicherten Arbeitsergebnisse (*_dvd oder *_ts) wird ermittelt und zwischengespeichert.
  hilfsverzeichnis=`find $sicherungs_pfad/$verzeichnistyp -maxdepth 0 -type d`
+
  hilfsverzeichnis=`find $hauptverzeichnis/sicherung/$verzeichnistyp -maxdepth 0 -type d`
 
Die Namen der gesicherten Arbeitsergebnisse (*_dvd oder *_ts) wird ermittelt und zwischengespeichert.
 
Die Namen der gesicherten Arbeitsergebnisse (*_dvd oder *_ts) wird ermittelt und zwischengespeichert.
 
case $anzahl_der_sicherungen in
 
case $anzahl_der_sicherungen in
Zeile 273: Zeile 227:
 
*Anzahl 0: Das Script wird nach einem Hinweis beendet, da keine passene Sicherung zum Brennen gefunden wurde
 
*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 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 und in die Variable $brenn_pfad kopiert.
+
*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 weis growisofs, was zu brennen ist.
  
 
==<font color="maroon"> Eingangsverarbeitung </font>==
 
==<font color="maroon"> Eingangsverarbeitung </font>==
  
 
=== pjx_demux_gui () ===
 
=== pjx_demux_gui () ===
  java -jar ${pjx} -demux -gui -ini ${default_pfad}/X.ini.film -out ${tmp_pfad} -name film "$quelldatei" 1>/dev/null
+
  java -jar $pjx -demux -gui -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
 
*''-demux'': Der mpeg-Stream wird demultiplext
 
*''-gui'': PJX startet mit graphischer oberfläche (notwendig nur, wenn mit PJX geschnitten werden soll)
 
*''-gui'': PJX startet mit graphischer oberfläche (notwendig nur, wenn mit PJX geschnitten werden soll)
*''-ini ${default_pfad]/X.ini.film'': mit dieser Initialisierungsdatei wird PJX gestartet.
+
*''-ini $hauptverzeichnis/X.ini'': mit dieser Initialisierungsdatei wird PJX gestartet.
*''-out $tmp_pfad'': Hierhin wird das Bearbeitungsergebnis geschrieben
+
*''-out $hauptverzeichnis/tmp1'': Hierhin wird das Bearbeitungsergebnis geschrieben
 
*''-name film'': Die Ausgabedatei erhält den Basisnamen "film"
 
*''-name film'': Die Ausgabedatei erhält den Basisnamen "film"
 
'''$quelldatei'':Dieser Stream wird verarbeitet
 
'''$quelldatei'':Dieser Stream wird verarbeitet
*''1>/dev/null'': Alles, was ich an Ausgeben auf dem Bildschirm nicht sehen will, wird ins Leere geschickt.
+
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 diese Dateien 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 alles 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 () ===
 
=== pjx_ts_gui () ===
  java -jar ${pjx} -tots -gui -split 4300 -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)
Zeile 296: Zeile 266:
 
*''-gui'': PJX startet mit graphischer oberfläche (notwendig nur, wenn mit PJX geschnitten werden soll)
 
*''-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)
 
*''-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.
+
*''-ini $hauptverzeichnis/X.ini'': mit dieser Initialisierungsdatei wird PJX gestartet.
*''-out $tmp_pfad'': Hierhin wird das Bearbeitungsergebnis geschrieben
+
*''-out $hauptverzeichnis/tmp1'': Hierhin wird das Bearbeitungsergebnis geschrieben
 
'''-name film'': Die Ausgabedatei erhält den Basisnamen "film"
 
'''-name film'': Die Ausgabedatei erhält den Basisnamen "film"
 
*''$quelldatei'':Dieser Stream wird verarbeitet
 
*''$quelldatei'':Dieser Stream wird verarbeitet
*''1>/dev/null'': Alles, was ich an Ausgeben auf dem Bildschirm nicht sehen will, wird ins Leere geschickt.
 
  
 
=== mpeg1_input () ===
 
=== mpeg1_input () ===
  ${ffmpeg} -i "${quelldatei}" -acodec copy ${tmp_pfad}/film.mp2 -vcodec copy ${tmp_pfad}/film.m1v
+
  $ffmpeg -i "$quelldatei" $hauptverzeichnis/tmp1/film.mp2 -vcodec copy $hauptverzeichnis/tmp1/film.m1v
 
*''${ffmpeg}'': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg),
 
*''${ffmpeg}'': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg),
 
*''-i ${quelldatei}'': um diesen Video-Clip zu demultiplexen
 
*''-i ${quelldatei}'': um diesen Video-Clip zu demultiplexen
  
 
==<font color="maroon"> Bearbeitung </font>==
 
==<font color="maroon"> Bearbeitung </font>==
 
=== 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:
 
 
====<font color="gray"> videogroesse </font>====
 
videogroesse=`du -bc ${tmp_pfad}/*.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)
 
*''${tmp_pfad}/*.m2v'': Alle Dateien im tmp_pfad, 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
 
 
====<font color="gray"> audiosumme </font>====
 
audio_summe=`du -bc ${tmp_pfad}/*.ac3 ${tmp_pfad}/*.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)
 
*''${tmp_pfad}/*.ac3 ${tmp_pfad}/*.mp2'': Alle Dateien im tmp_pfad, 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
 
 
====<font color="gray"> audio_video_summe </font>====
 
audio_video_summe=`du -bc ${tmp_pfad}/*.ac3 ${tmp_pfad}/*.mp2 ${tmp_pfad}/*.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
 
 
====<font color="gray"> requantisierungsfaktor </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
 
 
====<font color="gray"> Muß requantisiert werden? </font>====
 
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.
 
 
====<font color="gray"> Die Requantisierung </font>====
 
${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.
 
  
 
=== normalisieren () ===
 
=== normalisieren () ===
Zeile 404: Zeile 306:
  
 
====<font color="gray"> Ton-Dateien vorbereiten </font>====
 
====<font color="gray"> Ton-Dateien vorbereiten </font>====
  mv ${basisverzeichnis}/dvd_tmp/film.mp2 ${basisverzeichnis}/dvd_tmp1
+
  mv $hauptverzeichnis/tmp1/film.mp2 $hauptverzeichnis/tmp2
  rm ${basisverzeichnis}/dvd_tmp/*.mp2
+
  rm -- $hauptverzeichnis/tmp1/*.mp2
Es gibt Fernsehsender, die mehr als eine mp2-Tondatei senden, zum Beispiel einen zusätzlich zum normalen Stereoton einen Zweikanalton. Wir wollen uns beim normalisieren ausschließlich auf den Stereoton beschränken. Deshalb werden alle anderen mp2-Dateien gelöscht.
+
Normalisieren funktioniert sinnvoll nur mit mp2 Dateien, der Rest fliegt raus.
  
 
====<font color="gray"> mp2 decodieren </font>====
 
====<font color="gray"> mp2 decodieren </font>====
  ${ffmpeg} -i ${basisverzeichnis}/dvd_tmp1/film.mp2 ${basisverzeichnis}/dvd_tmp1/film.mp2.wav
+
  $ffmpeg -i $hauptverzeichnis/tmp2/film.mp2 $hauptverzeichnis/tmp2/film.mp2.wav
 
Aus dem mp2-File wird mit Hilfe von ffmpeg ein wav-File gemacht.
 
Aus dem mp2-File wird mit Hilfe von ffmpeg ein wav-File gemacht.
  
 
====<font color="gray"> normalisieren </font>====
 
====<font color="gray"> normalisieren </font>====
  ${normalize} -v ${basisverzeichnis}/dvd_tmp1/film.mp2.wav
+
  $normalize $hauptverzeichnis/tmp2/film.mp2.wav
 
Das wav-File wird normalisiert. Es überschreibt sich dabei selbst mit dem Ergebnis.
 
Das wav-File wird normalisiert. Es überschreibt sich dabei selbst mit dem Ergebnis.
  
 
====<font color="gray"> encodieren zu mp2 </font>====
 
====<font color="gray"> encodieren zu mp2 </font>====
  ${ffmpeg} -i ${basisverzeichnis}/dvd_tmp1/film.mp2.wav -acodec mp2 -ab 192k ${tmp_pfad}/film.mp2
+
  $ffmpeg -i $hauptverzeichnis/tmp2/film.mp2.wav -acodec mp2 -ab 192k $hauptverzeichnis/tmp1/film.mp2
Aus einer wav -Datei wird wieder ein mp2-File gemacht.
+
Aus der wav -Datei wird wieder ein mp2-File gemacht.
 
*''${ffmpeg}'': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg)
 
*''${ffmpeg}'': Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg)
*''-i ${tmp_pfad1}/film.mp2.wav'': Dieses PCM-file
+
*''-i $hauptverzeichnis/tmp2/film.mp2.wav'': Dieses PCM-file
 
*''-acodec mp2'': wird zu einem mp2-File encodiert,
 
*''-acodec mp2'': wird zu einem mp2-File encodiert,
 
*''-ab 192k'': welches eine Audio-bitrate von 192k erhält (mp2-Standard)
 
*''-ab 192k'': welches eine Audio-bitrate von 192k erhält (mp2-Standard)
*''${tmp_pfad}/film.mp2'': Das Ergebnis findet man dann hier
+
*''$hauptverzeichnis/tmp1/film.mp2'': Das Ergebnis findet man dann hier
  
 
=== ac3_behalten () ===
 
=== ac3_behalten () ===
Es weden ausschließlich AC3-Tondateien zur Weiterverarbeitung bereitgestellt. Alles andere, was "Ton" heißt, wird gelöscht
+
Es weden ausschließlich AC3-Tondateien zur Weiterverarbeitung bereitgestellt. Alles andere, was "Ton" heißt, wird gelöscht. Gibt es keinen AC3-Ton, dann bricht das Script nach einem Hinweis ab.
  
 
=== mp2_behalten () ===
 
=== mp2_behalten () ===
Es weden ausschließlich mp2-Tondateien zur Weiterverarbeitung bereitgestellt. Alles andere, was "Ton" heißt, wird gelöscht
+
Es weden ausschließlich mp2-Tondateien zur Weiterverarbeitung bereitgestellt. Alles andere, was "Ton" heißt, wird gelöscht. Gibt es keinen mp2-Ton, dann bricht das Script nach einem Hinweis ab.
  
 
=== multiplexen () ===
 
=== multiplexen () ===
Zeile 436: Zeile 338:
 
====<font color="gray"> Vorbereiten der Dateien </font>====
 
====<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>====
 
====<font color="gray"> Das eigentliche Multiplexen </font>====
  ${mplex} -v1 -f8 -o ${tmp_pfad}/film.mpg ${mpeg1_video} ${mpeg2_video} ${mp2_audio} ${ac3_audio}
+
  $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)
 
*''${mplex}'': Aufruf von mplex (z.B.: /usr/bin/mplex)
 
*''-v1'': Fortschrittsanzeige (beim Befehl mplex leider nicht so sehr fortschrittlich)
 
*''-v1'': Fortschrittsanzeige (beim Befehl mplex leider nicht so sehr fortschrittlich)
 
*''-f8'': Format zur späteren Erzeugung einen DVD
 
*''-f8'': Format zur späteren Erzeugung einen DVD
*''-o ${tmp_pfad}/film.mpg'': Das Ergebnis
+
*''-o $hauptverzeichnis/tmp1/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.
 
*''${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.
+
if [ ! -e $hauptverzeichnis/tmp1/film.mpg ]
 +
then
 +
funktionsabbruch "Es konnte keine Datei multiplext werden!"
 +
fi
 +
Wenn nicht demultiplext werden konnte (keine mpg-Datei im tmp1-Pfad), dann wird das Programm abgebrochen.
  
 
=== authoring_ohne_menue () ===
 
=== 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 ein 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'': In diesem Ordner: -o $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="maroon"> Ergebniskontrolle </font>==
 
 
=== abspielen () ===
 
$kaffeine -nofork --geometry 600x500-0+0 ${brenn_pfad}
 
*''$kaffeine'': Der Videoplayer wird gestartet,
 
*''--nofork'': luft im Vordergrund
 
*''${brenn_pfad}''': und spielt die hier enthaltene Datei ab
 
  
 
==<font color="maroon"> Brennen </font>==
 
==<font color="maroon"> Brennen </font>==
Zeile 472: Zeile 369:
 
=== brennen_video_dvd () ===
 
=== 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}
+
  $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 Brenngeschwindigkeit
 
*''-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 der Rückmeldung von growisofs kann erkannt werden werden, ob die DVD bereit ist, Daten aufzunehmen. Das Tool gibt dann eine Null zurück. Dieser Rückgabewert kann über die Variable $? ausgewertet werden.
 +
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 steht Null in $? und es wird mit dem nächsten Trocklauf zur DVD-Erkennung weitergemacht.
 +
Ist die DVD endlich bereit, dann wird das $? vom Tockenlauf (mit growisofs) Null, 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_ts () ===
Zeile 488: Zeile 402:
 
*''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 If-Schleife passiert nun folgendes:
kdialog --msgbox "Bitte DVD Nr.: $i einlegen"
+
Es erfolgt der schon von ''brennen_dvd () '' bekannte Trockenlauf zur DVD-Erkennung mit der Möglichkeit, den Vorgang abzubrechen. 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)))"*
 
 
*''${growisofs}'': Programmaufruf für growisofs (z.B. /usr/bin/growisofs)
 
*''${growisofs}'': Programmaufruf für growisofs (z.B. /usr/bin/growisofs)
*''-speed=${brenngeschwindigkeit}'': maximale Brenngeschwindigkeit
+
*''-speed=$speed'': 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)))'': Diese Datei auf DVD brennen
+
*''$brenn_pfad/"film($((i-1)))[remux].ts'': Diese Datei auf DVD brennen
 +
Es werden in der if-Schleife solange DVDs angefordert, bis all Daten gebrannt sind.
 +
 
  
 
==<font color="maroon"> Sichern </font>==
 
==<font color="maroon"> Sichern </font>==
Zeile 504: Zeile 419:
 
=== sichern_dvd_struktur () ===
 
=== sichern_dvd_struktur () ===
 
Diese Funktion sichert die DVD-Struktur
 
Diese Funktion sichert die DVD-Struktur
  sicherungsordner=$(date +%Y%m%d%H%M%S)_dvd
+
  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.
 
In diesen Sicherungsordner wird die DVD-Struktur geschrieben. Der Name des Ordner wird aus dem aktuellen Datum und der momentanen Uhrzeit generiert.
  mkdir ${sicherungs_pfad}/${sicherungsordner}
+
  mkdir $hauptverzeichnis/sicherung/$sicherungsordner
 
Hiermit wird der Sicherungsordner angelegt
 
Hiermit wird der Sicherungsordner angelegt
  mv ${dvdstruktur_pfad}/* ${sicherungs_pfad}/${sicherungsordner}
+
  mv $hauptverzeichnis/dvdstruktur/* $hauptverzeichnis/sicherung/$sicherungsordner
 
mv verschiebt die DVD-Struktur in den Sicherungsordner
 
mv verschiebt die DVD-Struktur in den Sicherungsordner
 +
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 () ===
 
=== sichern_ts () ===
Zeile 517: Zeile 434:
 
  mkdir ${sicherungs_pfad}/${sicherungsordner}
 
  mkdir ${sicherungs_pfad}/${sicherungsordner}
 
Hiermit wird der Sicherungsordner angelegt
 
Hiermit wird der Sicherungsordner angelegt
  mv ${tmp_pfad}/*.ts ${sicherungs_pfad}/${sicherungsordner}
+
  mv $hauptverzeichnis/tmp1/*.ts $hauptverzeichnis/sicherung/$sicherungsordner
 
mv verschiebt die TS-files in den Sicherungsordner
 
mv verschiebt die TS-files in den Sicherungsordner
 +
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 () ===
 
===< sichern_clip () ===
 
Diese Funktion speichert einen Videoclip
 
Diese Funktion speichert einen Videoclip
  clipspeicher=`kdialog --title "$quelldatei" --getsavefilename ${clip_pfad}`
+
  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.
*''${clip_pfad}'': 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
 +
fi
 +
Damit wird die Abbruchtaste des KDE-Dialogs ausgewertet.
 +
if [ -e "$clipspeicher" ]
 +
then
 +
......
 +
fi
 +
Existiert bereits ein Clip mit dem gleichen Namen, dann
 +
kdialog --yesno "Dieser Clip ist schon gespeichert. Überschreiben?"
 +
wird gefragt ob der Clip überschrieben werden darf.
 +
if [ $? != 0 ]
 +
then
 +
sichern_clip
 +
fi
 +
Wurde ''Nein'' gedrückt, dann wird die Funktion ''sichern_clip ()'' erneut aufgerufen. Der Dialog beginnt dann von vorne. Wurde allerdings ''Ja'' gedrückt, dann wird die if-Abfrage verlassen.
 +
  mv $hauptverzeichnis/tmp1/film.mpg "$clipspeicher"
 +
Der Videoclip wird gespeichert, wobei ein eventuell schon vorhandener Clip gleichen Namens überschrieben wird. Anschließend wird das Programm beendet mit einem Hinweis, welcher Clip gespeichert wurde.
  
 
=Hauptprogramm=
 
=Hauptprogramm=
 
==<font color="maroon"> Initialisierung </font>==
 
*''basisverzeichnis_festlegen'': Festlegen des Basisverzeichnisses
 
*''arbeitsverzeichnisse_erstellen'': Im Basisverzeichnis werden die Arbeitsverzeichnisse angelegt
 
*''programmerkennung'': Erkennung der notwendigen Helferprogramme
 
*''variablenzuweisungen'': zur besseren Lesbarkeit des Scriptes
 
*''konfiguration'': X.ini für ProjectX anlegen und einige Werte vordefinieren
 
*''loeschen_temporaere_arbeitsordner'': Definierten Anfangszustand herstellen
 
  
 
==<font color="maroon"> Hauptmenue </font>==
 
==<font color="maroon"> Hauptmenue </font>==
Mit Aufruf der Funktion hauptmenue () wird ein Aufgabenbereich gewählt. Entspechend dieses Aufgabenbereiches wird zu den Untermenues verzweigt.
+
Mit Aufruf der Funktion hauptmenue () wird ein Aufgabenbereich gewählt. Entspechend dieses Aufgabenbereiches wird (über case) zu den Untermenues verzweigt.
  
 
==<font color="maroon"> Untermenues </font>==
 
==<font color="maroon"> Untermenues </font>==
  
=== untermenue_video_dvd ===
+
Am Beispiel des Untermenues mit der Kennziffer 11 wird die Funktionsweise des Hauptprogramms gezeigt.
  
====<font color="gray"> Fernsehaufnahme schneiden und als Video-DVD brennen </font>====
+
*''filmauswahl'': Das gewünschte Videofile wird geladen
*''filmauswahl_dvd'': Das gewünschte Videofile wird geladen
 
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
*''requantisieren'': Passt der Film nicht auf eine DVD wird er requantisiert
 
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''authoring_ohne_menue'': Vom mpg-file wird die DVD-Struktur erstellt,
 
*''authoring_ohne_menue'': Vom mpg-file wird die DVD-Struktur erstellt,
*''abspielen'': noch einmal einer "Sichtprüfung" (mit optionaler Screenshot-Möglichkeit) unterzogen,
 
 
*''brennen_video_dvd'': um danach als Video-DVD gebrannt zu werden.
 
*''brennen_video_dvd'': um danach als Video-DVD gebrannt zu werden.
 
+
*''programmende'': Der Name sagt alles.
====<font color="gray"> Fernsehaufnahme schneiden und DVD-Struktur in Datei sichern </font>====
+
Das jeweils ausgewählte Untermenue wird über die case-Abfrage aufgerufen. Die Abarbeitung erfolgt dann schrittweise. Erst wenn eine Funktion beendet ist, wird die nächste gestartet.
*''filmauswahl_dvd'': Das gewünschte Videofile wird geladen
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
 
*''requantisieren'': Passt der Film nicht auf eine DVD wird er requantisiert
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''authoring_ohne_menue'': Vom mpg-file wird die DVD-Struktur erstellt,
 
*''abspielen'': noch einmal einer "Sichtprüfung" (mit optionaler Screenshot-Möglichkeit) unterzogen,
 
*''sichern_dvd_struktur'': um nun im Sicherungsverzeichnis gespeichert zu werden
 
 
 
====<font color="gray"> DVD-Struktur brennen </font>====
 
*''verzeichnisauswahl_dvd'': Aus dem Sicherungsverzeichnis wird eine gespeicherte DVD-Struktur geladen.
 
*''abspielen'': noch einmal einer "Sichtprüfung" (mit optionaler Screenshot-Möglichkeit) unterzogen,
 
*''brennen_video_dvd'': um danach als Video-DVD gebrannt zu werden.
 
 
 
=== untermenue_ts ===
 
 
 
====<font color="gray"> Fernsehaufnahme schneiden, TS als Daten-DVD brennen </font>====
 
*''filmauswahl_ts'': Das gewünschte Videofile wird geladen
 
*''pjx_ts_gui'': und mit ProjectX geschnitten und gewandelt nach TS,
 
*''brennen_ts'': um danach als Daten-DVD gebrannt zu werden
 
 
 
====<font color="gray"> Fernsehaufnahme schneiden, TS sichern </font>====
 
*''filmauswahl_ts'': Das gewünschte Videofile wird geladen
 
*''pjx_ts_gui'': und mit ProjectX geschnitten und gewandelt nach TS,
 
*''sichern_ts'': um nun im Sicherungsverzeichnis gespeichert zu werden
 
 
 
====<font color="gray"> gesichertes TS-file als Daten-DVD brennen </font>====
 
*''verzeichnisauswahl_ts'': Aus dem Sicherungsverzeichnis wird ein gespeicherter TS-Stream geladen,
 
*''brennen_ts'': um danach als Daten-DVD gebrannt zu werden
 
 
 
=== untermenue_videoclip ===
 
 
 
====<font color="gray"> DVB-Clip: Schneiden und speichern (Ton: MP2 normalisiert + AC3) </font>====
 
*''filmauswahl_clip'': Der gewünschte Videoclip wird geladen
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
 
'''normalisieren'': Der mp2-Ton wird normalisiert.
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''sichern_clip'': um nun im Videoclip-Verzeichnis gespeichert zu werden
 
 
 
====<font color="gray"> DVB-Clip: Schneiden und speichern (Ton: AC3) </font>====
 
*''filmauswahl_clip'': Der gewünschte Videoclip wird geladen
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
 
*''ac3_behalten'': Alle Tonspuren, die nicht "AC3" heißen, werden gelöscht.
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''sichern_clip'': um nun im Videoclip-Verzeichnis gespeichert zu werden
 
 
 
====<font color="gray"> DVB-Clip: Schneiden und speichern (Ton: MP2 normalisiert) </font>====
 
*''filmauswahl_clip'': Der gewünschte Videoclip wird geladen
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
 
*''mp2_behalten'': Alle Tonspuren, die nicht "mp2" heißen, werden gelöscht.
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''sichern_clip'': um nun im Videoclip-Verzeichnis gespeichert zu werden
 
 
 
====<font color="gray"> Mpeg1-Clip: Schneiden und speichern (Ton: MP2 normalisiert) </font>====
 
*''filmauswahl_clip'': Der gewünschte mpeg1-Videoclip wird geladen
 
*''pjx_demux_gui'': und mit ProjectX geschnitten und demultiplext
 
*''normalisieren'': Der mp2-Ton wird normalisiert.
 
*''multiplexen'': Bild und Ton werden nun wieder gemultiplexed.
 
*''sichern_clip'': um nun im Videoclip-Verzeichnis gespeichert zu werden
 
 
 
=== untermenue_dvd_direktdruck ===
 
Selbsterklärend. Siehe auch in der Bedienunganleitung.
 
 
 
=== untermenue_verwaltung ===
 
Hier werden die jeweiligen Scripte zum Löschen / Ändern / Deinstallieren aufgerufen. Das ist selbsterklärend.
 
  
 
{{blau|
 
{{blau|

Version vom 30. Januar 2009, 19:12 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.

Vorbereitungen

Voreinstellungen

hauptverzeichnis=~/dvb_wiki_script
ini_verz=~/.dvb_wiki_script

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

speed=8
dvdgroesse=4600000000

Hier 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. dort findet man auch die X.ini für ProjectX.
  • 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 der einer playlist für mplayer.
  • speed: Diese Geschwindigkeit wird maximal zum Brennen der DVD verwendet
  • dvdgroesse: An Hand dieser Größe wird entschieden, ob das Bearbeitungsergebnis auch auf eine einzige DVD passt.

Verzeichnisstruktur erstellen

mkdir $hauptverzeichnis 2>/dev/null
  • mkdir: Es wird ein Verzeichnis erstellt
  • $hauptverzeichnis: Der Verzeichnispfad wird aus der Variablen hauptverzeichnis geholt ( default: 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

In dieser Routine wird nachgesehen, ob die notwendigen Helferprogramme installiert sind. Und das funktioniert so:

Namen der notwendigen Helferprogramme

hilfsprogramm=( mplex dvdauthor ProjectX.jar normalize ffmpeg growisofs )

Die benötigten Helferprogramme werden als Array in der Variablen hilfsprogramm abgelegt.

Suchschleife

for var in ${hilfsprogramm[*]}
do
.....
done

Für jedes Element (var) im Array, also für jedes Helferprogramm wird die Suchschleife zwischen do und done einmal durchlaufen

Ini-Datei anlegen

touch $ini_verz/$var
  • touch: So noch nicht vorhanden, wird eine leere Datei erzeugt
  • $ini_verz/$var: und zwar im Initialisierungsverzeichnis. Die Datei erhält dann den Namen der gerade aktuellen Schleifenvariablen (z.B. mplex)

Pfad lesen

hilfsvar=`cat $ini_verz/$var`

Mit Hilfe von cat wird der Inhalt dieser Datei, die den Pfad zu dem entsprechenden Helferprogramm enthalten sollte (z.B. /usr/bin), in die Variable hilfsvar kopiert. In $hilfsvar steht also der Pfad zu dem Helferprogramm, dessen Name in $var steht.

Helferprogramm vorhanden?

if [ ! -e "$hilfsvar/$var" ]

Wenn die in den Variablen angegebene Datei (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 nach dem Helferprogramm 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 gefunden?

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 der Anzahl der gefundenen Pfade passiert folgendes:

  • 0): Anzahl 0, das Programm wurde nicht gefunden.

Nach einem Hinweis wird das Script beendet . Das fehlende Helferprogramm muß installiert werden..

  • 1): Anzahl 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.film enthält folgende Einstellungen (Voraussetzung ist ProjectX in der CVS-Version b28 oder größer)

  • Application.Agreement=1: Ja zur Lizenz
  • Application.Language=de: PJX startet auf deutsch
  • Application.ActiveDirectory=$hauptverzeichnis/screenshots: Damit kommen die Screenshots dahin, wohin sie sollen
  • CollectionPanel.Preview.SliderWidth=0: Der Vorschau-Slider bekommt dieselbe Breite wie das Vorschaufenster
  • WindowPosition.Main.Width=9999: Die Breite des PJX-Fensters wird maximiert
  • 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 Initialisierungsverzeichnis abgelegt, von wo sie bei Bedarf von ProjectX geladen wird.

Werden im PJX-Fenster irgendwelche Einstellungen verändert, so werden diese Änderungen nicht in die X.ini übernommen. Das wurde absichtlich so programmiert, damit man immer einen definierten Ausgangszustand hat.
Wird hier eine Speicherung gewünscht, kann dies durch einen zusätzlichen Eintrag in die X.ini erfolgen. Dann steht man allerdings vor dem Problem, oft nicht zu wissen, mit welchen Einstellungen PJX denn nun tatsächlich startet. Da es mir immer wieder so ging, kann ich nur raten, die Speicherung ausgeschalten zu lassen.

Playlist für mplayer erzeugen

find $videoclips/* > ~/.mplayer/playlist
  • find $videoclips/*: Die im Clipordner gespeicherten Videoclips werden gesucht.
  • ~/.mplayer/playlist: Deren Pfade werden in diese Textdatei gespeichert

Damit ist eine von mplayer verwendbare Playlist erzeugt worden

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

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

Die Funktion programmende () wird aufgerufen

funktionsabbruch ()

echo "$1"

Es wird der in $1 gespeicherte Text über die Konsole ausgegeben.

programmende

Die Funktion programmende () wird aufgerufen

In der Variablen $1 ist das gespeichert, was der Funktion bei ihrem Aufruf als Argument übergeben wurden. Beispiel:

funktionsabbruch "Heute scheint die Sonne"

Der "Sonnentext" wird der Funktion bei ihrem Aufruf ü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 fenster 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 diese Variable wird die Nummer der Antwort geschrieben.

Diese Nummer wird dann später vom Hauptprogramm ausgewertet.
Der per default aktivierte Eintrag der List wird durch das on festgelegt.

if [ $? != 0 ]
then
	benutzerabbruch
fi

Wenn im Auswahlfenster auf Abbrechen gedrückt wird, dann wird das Script beendet.

untermenue_video_dvd ()

Diese Funktion arbeitet analog zum Hauptmenue mit dem Unterscheid, daß die Antwortnummer in die Variable was_tun gespeichert wird.

Die weiteren Untermenues funktionieren ebenso.

°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 Brennpfad 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. Dieser String wird zur Dateisuche mit find in der nun aufgerufenen Funktion verzeichnisauswahl () benötigt.

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) wird 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 weis growisofs, 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 graphischer oberfläche (notwendig nur, wenn mit PJX geschnitten werden soll)
  • -ini $hauptverzeichnis/X.ini: mit dieser Initialisierungsdatei wird PJX gestartet.
  • -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 diese Dateien 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 alles 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 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 $hauptverzeichnis/X.ini: mit dieser Initialisierungsdatei wird PJX gestartet.
  • -out $hauptverzeichnis/tmp1: Hierhin wird das Bearbeitungsergebnis geschrieben

'-name film: Die Ausgabedatei erhält den Basisnamen "film"

  • $quelldatei:Dieser Stream wird verarbeitet

mpeg1_input ()

$ffmpeg -i "$quelldatei" $hauptverzeichnis/tmp1/film.mp2 -vcodec copy $hauptverzeichnis/tmp1/film.m1v
  • ${ffmpeg}: Aufruf von ffmpeg (z.B.: /usr/bin/ffmpeg),
  • -i ${quelldatei}: um diesen Video-Clip zu demultiplexen

Bearbeitung

normalisieren ()

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. 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. Ne, noch etwas gibts und das heißt AC3, zu Deutsch "Dolby digital"

Ton-Dateien vorbereiten

mv $hauptverzeichnis/tmp1/film.mp2 $hauptverzeichnis/tmp2
rm -- $hauptverzeichnis/tmp1/*.mp2

Normalisieren funktioniert sinnvoll nur mit mp2 Dateien, der Rest fliegt raus.

mp2 decodieren

$ffmpeg -i $hauptverzeichnis/tmp2/film.mp2 $hauptverzeichnis/tmp2/film.mp2.wav

Aus dem mp2-File wird mit Hilfe von ffmpeg ein wav-File gemacht.

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 ()

Es weden ausschließlich AC3-Tondateien zur Weiterverarbeitung bereitgestellt. Alles andere, was "Ton" heißt, wird gelöscht. Gibt es keinen AC3-Ton, dann bricht das Script nach einem Hinweis ab.

mp2_behalten ()

Es weden ausschließlich mp2-Tondateien zur Weiterverarbeitung bereitgestellt. Alles andere, was "Ton" heißt, wird gelöscht. Gibt es keinen mp2-Ton, dann bricht das Script nach einem Hinweis ab.

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 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.
if [ ! -e $hauptverzeichnis/tmp1/film.mpg ]
then
	funktionsabbruch "Es konnte keine Datei multiplext werden!"
fi

Wenn nicht demultiplext werden konnte (keine mpg-Datei im tmp1-Pfad), dann wird das Programm abgebrochen.

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 ein 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: In diesem Ordner: -o $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 Brenngeschwindigkeit
  • -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 der Rückmeldung von growisofs kann erkannt werden werden, ob die DVD bereit ist, Daten aufzunehmen. Das Tool gibt dann eine Null zurück. Dieser Rückgabewert kann über die Variable $? ausgewertet werden.

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 steht Null in $? und es wird mit dem nächsten Trocklauf zur DVD-Erkennung weitergemacht. Ist die DVD endlich bereit, dann wird das $? vom Tockenlauf (mit growisofs) Null, 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 If-Schleife passiert nun folgendes: Es erfolgt der schon von brennen_dvd () bekannte Trockenlauf zur DVD-Erkennung mit der Möglichkeit, den Vorgang abzubrechen. 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 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)
  • -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 if-Schleife solange DVDs angefordert, bis all Daten gebrannt sind.


Sichern

sichern_dvd_struktur ()

Diese Funktion sichert die DVD-Struktur

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.

mkdir $hauptverzeichnis/sicherung/$sicherungsordner

Hiermit wird der Sicherungsordner angelegt

mv $hauptverzeichnis/dvdstruktur/* $hauptverzeichnis/sicherung/$sicherungsordner

mv verschiebt die DVD-Struktur in den Sicherungsordner

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

In diesen Sicherungsordner wird die DVD-Struktur geschrieben. Der Name des Ordner wird aus dem aktuellen Datum und der momentanen Uhrzeit generiert.

mkdir ${sicherungs_pfad}/${sicherungsordner}

Hiermit wird der Sicherungsordner angelegt

mv $hauptverzeichnis/tmp1/*.ts $hauptverzeichnis/sicherung/$sicherungsordner

mv verschiebt die TS-files in den Sicherungsordner

funktionsabbruch "Datei gesichert nach $hauptverzeichnis/sicherung/$sicherungsordner. Programm beendet"

im Terminalfenster wird angezeigt, welche Datei wohin gesichert wurde Danach wird das Script beendet.

< sichern_clip ()

Diese Funktion speichert einen Videoclip

clipspeicher=`kdialog --title "$quelldatei" --getsavefilename $videoclips`
  • kdialog: Programmaufruf für kdialog (z.B. /usr/bin/kdialog)
  • --title "$quelldatei": Überschrift für das KDE-Fenster
  • --getsavefilename: Generiert ein KDE-Fenster, in dem ein Zielverzeichnis zum Speichern ausgewählt werden kann. Auch der Name, den der zu speichernde Clip bekommen soll, wird angegeben.
  • $videoclips: In dieses Verzeichnis wird bevorzugt gespeichert
  • clipspeicher=`....`: Der gewählte Name und Speicherpfad steht dann in dieser Variable zur Verfügung
if [ $? != 0 ]
then
	benutzerabbruch
fi

Damit wird die Abbruchtaste des KDE-Dialogs ausgewertet.

if [ -e "$clipspeicher" ]
then
......
fi

Existiert bereits ein Clip mit dem gleichen Namen, dann

kdialog --yesno "Dieser Clip ist schon gespeichert. Überschreiben?"

wird gefragt ob der Clip überschrieben werden darf.

if [ $? != 0 ]
then
	sichern_clip
fi

Wurde Nein gedrückt, dann wird die Funktion sichern_clip () erneut aufgerufen. Der Dialog beginnt dann von vorne. Wurde allerdings Ja gedrückt, dann wird die if-Abfrage verlassen.

mv $hauptverzeichnis/tmp1/film.mpg "$clipspeicher"

Der Videoclip wird gespeichert, wobei ein eventuell schon vorhandener Clip gleichen Namens überschrieben wird. Anschließend wird das Programm beendet mit einem Hinweis, welcher Clip gespeichert wurde.

Hauptprogramm

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.

Das jeweils ausgewählte Untermenue wird über die case-Abfrage aufgerufen. Die Abarbeitung erfolgt dann schrittweise. Erst wenn eine Funktion beendet ist, wird die nächste gestartet.


Das war's!


Vom DVB zur DVD, ein Wikibuch: Übersicht - Der Weg - Die Helferprogramme - Das Script - Installation - Bedienungsanleitung - Programmieranleitung



Zurück zur Multimedia-Übersicht