Mein Bash Script für ffmpeg Stapelverarbeitung incl. extras.

dragnod0

Ensign
Registriert
Juni 2008
Beiträge
238
Hallo zusammen.
Heute möchte ich euch wieder einmal einen Script vorstellen den ich gebastelt habe.
Wie der Titel schon sagt ist es ein Script für ffmpeg der mehrere Dateien nacheinander verarbeitet aber auch noch etwas mehr macht.

Was macht der Script?

  • Er liest alle Videos mit der ausgewählten Dateiendung im Quellordner ein, konvertiert es mit dem HEVC (h.265) und AAC Codec in die Dateiendung die man als ziel angegeben hat.
  • Der Script muss sich dabei nicht in dem Ordner mit den Videos befinden weil man Quell- und Zielpfade angeben kann (diese müssen aber schon existieren).
  • Die Audiospur wird in 5.1 mit 128k pro Kanal (gesamter Audiostream 768k) konvertiert.
  • Die ursprünglichen Dateinamen werden übernommen.
  • Es werden nur das Video selbst, die deutsche Audiospur und wenn vorhanden die als forced geflaggte Untertitelspur übernommen.
  • Die schwarzen Balken werden automatisch entfernt. Eine Garantie das dies immer korrekt funktioniert kann ich natürlich nicht geben.

Und hier ist der Script:
Bash:
#! /bin/bash
# Einlesen der Eingabe von Quellkontainer und Zielkontainer sowie Quellordner und Zielordner
# Sytax: ./[nameDerScriptdatei].sh [Quellkontainer] [Zielkontainer] [/Pfad/zum/Quellordner] [/Pfad/zum/Zielordner]
# Beispiel: ./ffmpeg-batch.sh mp4 mkv /home/user/Videos /home/user/Videos/optimiert
# Die Pfadangaben dürfen nicht mit einem / enden!

srcExt=$1     #Quell Dateityp z.B. mp4 oder * für alle (Video) Dateien
destExt=$2    #Ziel Dateityp z.B. mkv

srcDir=$3     #Quellordner
destDir=$4    #Zielordner
number=1
# Übergabe von Optionen für ffmpeg
opts="-c:v hevc -crf 18 -preset slow -ac 6 -c:a aac -b:a 128k"

# Ermittelt die Dateinamen aus dem Quellordner, fügt ihn mit der Angabe des Quellordners zusammen und macht daraus die Variable filename.
for filename in "$srcDir"/*.$srcExt; do

        basePath=${filename%.*}
        baseName=${basePath##*/}

# ermittelt die Dimensionen des tatsächlichen Videos bei Position 240 Sekunden (4 Minuten) um die schwarzen Balken entfernen zu können. Die 240 Sekunden stellen sicher das ein langer Vorspann nicht die Werte verfälscht.
echo -e "\033[32m\033[1m>>>>> Größe des Bildausschnittes wird ermittelt für späteren zuschnitt. Das kann ein paar Sekunden dauern. <<<<<\033[0m"
cropvalue=$(ffmpeg -i "$filename" -t 240 -vf cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tail -1)

# Ermittelt die Untertitelspur die als forced markiert ist.
echo -e "\033[32m\033[1m>>>>> Die untertitelspur die als forced getagt ist wird gesucht <<<<<\033[0m"
sleep 3
subIndex=$(ffprobe -v 0 -select_streams s -show_entries stream=index:disposition=forced -of compact=nk=0 "$filename" | grep disposition:forced=1 | sed -ne 's#^stream|index=\([0-9]\+\)|.*$#\1#p')
     
    if [ -z $subIndex ] ; then
            echo -e "\033[32m\033[1m>>>>> Das Quell Video enthält keine Untertitelspuren die als forced getaggt sind. <<<<<\033[0m"
            sleep 3
        else
            echo -e "\033[32m\033[1m>>>>> Es wurde die Untertitelspur:"$subIndex" ausgewählt. <<<<<\033[0m"
            sleep 3
    fi
 
     
    if [ -z $subIndex ] ; then
            # Konvertiert und beschneidet das Video in das angegebene Zielordner und den angegeben Zielkontainer wenn KEINE Untertitelspur mit forced getaggt gefunden wurde.
            echo -e "\033[32m\033[1m>>>>> Konvertierung von $filename. Keine Untertitel vorhanden <<<<<\033[0m"
            sleep 3
            ffmpeg -y -loglevel error -stats -i "$filename" -map 0:0 -map 0:a:m:language:ger -vf "$cropvalue" $opts "$destDir"/"$baseName"."$destExt"
        else
            # Konvertiert und beschneidet das Video in das angegebene Zielordner und den angegeben Zielkontainer wenn eine Untertitelspur mit forced tag gefunden wurde.
            echo -e "\033[32m\033[1m>>>>> Konvertierung von $filename. <<<<<\033[0m"
            sleep 3
            ffmpeg -y -loglevel error -stats -i "$filename" -map 0:0 -map 0:a:m:language:ger -map 0:$subIndex -vf "$cropvalue" $opts "$destDir"/"$baseName"."$destExt"    
        fi
     
done

Ich habe ihn unter Ubuntu getestet. ob es auch mit anderen nicht debian basierten Distros geht kann ich leider nicht sagen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Mulciber, BachUhr, madmax2010 und 2 andere
Hallo,

Erwartungsgemaess funktioniert Dein Script auch im WSL. 👍
Hier getestet mit einem Debian.

1593636349501.png


Danke!

Achso.
Zeile 42 und 47.
Das Wort "Convertirung" wuerde ich nicht verwenden. Eher "Konvertierung".

BFF
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: dragnod0
@BFF
Ich vermische manchmal die englische mit der deutschen Schreibweise ;)
Danke für den Hinweis ich hab's korrigiert.

Interessant das es mit WSL auch unter Windows funktioniert.

Mann könnte die sleep Anweisung aus Zeile 33 und 36 auch weg lassen das würde 6 Sekunden sparen ;)
Ich hatte die Wartezeit rein gemacht bevor ich das Loglevel von ffmpeg verkürzt habe. Da waren die ausdrücke nämlich fast sofort wieder weg wegen ffmpeg.
 
Zuletzt bearbeitet:
Zurück
Oben