Shell script: Übergabe einer beliebigen Video Datei -> konvertieren mit ffmpeg nach h265 mit deutscher Audiospur

jteschner

Aktives Mitglied
Thread Starter
Registriert
30.05.2006
Beiträge
8.043
Reaktionspunkte
5.711
Bevor ich selbst anfange mit Hilfe von ChatGPT was zu erstellen. Es gibt doch bestimmt jemanden der/die so etwas bereits im Fundus hat.
Und: Handbrake funktioniert auch, ich habe aber im Vergleich festgestellt, dass ffmpeg die besseren Ergebnisse liefert.

Rahmen:
Ich habe hier Video-Dateien .mkv und .mp4, die mehrere Audiospuren haben (eng, deu, verschiedene Formate), die ich nach h265 mit ffmpeg konvertieren möchte.
Allerdings will ich nur die deutsche Audiospur haben und ggf will ich ein downscaling der Videospur vornehmen.
Aktuell gehe ich so vor, dass ich mir mit ffmpeg die vorhandenen Streams anzeigen lasse und mir dann die passende ffmpeg-Zeile manuell zusammenbaue.
In einem passenden Script liesse sich das doch bestimmt vereinfachen.

Ziel:
Ein script, dem ich mit dem Aufruf die Video Datei und ggf Parameter mitgebe wie (-s 1280x720 -a stereo) und das mir dann den ffmpeg-Aufruf zusammenbaut und ausführt, so dass am Ende ein .mp4 mit h265 Videostream in gewünschter Auflösung und nur deutscher Tonspur entsteht.

Hat jemand bereits so etwas oder ähnliches (anpassen ist ggf einfacher als neuschreiben)?
 
... willst du die deutsche Audio-Spur automatischer ermitteln lassen oder gibst du die Stream-Nummer manuell an?

Das automatische Ermitteln setzt voraus, dass das entsprechende metadata tag auch gesetzt ist.

Ob sich das allerdings mit einem script einfacher gestaltet, als gleich ffmpeg direkt aufzurufen ist fraglich, da du zwar vielleicht ein paar wenige Paramater fest vorgeben kannst und du dir diese Parameter sparst.

Für den ganzen Rest musst du dir dann im script faktisch einen Parser für die immer noch auszuwählenden Parameter schreiben und dabei sicherstellen, dass sie auch korrekt verarbeitet werden. Der Punkt dabei ist, dass die Parameter bei ffmpeg teilweise positionsabhängig sind, du aber sicher sowas wie den Videocodec (-c:v hevc_videotoolbox) vorgeben willst.

Kann man alles machen und das macht auch Spaß, sowas mit einem shell-script zu erstellen. Aber für das doch sehr einfache Ziel der Nuekodierung, würde ich das nicht tun.

Ich habe mir über die letzten Jahre eine große Sammlung an scripten für ffmpeg erstellt. Die führen aber mitunter sehr komplexe Dinge durch und sind nicht einzeln nützlich, sondern nur im Zusammenspiel.

Bsp: Konvertieren eines 25 fps PAL Videos nach 23.976 NTSC. Video verlustfrei, Audio pitchkorrekt kodiert, incl aller Audio-Spuren, wählbarer Audio-Bitrate und optionalem Downmix nach Dolby Prologic II

Aber mein "größtes" script transkodiert wäre in etwas so das was du meinst. Nur haben meine Videoquellen nur 1 Audiospur. Das script transkodiert nach h265 videotoolbox. Es halt automatische Werte für downmix, croppen, und für mcih passenden defaults, kann overlays über Abschnitte legen, kann mehrere Teile zu einem Video zusammenfügen (die ich vorher durch rausschneiden von Werbung erzeugt habe).

Selbst das ist noch nicht perfekt und vorallem nicht universell, sondern auf meinen speziellen Use-Case zugeschnitten.

Wenn du willst, kann ich das mal als Anschauungsobjekt posten. Wie gesagt, es ist aber nicht in allen Dingen alleine sinnvoll, sondern braucht andere scripte. Du kannst darausüber den Parser der Kommandozeile erkennen und die Art, wie die letzendliche vorhandene Kommandozeile generiert und ausgeführt wird.

Dennoch: ich würde mir die Arbeit für deinen Use-Case nicht machen.
 
... willst du die deutsche Audio-Spur automatischer ermitteln lassen oder gibst du die Stream-Nummer manuell an?
Erst mal danke für deine Mühe .. .ich habe es mir fast gedacht, dass das doch nicht so einfach ist...
Die deutsche Spur sollte automatisch ermittelt werden.
Aktuell suche ich sie mir manuell raus - und ja, die Metadaten sind nicht immer korrekt oder gar nicht gesetzt.
Ich gebe dann die zu konvertierenden Spuren per `-map` dem ffmpeg mit
Es ist ja nicht allzu kompliziert das manuell zu machen und ich habe mir auch ein paar entsprechende "Vorlagen" in Obsidian erstellt, die ich dann nur noch eben anpassen und per Mausclick kopieren kann .

Aber kein Problem - so groß ist der manuelle Aufwand nicht. Ich dachte nur: wenn schon was existiert, dann kann man das auch nutzen :-)

Ganz nebenbei - und sollte hier nicht diskutiert werden: wird hatten ja mal über macdown.app gesprochen. Inzwischen teste ich etwas markedit.app - und finde das schon recht gut. Ich gehe mal davon aus, dass du es kennst ...
 
Erst mal danke für deine Mühe .. .ich habe es mir fast gedacht, dass das doch nicht so einfach ist...
Die deutsche Spur sollte automatisch ermittelt werden.

Das Ermitteln der Spur ist nicht schwer.

Code:
audio=$(ffmpeg -i "input.mp4" 2>&1 | grep -e "Audio" | grep -e "deu" | sed "s/.*#//;s/\[.*//")

Der Aufwand liegt im Parser der Eingabe-Parameter und dem anschließend korrekten Erzeugen der Zeile für ffmpeg.

Edit:
Ja, MarkEdit kenn ich und versuche mich daran zu gewöhnen ;)
 
Das Ermitteln der Spur ist nicht schwer.

Code:
audio=$(ffmpeg -i "input.mp4" 2>&1 | grep -e "Audio" | grep -e "deu" | sed "s/.*#//;s/\[.*//")

:LOL: Ich würde hauptsächlich schon am "sed ..." scheitern :-)
 
:LOL: Ich würde hauptsächlich schon am "sed ..." scheitern :-)
:LOL: ja, am Anfang ist das schon arg nerdy.

Aber das s = search and replace ist auch recht einfach

s = der operator, heir search and replace
/ ist das Trennzeichen. Das kann auch jedes andere Zeichen sein. Leicht lesbar ist auch |
der erste Teil zwischen den Trennzeichen ist der Suchstring, der zweite Teil der Ersatz

Die Pattern sind eigentlich auch einfach:
. = 1 beliebiges Zeichen oder gar kein Zeichen
* = das vorherige Zeichen wird beliebig of wiederholt
? = exakt 1 Zeichen das vorhanden sein muss
\ = escaped diese besonderen Zeichen (Klammern haben auch besondere Bedeutung, daher escapen, wenn man sie sucht/ersetzt)

am Ende kann man noch ein "g" für "general" angeben, also alle Vorkommen in 1 Zeile, ohne g nur das erste Vorkommen.

Wichtig: sed sucht standardmäßig nach dem längsten String der passt

Mehrere suchen/ersetzen verknüpft man einfach mit ;

Also s/.*#// sucht nach einem Match für beliebig viele Zeichen (.*) die vor einem # stehen und ersetzt das mit "nichts" (//)

Dann sucht s/\[.*// nach dem Zeichen [ mit anschließend beleibig vielen Zeichen danach, also bis zum Ende der Zeile und ersetzt auch das mit "nichts"
 
Zurück
Oben Unten