it's turtles all the way down
Tipps & Tricks
Images erstellen mit ddrescue
05. Jul
Einige Klassiker und ihre Schwächen
Nicht regelmäßig aber doch immer mal wieder ist man in der unschönen Situation, eine defekte CD, DVD oder gar Festplatte kopieren zu müssen. Wenn man ein Image des ganzen Mediums anlegen möchte, gibt es zunächst einmal das Tool dd. Von der Sicherung defekter Medien mit dd ist allerdings abzuraten: Zum einen ist dd nur sinnvoll zu verwenden, wenn verschiedene Parameter richtig gesetzt werden – ansonsten bricht dd beim ersten Fehler ab oder schreibt unbrauchbare Images. Zum anderen bietet dd aber schlicht einige Features nicht, die man bei der Datenrettung haben möchte: So lässt sich zwar angeben, wie viele Bytes jeweils in einem Rutsch gelesen werden sollen – wenn die Quelle aber defekte Sektoren hat, wird man diese Zahl eher gering ansetzen wollen. Dies führt aber dazu, dass der Auslesevorgang unnötig verlangsamt wird. Setzt man die Anzahl der gelesenen Bytes aber zu hoch, wird im Falle eines Lesefehlers auch gleiche diese (hohe) Anzahl an Bytes als defekt behandelt – es werden somit weniger Daten gerettet als möglich wäre. dd kann also nur schnell oder langsam – eine Unterscheidung zwischen defekten und lesbaren Sektoren gibt es nicht (ich bitte im Zweifelsfall um Verbesserung).
Eine Lösung ist das Programm dd_rescue (der Name des Paketes in den Paketquellen lautet ddrescue). Dieses Programm kopiert ein Medium, indem es zunächst große Blöcke einliest und kopiert – das ist schnell. Tritt nun ein Fehler auf, fällt dd_rescue in den Fehler-Modus zurück, in welchem lediglich kleine Blöcke gelesen werden – das ist langsamer, stellt aber sicher, dass nicht unnötig Daten als “defekt” verworfen werden. Treten über längere Zeit keine Fehler mehr auf, setzt dd_rescue die Blockgröße wieder hoch und beschleunigt somit die Datenrettung erneut. Damit eignet sich dd_rescue schon deutlich besser zur Rettung defekter Medien, ist aber – für sich genommen – noch nicht ganz optimal: Stellt man sich vor, dass eine Festplatte in der Mitte eine große Anzahl defekter Sektoren enthält, wird dd_rescue zunächst die lesbaren Daten am Anfang der Platte kopieren und dann viel Zeit dafür aufwenden, die defekten Sektoren in der Mitte im langsamen Fehler-Modus zu kopieren. Erst danach werden die lesbaren Daten am Ende der Platte kopiert. Es wird also viel Zeit dafür aufgewendet, möglicherweise ohnehin nicht mehr verwertbare Daten aus defekten Sektoren zu kopieren. Auf Grund der mechanischen Beanspruchung wird die Platte aber vielleicht schon beim aufwändigen und kleinteiligen Kopieren der defekten Sektoren endgültig das Zeitliche segnen. Die lesbaren Daten am Ende einer defekten Platte werden so unnötig gefährdet. Diese konzeptionelle Schwäche können erfahrene Nutzer eventuell umgehen, indem sie dd_rescue händisch mehrere Male laufen lassen und jeweils unterschiedliche Start-Positionen angeben oder die Rettung u.a. rückwärts laufen lassen. Auch zusätzliche Skripte wie dd_rhelp könnten das Verhalten von dd_rescue in dieser Hinsicht optimieren. Selbst der Autor von dd_rhelp empfiehlt aber inzwischen ein anderes Tool:
Antonio Diaz’ Programm ddrescue (ohne Unterstrich) aus dem Paket gddrescue ist eigentlich nichts anderes als eine konsequente Neukonzeption von dd_rescue, die die Funktionalität bietet, die dd_rescue nur in Ergänzung mit dem Skript dd_rhelp hatte: ddrescue liest zunächst das defekte Medium in großen Blöcken aus und schreibt die ausgelesenen Daten in das angegebene Ziel. Anders als dd_rescue liest ddrescue aber zunächst schnell über die defekten Sektoren hinweg und notiert das in einer Logdatei. Erst nachdem das ganze Medium so durchlaufen wurde, schaut sich ddrescue die defekten Sektoren erneut an: Es unterteilt die großen defekten Bereiche in mehrere kleine Bereiche und versucht dann diese kleinen “Häppchen” zu kopieren.
Durch dieses Vorgehen verwendet ddrescue zunächst seine Zeit darauf, die noch vorhandenen und lesbaren Daten eines Mediums zu retten. Erst am Ende dieses Vorgangs schaut sich ddrescue die womöglich ohnehin nicht mehr zu rettenden Daten an. Dieses Vorgehen kann gerade beim Kopieren defekter Festplatten ein enormer Vorteil sein: Jede Lesevorgang beansprucht die Mechanik zusätzlich und vermindert die Chance, wirklich die gesamte Festplatte auslesen zu können. Daher bietet es sich an, statt lange über defekte Sektoren zu rödeln zunächst die lesbaren Daten zu kopieren!
ddrescue hat aber noch andere Vorteile: Durch die Log-Datei kann eine Rettung jeder Zeit einfach abgebrochen und später fortgesetzt werden. Richtig genial (wenn auch sicher eher selten benötigt) ist dabei der Umstand, dass ddrescue auch ein funktionsfähiges Images aus mehreren defekten Datenträgern erstellen kann: Aus zwei DVDs mit identischem Inhalt kann ddrescue also ein funktionsfähiges Image erstellen! Auch im Alltag ist diese Funktion aber durchaus hilfreich: So kopiere ich meine defekten und verschmutzten DVDs zunächst mit ddrescue auf die Festplatte. Wenn dabei einige Datenbereiche nicht gelesen werden konnten, kann man seine DVD jetzt aus dem Laufwerk nehmen, (aggressiver) reinigen und es erneut versuchen: Durch die Logdatei “weiß” ddrescue genau, welche Daten beim ersten Durchlauf nicht kopiert werden konnten und schaut sich nur diese Bereiche auf der DVD erneut an. Bevor man seine DVD also mit Gewalt, Wasser und Schmierlappen bearbeitet: Erstmal das auslesen, was noch da ist und in einem zweiten Durchlauf die Lücken füllen.
Benutzung
ddrescue ist denkbar einfach zu benutzen. Beachten sollte man nur, dass man die Log-Datei bei jeder Verwendung selbst angeben muss. Gibt man keine Log-Datei an, wird auch keine angelegt und viele nützliche Features von ddrescue bleiben unzugänglich. Einen einfach Durchlauf startet man wie folgt:
sudo ddrescue -n /dev/sr0 rettungsimage.iso logdatei.log
/dev/sr0 ist dabei durch das zu rettende Laufwerk / Medium zu ersetzen. Das Image wird (naheliegend) in die Datei “rettungsimage.iso” geschrieben, das Log in “logdatei.log”. Dabei ist natürlich darauf zu achten, dass für jede Rettung eine eigene Logdatei verwendet wird.
Da ddrescue in seinem Log notiert, welche Blöcke defekt sind und welche defekten Blöcke nicht kopiert werden konnten, würde ddrescue bei einem weiteren Durchlauf erstmal gar nichts machen – im Log steht ja, dass die verbliebenen Blöcke nicht kopiert werden konnten. Um ddrescue zu einem neuen Versuch zu bewegen, müssen zunächst die defekten Sektoren als “ungetestet” markiert werden, um im Anschluss alle ungetesteten Blocks einem erneuten Test zu unterziehen:
sudo ddrescue -RT /dev/sr0 rettungsimage.iso logdatei.log
Jetzt wird ddrescue nur die vormals defekten Blöcke neu auslesen – und vielleicht retten können.
Fazit
Sicher lassen sich viele der beschriebenen Funktionen auch mit dd_rescue, dd_rhelp und sogar dd erreichen, wenn man die Tools gut zu bedienen weiß, viel Erfahrung im Umgang damit hat oder sich entsprechende Skripte geschrieben hat. ddrescue besticht aber dadurch, dass es all dies aus einer Hand bietet und keine (u.U. langsamen) Skript-Erweiterungen benötigt. Für eine einfache Datenrettung sind keine zusätzlichen Angaben durch den Benutzer nötig und die Überlegung, zunächst erstmal alle lesbaren Daten zu retten bevor man die defekten Sektoren auf Überlebende abklopft, ist sicher in sehr vielen Fällen die sinnvollere Strategie als das sequentielle Vorgehen.
Weitere Informationen
gibt es…
- …auf der sehr ausführlichen Info-Seite von ddrescue,
- …in diesem Artikel,
- …auf der Seite von dd_rhelp und
- …in diesem Foren-Beitrag.
Hinweis
stfischr hat mich auf meine vorschnelle Editierung des Artikels hingewiesen, weswegen ich die ursprüngliche Version wiederhergestellt habe.
In der vorherigen Version des Artikels hatte ich behauptet, dass eine Rettung zunächst mit dem Schalter “-n” angestoßen werden sollte und erst in einem zweiten Durchgang darauf verzichtet werden könne. So wie sich die Sache mir jetzt darlegt, ist das nicht zutreffend und ein Durchlauf ohne irgendwelche Schalter erfüllt bereits seinen Zweck. An dieser Stelle nochmal besten Dank an stfischr für die Korrektur!
Archos Vision und Ubuntu
07. Jun
Der neue MP3-Player im Hause hört auf den schönen Namen “Archos Vision A14VG” und ist ein eher kleiner und leichter Vertreter seiner Zunft. Nachdem mir im Laden versichert wurde, dass sich das Gerät ganz normal ins Dateisystem einbindet, musste ich hier aber feststellen, dass genau das nicht der Fall ist.
Allerdings wurde das Gerät prinzipiell als Laufwerk erkannt, es gab einen neuen Eintrag unter “/dev/sdb” was darauf schließen ließ, dass etwas mit der Formatierung / Partitionierung des Players nicht stimmte. GParted bestätigte diese Vermutung, so dass ich mit dd eine Sicherheitskopie von /dev/sdb angefertigt und den Archos Vision mit Fat32 neu formatiert habe.
Wie erwartet legt das Gerät beim nächsten Start automatisch die erforderliche Verzeichnisruktur an, so dass in dieser Hinsicht keine Probleme entstehen. Danach wurde der Archos ohne Probleme eingebunden und ließ sich mit Musik bespielen.
Ich übernehme natürlich keine Gewähr dafür, dass Neuformatierung euren Player nicht in einen (sehr leichten) Briefbeschwerer verwandelt. Aber für mich war das Problem damit behoben.
cURL
17. Mai
Ich benutze curl in der Regel als eine Art “Internet cat”: Damit kann man beispielsweise schnell den HTML-Code einer Seite nach einer beliebigen Information durchsuchen – hier etwa meiner IP:
curl -s http://www.wieistmeineip.de/|egrep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"
Mit curl kann man sich aber nicht einfach nur Internetseiten im Terminal ausgeben lassen: Auch einfache Interaktionen via POST sind möglich. So nutze ich curl beispielsweise, um mich bei meinen Router anzumelden und dort die Verbindung mit dem ISP zu trennen und neu aufzubauen.
Worauf ich erst vor ein paar Tagen gestoßen bin und was mir sehr gut gefällt: curl unterstützt auch Gruppen und Bereiche von URLs. So würde mir folgender Befehl nacheinander die Seiten eins.html, zwei.html und drei.html auf example.com anzeigen:
curl http://example.com/{eins,zwei,drei}.html
Bereiche werden wie folgt definiert:
curl http://example.com/[1-3].html
Ein Bereich wie [1-50:5] definiert dabei einen Schrittzähler: Hier wird also nur jede fünfte Seite angezeigt 1, 6, 11, … 46. Auch Bereiche von Buchstaben können angegeben werden.
Das Ganze kann beispielsweise dann äußerst hilfreich sein, wenn man sich mal wieder durch eine grottenschlechte HTML-Bildergalerie klicken muss. Anstatt sich mit jedem Klick etwas mehr zu ärgern, befördert man die Bilder in einem Rutsch auf den lokalen Datenträger und betrachtet sie dort mit dem Bildbetrachter des Vertrauens. Zur Veranschaulichung habe ich im Rahmen dieses Artikels einmal 50 kleine Bildchen erstellt. Mit folgendem Befehl laden wir diese direkt auf die heimische Festplatte:
curl -s www.xn--ngel-5qa.de/wordpress/wp-content/uploads/2010/05/wp_bilder/[1-50].png -o test/bild_#1.png
In diesem Fall wird im aktuellen Verzeichnis ein Ordner test angelegt, in dem die Bilder gespeichert werden. Neu ist hier der Parameter -o, mit dem die Ausgabe von curl in eine Datei umgeleitet wird. Die Zeichenkette “#1″ wird dabei von curl durch die jeweilige Bild-Nummer ersetzt.
Insgesamt ist curl ist recht mächtiges Tool, dessen Einsatzbereiche sich nicht auf http beschränken. So verbindet sich curl auch mit FTP oder gar IMAP-Servern und kann (anders als wget) Dateien auch hochladen.
Änderung: Die Beispiele sollten jetzt Copy&Paste-kompatibel sein.
Wine + Office
02. Mai
Bisweilen kommt man ja nicht umhin Microsofts Office zu nutzen, weil man .doc-Dateien erstellen muss, die beim Empfänger ohne Formatierungsfehler angezeigt werden.
Da Office unter Linux aber nur in einer Wine-Umgebung läuft, kann man nicht wie gewohnt die Datei einfach an das ausführende Programm übergeben: Man muss zunächst den Pfad der Datei an die Wine-Umgebung anpassen – das Ergebnis könnte wie folgt aussehen:
z:\home\benutzer\dokumente\arbeit\123.doc
Außerdem möchte man unter Umständen auch noch eine WINEPREFIX-Angabe setzen. Kurzum: Ein Skript muss her:
#!/bin/sh # DIE NÄCHSTEN BEIDEN ZEILEN SOLLTEN ANGEPASST WERDEN PREFIX=~/.wine/officesp1 EXEC_PATH=~/.wine/officesp1/drive_c/Programme/Microsoft\ Office/Office12/WINWORD.EXE wine_path=$(WINEPREFIX=$PREFIX winepath -w "$@") WINEPREFIX=$PREFIX wine "$EXEC_PATH" "$wine_path"
Dieses kleine Skript wandelt den Pfad der übergebenen Datei um, ruft Wine mit entsprechendem Prefix auf und übergibt Office die Datei. Das Ganze kann dann beispielsweise unter /home/BENUTZER/.wine/open.sh abgelegt und ausführbar gemacht werden. Um nun eine beliebige .doc-Datei zu öffnen, wählt man in deren Kontextmenü einfach Öffnen mit…->Andere Anwendungen aus und gibt die oben erstellte open.sh an. Der Dateiname kann natürlich auch angepasst werden – “MS Word” wäre vermutlich ein eindeutigerer Name.
Mit diesem Skript lassen sich problemlos mehrere Dateien gleichzeitig öffnen und auch Leerzeichen stellen kein Problem dar.
Abstürzende Mediaplayer
10. Apr
Unter verschiedenen Linux-Distributionen kann es unter bestimmten Umständen dazu kommen, dass Mediaplayer abstürzen, wenn sie in den Vollbildmodus geschaltet werden. Teilweise passiert das sogar, wenn man das Fenster des Mediaplayer nur vergrößert.
Üblicherweise spuckt die Konsole eine Fehlermeldung wie diese aus:
BadAlloc (insufficient resources for operation)
Das Problem tritt anscheinend nur in Verbindung mit Compiz auf: Das Abschalten der Fenstereffekte kann das Problem also beheben. Wer auf wackelige Fenster & Co nicht verzichten möchte, kann das Problem beheben, indem er die Videoausgabe verändert.
Für den VLC:
Unter Extras->Einstellungen->Video die Option Ausgabe auf “X11-Videoausgabe” ändern.
Für Totem und viele mehr:
Programme, die auf GStreamer basieren (Totem etwa), lassen sich über das Programm gstreamer-properties konfigurieren. Im Reiter Video wählt man als Plugin im Bereich Default Output “X Window System (Kein XV)”.
Danach sollten die Videos in den genannten Programmen problemlos mit Compiz harmonieren.
Upload aus dem Kontext-Menü
05. Apr
Dieses Skript lädt die ausgewählten Dateien auf einen FTP Server. Angepasst werden müssen:
FTP-Server: Der zu nutzende FTP-Server
Server: Der gleiche Server – über HTTP
sowie
BENUTZERNAME (selbsterklärend).
Das Passwort wird jeweils vorher abgefragt. Wie zuvor wird das Paket zenity benötigt, ebenso das Paket wput.
#!/bin/sh paths=$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS selected=$NAUTILUS_SCRIPT_SELECTED_URIS cur=$NAUTILUS_SCRIPT_CURRENT_URI if ! PASS=$(zenity --entry --hide-text --text "Bitte geben Sie das Passwort ein:" --title "Und das Passwort?"); then exit; fi for x in $selected do name=$(echo $x|sed 's/file:\/\///') timestamp=$(date +%s.%N) #lastchar=$(echo $name|tail -c 5) nn=$(echo $name|awk -F/ '{print $NF}') output="$timestamp-$nn" wput "$name" ftp://BENUTZERNAME:$PASS@FTP-SERVER/bilder/$output error=$? uri=http://SERVER/bilder/$output if [ $error != 0 ] then zenity --info --text "Fehler beim Hochladen der Datei $name" --title "Fehler" else zenity --info --text "Datei $name erfolgreich hochgeladen\nUrl:\t $uri" --title "Abgeschlossen" fi done
Wie schon zuvor gilt: Abzulegen ist das Ganze in einer ausführbaren Datei im Verzeichnis ~/.gnome2/nautilus-scripts.
FourCC mit Nautilus-Skript ändern
04. Apr
#!/bin/sh paths=$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS selected=$NAUTILUS_SCRIPT_SELECTED_URIS cur=$NAUTILUS_SCRIPT_CURRENT_URI fourcc=$(zenity --entry --text "Geben sie den neuen FOURCC ein") for x in $selected do name=$(echo $x|sed 's/file:\/\///') cfourcc -u $fourcc $name done
Abzulegen ist das Ganze in einer ausführbaren Datei im Verzeichnis ~/.gnome2/nautilus-scripts. Benötigt werden die Pakete cfourcc und zenity
pyConnect
03. Apr
Da ich in letzter Zeit doch öfter mal meinen Router neu starten musste, habe ich mich nach Möglichkeiten umgesehen, dies automatisiert zu tun. Auf dieser Seite finden sich dazu sehr einfache Skripte für dutzende von Routern.
Mit etwas Python drumherum erhält man auch direkt Rückmeldung darüber, in welchem Zustand sich die Verbindung gerade befindet:
#!/usr/bin/env python # coding:utf-8 import subprocess from pynotify import init, Notification import sys IP="192.168.2.123" pwd="PASSWORD" user="USERNAME" # For information how to restart your router, # visit: # # http://www.paehl.de/reconnect init("PyConnect") class main(object): def __init__(self): self.notification = None def go(self): self.notify(message="Loging in") subprocess.Popen('curl -sS "http://%s/cgi-bin/login.exe" -d "user=%s&pws=%s" 1>/dev/null' % (IP, user, pwd), shell=True).wait() self.notify(message="Disconnecting") subprocess.Popen('curl -sS "http://%s/cgi-bin/statusprocess.exe" -d "pvc=0&cur_if=11&disconnect.x=102&disconnect.y=5&disconnect=Reconnect" 1>/dev/null' %IP , shell=True).wait() self.notify(message="Connecting") subprocess.Popen('curl -sS "http://%s/cgi-bin/statusprocess.exe" -d "pvc=0&cur_if=3&connect.x=47&connect.y=10&connect=+Verbinden+" 1>/dev/null' % (IP), shell=True).wait() self.notify(message="Done") def notify(self, title="pyConnect", message=""): if not self.notification: self.notification = Notification(title, message) else: self.notification.update(title, message) self.notification.show() prog = main() prog.go()
configparser gone pythonic
22. Mrz
Zum Lieferumfang von Python gehört ja auch der ConfigParser. Mit dieser Bibliothek lassen sich Konfigurationsdateien erstellen, lesen und bearbeiten, was gerade im Linux-Umfeld ja eine durchaus nützliche Sache ist (wenngleich natürlich nicht alle Konfigurationsdateien dem selben Standard gehorchen). Wer seinen Nutzern aber schnell und unkompliziert die Möglichkeit bieten möchte, bestimmte Verhaltensweisen seines Programms zu beeinflussen, bekommt mit dem ConfigParser ein nützliches Werkzeug dazu an die Hand.
Es geht aber noch besser, wie ich gerade festgestellt habe. Mit ConfigObj lassen sich noch einfacher und pythonischer Konfigurationsdateien bearbeiten. Dazu wird die jeweilige Konfig-Datei auf ein verschachteltes Dictionary abgebildet. Ein Aufruf könnte entsprechend so aussehen:
config["Section1"] = {}
config["Section1"]["OptionA"] = “Mein Wert”
Was mir daran besonders gefällt: Statt mit irgendwelchen config.has_section(“Section1″) oder section.has_option(“OptionA”) Aufrufen fragt man ganz bequem und python-intuitiv “Section1″ in config oder “OptionA” in section und erhält die gewünschte Antwort.
ConfigObj bietet darüber hinaus natürlich noch einige Möglichkeiten, wie etwa verschachtelte Sektionen. Was mich aber besonders zum Umstieg bewogen hat, ist der Umstand, dass ConfigObj die Kommentare in den Konfigurationsdateien belässt. ConfigParser hat dahingegen die lästige Angewohnheit, Kommentare beim Schreiben und Aktualisieren von Konfigurationsdateien zu entfernen. Eine Möglichkeit, dieses Verhalten zu ändern, habe ich bisher nicht aufgetan.
Wie auch immer: Dank der intuitiven Syntax lassen sich bestehende Programme leicht auf ConfigObj migrieren. Ich konnte zumindest mit wenigen Zeilen Code meine bestehende ConfigParser-Schnittstelle auf ConfigObj umbiegen.
TV-Karte trifft auf GStreamer
20. Mrz
Im dritten Teil dieser kleinen Serie schauen wir uns mal das Zusammenspiel von GStreamer und einer TV-Karte oder Webcam an.
GStreamer ist ein Multimedia-Framework, das in vielen Programmen Anwendung findet – etwa in Totem, Exaile, Banshee, OGG Convert oder Ubuntus zukünftigem Standard-Videoeditor PiTiVi. Sogar in meinem Pyjama
. Gerade unter GNOME ist GStreamer das Media-Framework schlechthin.
Entsprechend sollte es eigentlich nicht wundern, dass GStreamer ohne Probleme auf die V4L2-Schnittstelle zugreifen kann. Im Rahmen dieses Eintrages werde ich auch versuchen, ein paar Grundlegende Fähigkeiten von GStreamer zu beschreiben – es ist anfangs gar nicht so leicht, sich in dieses Gebiet einzuarbeiten.
Videowiedergabe
Grundsätzlich kann man bei GStreamer 3 Arten von Elementen unterscheiden: Source-Elemente kümmen sich um die Eingabe und lesen beispielsweise eine Datei. Filter-Elemente verarbeiten diese Daten, indem sie diese etwa kodieren. Die sogenannten Sink-Elemente kümmern sich schließlich um die Ausgabe und schreiben die Daten beispielsweise in eine Datei. Schauen wir uns einfach mal diesen Befehl zur Videowiedergabe an:
gst-launch-0.10 v4l2src device=/dev/video0 ! video/x-raw-rgb,width=640,height=480 ! ffmpegcolorspace ! xvimagesink
Hier wird schon deutlich, dass GStreamer in Pipes organisiert ist. Das Programm gst-launch-0.10 erlaubt es dabei, selbst komplexe GStreamer-Pipes zu testen, ohne tatsächlich irgendwelchen Code schreiben zu müssen. Hier werden die einzelnen Elemente mit Rufzeichen miteinander verbunden. Eigentlich ist dieser Befehl aber nur zum Testen gedacht: Für richtige Programme bietet GStreamer andere Schnittstellen, so dass auch Laufzeit-Interaktion möglich ist.
Im obigen Beispiel liest das Plugin v4l2src Daten aus der angegebenen Quelle. Diese werden dann an das nachfolgende Element weitergegeben – und in diesem Fall auf 640×480 Pixel skaliert. Das nächste Element ffmpegcolorspace konvertiert die Videodaten in den richtigen Farbraum und xvimagesink gibt schließlich das Bild aus.
Das Ganze mit Ton
Bisher haben wir leider nur Video und keinen Ton. Mit folgendem Befehl lässt sich das ändern:
gst-launch-0.10 v4l2src device=/dev/video0 ! video/x-raw-rgb,width=640,height=480 ! ffmpegcolorspace ! xvimagesink osssrc device=/dev/dsp ! osssink
Hier wird eine zweite Pipe eingerichtet, die sich um die Audioausgabe kümmert. Das Element osssrc liest nun Audiodaten vom Geät /dev/dsp. In diesem Fall haben wir keine Filter-Elemente zwischengeschaltet – die Daten werden sofort an den osssink weiter- und damit ausgegeben. Die beiden Abschnitte dieses Befehls sind dabei voneinander völlig unabhängig. Sowohl die Pipe
v4l2src device=/dev/video0 ! video/x-raw-rgb,width=640,height=480 ! ffmpegcolorspace ! xvimagesink
als auch die Pipe
osssrc device=/dev/dsp ! osssink
sind vollständig lauffähig. Nicht unterschlagen werden soll, dass es sei bei dem “video/x-raw-rgb…”-Element nicht im strengen Sinne um ein Element handelt: Intern wird es erst zu einem Capsfilter-Element umgewandelt. Für uns ist das hier aber zunächst nicht weiter wichtig.
Einmal speichern bitte!
Wer die Audio- und Videodaten nun speichern möchte, sollte sich folgenden Befehl einmal näher ansehen:
gst-launch-0.10 v4l2src device=/dev/video0 ! queue ! video/x-raw-rgb,width=640,height=480 ! ffmpegcolorspace ! theoraenc ! queue ! oggmux name=mux osssrc device=/dev/dsp ! queue ! audioconvert ! vorbisenc ! queue ! mux. mux. ! queue ! filesink location=video.ogg
Wie gehabt werden hier zunächst Videodaten ausgelesen, skaliert und farbkonvertiert. Das neue Element theoraenc kodiert die Daten. Wie wir später noch sehen werden, kann hier genauer spezifiziert werden, in welcher Qualität die Kodierung erfolgen soll. Das Element oggmux packt die kodierten Daten schließlich in einen OGG-Datenstrom, der den Namen “mux” erhält.
Der zweite Abschnitt dieser Pipeline wird durch das Source-Element osssrc eingeleitet. audioconvert wandelt die Raw-Audiodaten zur Weiterverarbeitung um, vorbisenc komprimiert das Ganze mit dem OGG-Vorbis-Encoder. Die Daten aus diesem Vorgang fließen über ein Queue-Element in den OGG-Muxer, den wir zuvor ja “mux” getauft haben. Das war der zweite Abschnitt unserer Pipeline.
Im letzten Teil werden nun die Daten aus “mux” – wieder über einen Queue – an filesink übergeben. Wie der Name schon andeutet, kümmert sich dieser Sink darum, die Daten in eine Datei zu gießen. Das etwas irritierende Element “! mux. mux. !” besteht also tatsächlich aus zwei Elementen: Das erste “mux” fungiert als Ziel für die komprimierten Audiodaten. Da “mux” ja der Name des OGG-Muxers ist, werden diese Audiodaten hier also mit den Videodaten “gemultiplext” – sprich: Zusammen in einen Datenstrom gepackt. Das zweite “mux” leitet einen neuen Abschnitt unserer Pipeline ein: Es fungiert hier also als Source-Element und gibt die Daten an das filesink weiter.
Die Queues sind übrigens immer da gefordert, wo ein nachfolgendes Element potenziell “langsamer” ist, das aktuelle: Um Aussetzer in Ton und Bild zu vermeiden, wird so schlicht ein Puffer zwischengeschaltet. Besonders, wenn ihr feststellt, dass eine GStreamer-Pipeline in eurer Programm-Implementierung stuckt und springt, fehlen sehr wahrscheinlich Queues an der richtigen Stelle.
Sehen, hören und speichern
Jetzt wollen wir die ganzen Einzelschritte einmal zusammenbringen. Folgender Aufruf sieht schon wirklich mächtig aus:
gst-launch-0.10 v4l2src device=/dev/video0 ! tee name=videoout ! queue ! video/x-raw-yuv,width=640,height=480 ! queue ! theoraenc quality=30 ! muxout.
osssrc device=/dev/dsp ! tee name=audioout ! queue ! audio/x-raw-int,rate=44000 ! queue ! audioconvert ! vorbisenc ! muxout.
oggmux name=muxout ! filesink location=media2.ogg
videoout. ! queue ! ffmpegcolorspace ! xvimagesink
audioout. ! queue ! osssink
Zur besseren Übersicht habe ich die jeweiligen Abschnitte einmal voneinander getrennt. Eigentlich ist das aber eine zusammenhängende Befehlszeile!
Der erste Abschnitt ähnelt den bisher besprochenen Abschnitten. Neu ist das Element tee: Es dupliziert den Stream – wie das tee in der Linux-Konsole. So können wir später über den Namen “videoout” auf eine Kopie des Videostreams zurückgreifen. Nach einem tee-Element ist immer ein Queue-Element erforderlich. Es folgen weitere bekannte Elemente und schließlich wird der Stream an ein Element mit dem Namen “muxout” übergeben. Das es sich dabei nur um den Namen eines anderen Elementes handelt, erkennt man an dem nachgestellten Punkt. Für uns ist hier erstmal nur wichtig, dass wir den Stream gewissermaßen “zwischengeparkt” haben.
Im zweiten Abschnitt wird parallel für den Audiostream verfahren. Die meisten Elemente sind bekannt, auch hier wird eine “Kopie” mit tee erstellt und auch dieser Stream wird in “muxout” zwischengeparkt.
Der dritte Abschnitt bringt Licht ins Dunkel: “muxout” ist der OGG-Mixer. Er multiplexiert Audio- und Videodaten und gibt das Resultat an den filesink weiter, der das Ganze speichert. Bis hierher ähnelt das Beispiel sehr dem vorherigen Beispiel in “Einmal speichern bitte!”. Neu ist lediglich das Element tee und die Verwendung des Multiplexers. Wann und wo man den Multiplexer “definiert”, ist hier aber eigentlich egal: Man kann auch – wie hier – zunächst einen Stream an einen Element-Namen leiten und diesen erst später einem Element zuweisen.
In Abschnitt 4 wird der Video-Stream wie gewohnt ausgegeben. Neu ist lediglich, dass hier nicht eine Datei oder ein Gerät als Source dient, sondern eben das Element “videout.“, das wir zuvor mit tee definiert als Kopie des Streams definiert haben.
Im Abschnitt 5 wird mit “audioout.” parallel verfahren.
Fazit
GStreamer stellt Einsteiger meines Erachtens zunächst vor große Hürden. Das einfache Wiedergeben eines schnöden Videos kann dabei durchaus schon einige Kopfschmerzen bereiten. Was aber wirklich begeistert, ist die Vielzahl an Möglichkeiten, die man mit GStreamer hat. So ist es sogar ohne große Probleme möglich, Bluebox-Effekte mit GStreamer zu erzeugen – und das finde ich schon recht imposant. Weiterhin profitiert man als Programmierer von der Vielzahl der unterstützten Codecs. So ist es sicher nicht verwunderlich, dass unter GNOME so viele Programme auf GStreamer zurückgreifen.
Letzte Kommentare