ubuntuusers.de

Ordner auf neue Dateien überwachen und verarbeiten

Status: Ungelöst | Ubuntu-Version: Ubuntu 14.04 (Trusty Tahr)
Antworten |

Serengeti

Avatar von Serengeti

Anmeldungsdatum:
24. Februar 2008

Beiträge: 1961

Hallo zusammen

Ich nutze ein ubuntu 14.04 als tvheadend server. warum auch immer aber ich muss die Aufnahmen als "MPEG-TS Pass-through" erstellen ansonsten sind die Aufnahmen nicht komplett.

Ich möchte nun den Aufnahmen Ordner überwachen und bei Ankunft einer neuen Datei diese automatisch in ein handlicheres Dateiformat Konvertieren. dafür nutze ich

1
nice -n 14 ffmpeg -i in-file.ts -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn out-file.mkv

wie kann ich diese Befehlszeile für jede Datei in einem Ordner und dessen Unterordner ausführen lassen?
Wie kann ich nur wenn die Konvertierung die ganze Datei konvertieren konnte das Original löschen lassen?

Benno-007

Anmeldungsdatum:
28. August 2007

Beiträge: 29240

Wohnort: Germany

Du beschreibst damit drei additive Anforderungen, die sich nicht gegenseitig aufheben sollen, korrekt?

1. Ordner auf neue Dateien überwachen und verarbeiten

2. "kann ich diese Befehlszeile für jede Datei in einem Ordner und dessen Unterordner ausführen lassen"

3. "Wie kann ich nur wenn die Konvertierung die ganze Datei konvertieren konnte das Original löschen lassen?"

Vorbereitungen/ Beispiele zu 1.:

sudo apt-get install inotify-tools
inotifywait -mr /home
inotifywait -mr --excludei mtab /etc

Könnte am Ende etwa so aussehen (ORDNER einsetzen):

1
2
3
4
5
6
7
8
9
cd ORDNER
while true; do
for datei in */*.ts; do
  if  nice -n 14 ffmpeg -i "$datei" -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn out-file.mkv; then
    echo rm "$datei"
  fi
done
sleep 10m
done

Annahme: Es existiert nur max. ein Unterordner und es geht nur um .ts-Dateien. Zunächst wird der Löschbefehl nur ausgegeben. Soll er tatsächlich ausgeführt werden, das echo vor rm entfernen. Das wird nun alle 10 min erneut überprüft, wenn du das als Script in den Autostart legen würdest. Dann braucht es also also nicht mal inotify, es sei denn, es soll instantan erfolgen und die Schleife nicht dauernd aufgerufen werden.

Das geht auch nur, weil wir die ts-Datei gleich danach löschen. Und wenn eine mit Fehler auftritt, wird es an ihr alle 10 min wieder versucht. Beide Probleme (das eine hier nur fiktiv) kann man mit inotify eindämmen, indem nur neue Dateien geprüft werden (ab dem Zeitpunkt, wo der Server mit dem Script läuft).

Mit inotify:

Da müsste man dann erst einmal einen Durchlauf mit den alten Dateien machen, ggf. einmalig:

1
2
3
4
5
6
cd ORDNER
for datei in */*.ts; do
  if  nice -n 14 ffmpeg -i "$datei" -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn out-file.mkv; then
    echo rm "$datei"
  fi
done

Danach inotify auf die Lauer schicken (das fertige Beispiel in der man ist sehr gut!):

1
2
3
4
5
6
7
8
cd ORDNER
while inotifywait -r -e modify .; do
for datei in */*.ts; do
  if  nice -n 14 ffmpeg -i "$datei" -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn out-file.mkv; then
    echo rm "$datei"
  fi
done
done

Beide Varianten sind noch ungetestet - nur als Anregungen zu verstehen. Dafür aber immerhin mehr oder minder fertig ausgearbeitete.

Jetzt könnte man in dem letzten Codeblock noch versuchen, die ineffiziente Suche nach */*.ts rauszuwerfen, indem man dessen --format %f Option nutzt. Aber das mit inotify haut sowieso noch nicht hin, beim Ordner findet es gerade meine Testdatei nicht und es würde ja auch unendlich weiterlaufen und ohne -m bei der ersten Datei beenden, müsste also in die Endlosschleife mit rein.

Aber man kann ja, wie gesagt, drauf verzichten. Ich schick's nun nur erst mal ab und später sehen wir hier alle weiter. Meine ersten Beispiele für inotifywait funktionierten jedenfalls immer, falls man da was draus machen wöllte. Ich schau mir auch mal kurz inotifywatch an, auch interessant, für Statistiken der Zugriffe.

Grüße, Benno

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Das Event "modify" bietet sich überhaupt nicht an, weil das mehrfach vorkommen kann! Es ist besser, auf das Event "close" zu warten, da zwischen Eintrag der Datei ins Verzeichnis und Beenden des Schreibens reichlich Zeit liegen kann. Man muss auch nicht das Verzeichnis wechseln. Mein Vorschlag:

1
2
3
4
5
while file="$(inotifywait -r -e close --format %w%f -q ORDNER)"; do
  nice -n 14 ffmpeg -i "$file" -map 0:0 -map 0:1 \
    -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn "${file%.*}-out.mkv" \
  && rm "$file"
done

Man kann auch noch Ausschluss-Filter für Dateinamen setzen. Siehe Manpage.

Benno-007

Anmeldungsdatum:
28. August 2007

Beiträge: 29240

Wohnort: Germany

So, hab den letzten Block nochmal übearbeitet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
cd ORDNER
inotifywait -mre create . --format %f -o files &
while true; do
files="($(xargs -a files))"
files_count_before="$(echo ${#files[@]})"
for datei in ${files[@]}; do
  if  nice -n 14 ffmpeg -i "$datei" -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn out-file.mkv; then
    echo rm "$datei"
  fi
done
files_count_after="$(echo ${#files[@]})"
if [ "$files_count_before" -eq "$files_count_after" ]; then
  rm files
else # kann hier nur größer geworden sein...neue Elemente für neuen Durchlauf retten
  #files_new=...
fi
done

Da sind auch noch kleinere Fehler drin, z.B. wird ja bei der */*.ts-Variante beim Löschen angenommen, dass die Datei in ORDNER läge - ORDNER/* wird ja gar nicht geprüft. Mit der inotifywait-Variante fiele das zwar weg, aber dafür hab ich noch keine korrekte Lösung für das Löschen der Datei files bzw. dessen Variable files ausgearbeitet:

Ich lösche nun in der vorletzten Zeile die Datei, aber zwischenzeitlich neue Dateien beim Konvertieren würden damit auch entfernt, ohne zuvor für den nächsten Durchlauf herübergerettet worden zu sein. Das hab ich aber nun mit filesdiff im Griff. Naja, nicht ganz. Wie ich sehe, ging es schon weiter. Hatte übrigens dann auf event create gewechselt. Aber ist bei Videos natürlich auch blöd. Die drittletzte Zeile lässt das mal in einem Trümmerhaufen offen - da sitz ich noch länger dran, aber wenn hier nun eine Lösung ist, muss ich sehn, ob ich da noch weiter dran rumfriemele. Mal wieder den Zeitaufwand schön unterschätzt. 🙄

Serengeti

(Themenstarter)
Avatar von Serengeti

Anmeldungsdatum:
24. Februar 2008

Beiträge: 1961

Vielen vielen Dank für deine Mühe. Ich bin jetzt erst mal etwas damit beschäftigt zu verstehen. Bevor ich mich daran wage. Das sieht aber wohl schon besser aus als ich es mir erhofft hatte. Ich war schon darauf gefasst cronjobs durchlaufen zu lassen.

Es ist richtig dass es bei mir nur Sendungsspezifische Ordner gibt, also keine mehrfache Unterordner. Auch sind alle Dateien mit der Endung .ts versehen.

[EDIT]

@Benno-007 Ich sehe, dass TVheadend beim Anlegen der Datei nicht alles sofort schreibt sondern eine Datei kontinuierlich füllt. Könnte hier das von rklm angesprochene Problem für

1
inotifywait -mre create

eine rolle spielen?

Wobei es eigentlich kein Problem sein könnte, da die .ts Datei schneller mit Inhalt gefüllt wird als es ffmpeg am Ende schafft die Daten zu konvertieren.

Benno-007

Anmeldungsdatum:
28. August 2007

Beiträge: 29240

Wohnort: Germany

Ja. 😉

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Meine Lösung hat auch ein Problem: es können Ereignisse verloren gehen, da der inotifywait immer beim ersten Event beendet wird. Man könnte das so besser machen:

1
2
3
4
5
inotifywait -r -e close --format %w%f -q -m ORDNER | while read file; do
  nice -n 14 ffmpeg -i "$file" -map 0:0 -map 0:1 \
    -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn "${file%.*}-out.mkv" \
  && rm "$file"
done

Ggf. kann man einfach die ganze Kette von nice ab in den Hintergrund schicken. Gefahr ist natürlich, dass dann mehrere Jobs parallel laufen.

Serengeti

(Themenstarter)
Avatar von Serengeti

Anmeldungsdatum:
24. Februar 2008

Beiträge: 1961

Kann es trotz hohem nice-wert problematisch sein wenn mehrere Jobs gleichzeitig aktiv sind?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Serengeti schrieb:

Kann es trotz hohem nice-wert problematisch sein wenn mehrere Jobs gleichzeitig aktiv sind?

Die Anzahl der Prozesse könnte zu hoch werden, es könnte zu viel Speicher verbraucht (oder sogar geswappt werden) oder durch die vielen Prozesse nimmt die Anzahl der Kontextwechsel zu, was die Sache insgesamt weniger effizient macht. Das hängt alles vom Einzelfall ab, sprich, wie schnell neue Dateien geschrieben werden und wie lange die Verarbeitung im Schnitt benötigt.

Am schönsten ist es m.E., wenn man die Bearbeitung nicht in den Hintergrund schicken muss, denn die Pipe ist ein natürlicher FIFO. Ich weiß allerdings nicht, ob inotifywait das abkann wenn das Schreiben geblockt wird. Das müsste man mal ausprobieren.

Serengeti

(Themenstarter)
Avatar von Serengeti

Anmeldungsdatum:
24. Februar 2008

Beiträge: 1961

@rklm und Benno-007

Ich habe jetzt mal die Variante ohne inotitywait versucht und die läuft tadellos.

1
2
3
4
5
6
7
8
9
cd ORDNER
while true; do
for datei in */*.ts; do
  if  nice -n 14 ffmpeg -i "$datei" -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn "$datei.mkv"; then
    mv "$datei" "$datei".verarbeitet
  fi
done
sleep 10m
done

Im nächsten schritt versuche ich Inotifywailt, da das Konvertieren wohl doch schneller geht als die Datei mit Inhalt gefüllt wird.

Edit

@rklm und Benno-007

Welchen inotifywait soll ich nun nutzen? Also das Codebeispiel von rklm oder Benno 007?

Serengeti

(Themenstarter)
Avatar von Serengeti

Anmeldungsdatum:
24. Februar 2008

Beiträge: 1961

könnte man das script so schreiben, dass inotifiywait die gefundenen Dateien in eine "todo" liste schreibt, die vom Rest des Programms dann abgearbeitet wird?

TNTMaster

Anmeldungsdatum:
30. Juli 2009

Beiträge: 877

Du könnstest prüfen, wann die letzte Änderung in der Datei war und die Verarbeitung nur starten, wenn das z.B. mind. 60 Sekunden her ist

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cd ORDNER
while true; do
  for datei in */*.ts; do
    if [ -e "$datei" ]; then
      now=$(date +'%s')
      lastmodify=$(stat --format='%Y' "$datei")
      seconds=$((now-lastmodify))
      if [ $seconds -ge 60 ]; then
        if  nice -n 14 ffmpeg -i "$datei" -map 0:0 -map 0:1 -c:v libx264 -vf scale=-1:720 -r 25 -c:a:0 copy -sn "$datei.mkv"; then
          mv "$datei" "$datei".verarbeitet
        fi
      fi
    fi
  done
  sleep 10m
done

TNT

Serengeti

(Themenstarter)
Avatar von Serengeti

Anmeldungsdatum:
24. Februar 2008

Beiträge: 1961

Danke TNTMaster damit kriege ich es auch so hin dass sich das ganze nicht beisst. 👍

Benno-007

Anmeldungsdatum:
28. August 2007

Beiträge: 29240

Wohnort: Germany

Nette Idee!

Antworten |