TIL: Audio-Spuren mit ffmpeg umsortieren

Ich habe hier eine Handvoll Video-Dateien (Serienfolgen, welche vor Ewigkeiten von DVD importiert und mit Handbrake encodiert wurden). Die Videos enthalten zwei Audiospuren, nämlich Deutsch und English.

Deutsch ist die Standard-Spur und ist beim Öffnen im Player immer vorausgewählt. Um eine Folge schauen zu können, muss man also immer erst auf Englisch umstellen. Nach dem zweiten Mal nervt das.

Mit ffpmeg lässt sich der Default-Audio-Track einfach festlegen. Dazu werden die Dateien einmal neu geschrieben, ein erneutes Encodieren ist aber nicht notwendig. Der Prozess ist rein I/O-bound und dauert pro Video nur etwa eine knappe Sekunde:

1
2
3
4
5
ffmpeg -i S01E01.mp4 \
    -map 0:v:0 -map 0:a:1 -map 0:a:0 \
    -disposition:a:0 +default -disposition:a:1 -default \
    -codec copy \
    S01E01-eng.mp4

Der Reihe nach:

  • -i wählt als Eingabedatei S01E01.mp4 aus
  • mit -map werden die Streams für die Ausgabe selektiert (Dokumentation):
    • 0:v:0 entspricht dem ersten (und in diesem Beispiel einzigen) Videostream
    • 0:a:1 ist der zweite Audiostream (hier die englische Tonspur)
    • 0:a:0 ist der erste Audiostream (hier die deutsche Tonspur)
  • -disposition setzt (+default) bzw. entfernt (-default) das default-Flag der Tonspuren; a:0 und a:1 beziehen sich hier auf die Reihenfolge in der Ausgabe, a:0 meint also die jetzt englische und a:1 bezieht sich auf deutsche Tonspur (vertauscht zur Reihenfolge des Eingabe-Videos)
  • -codec copy kopiert die Stream-Inhalte ohne sie zu verändern oder umzucodieren
  • das Ergebnis wird in S01E01-eng.mp4 geschrieben

Es wird also zum einen die Reihenfolge der Audiostreams geändert und zum anderen ein anderer Default-Stream gesetzt.

Wenn man das ganze in eine for-Loop packt, lassen sich gleich alle Videos in einem Directory in einem Rutsch anpassen:

1
2
3
4
5
6
for FILE in S01E[012][0-9].mp4 ; do \
    ffmpeg -i "$FILE" \
        -map 0:v:0 -map 0:a:1 -map 0:a:0 \
        -disposition:a:0 +default -disposition:a:1 -default \
        -codec copy "$(basename "$FILE" .mp4)-eng.mp4" ; \
done

Du findest diesen Artikel hilfreich?

Folge Marcus auf Mastodon

Auch über Fragen und Anmerkungen freue ich mich! Am einfachsten sendest du diese direkt an meinen Mastodon-Account.