Ich habe mehrere Audiospuren und Untertitel, um sie in einer einzigen .mkv -Datei zu extrahieren. Ich bin neu bei ffmpeg
-Befehlen, dies habe ich (Audio) versucht:
ffmpeg -i VIDEO.mkv -vn -acodec copy AUDIO.aac
Es wird nur 1 Audio extrahiert. Ich möchte ffmpeg
sagen, dass alle einzelnen Audiodateien und Untertiteldateien an ein Ziel extrahiert werden und der ursprüngliche Name der einzelnen Dateien und Erweiterungen beibehalten wird. (Weil ich nicht weiß, um welche Erweiterung es sich bei den Audiodateien handelt, manchmal vielleicht .flac oder .aac ).
Ich bin nicht sicher über die Lösungen, die ich online gefunden habe, weil sie ziemlich kompliziert sind und ich brauche Erklärungen, um zu wissen, wie sie funktionieren, damit ich den Befehl in Zukunft bearbeiten kann. Ich wollte übrigens den Code von Windows CMD ausführen.
Vielen Dank.
Es gibt noch keine Option in ffmpeg
, um alle Streams automatisch in einen geeigneten Container zu extrahieren, aber es ist durchaus möglich, dies manuell durchzuführen. Die Standardeinstellung Stream-Auswahl wählt nur einen Stream pro Stream-Typ aus, sodass Sie jeden Stream manuell zuordnen müssen.
Mit ffmpeg
oder ffprobe
können Sie die Informationen in jedem einzelnen Stream abrufen, und es steht ein große Auswahl an Formaten (xml, json, cvs usw.) zur Verfügung, das Ihren Anforderungen entspricht.
ffmpeg
Beispielffmpeg -i input.mkv
Die resultierende Ausgabe (ich schneide etwas extra aus, die Stream-Nummern und Formatinformationen sind das Wichtigste):
Input #0, matroska,webm, from 'input.mkv':
Metadata:
Duration: 00:00:05.00, start: 0.000000, bitrate: 106 kb/s
Stream #0:0: Video: h264 (High 4:4:4 Predictive), yuv444p, 320x240 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
Stream #0:1: Audio: vorbis, 44100 Hz, mono, fltp (default)
Stream #0:2: Audio: vorbis, 44100 Hz, mono, fltp (default)
Stream #0:3: Audio: vorbis, 44100 Hz, mono, fltp (default)
Stream #0:4: Subtitle: ass (default)
ffprobe
Beispielffprobe -v error -show_entries stream=index,codec_name,codec_type input.mkv
Die resultierende Ausgabe:
[STREAM]
index=0
codec_name=h264
codec_type=video
[/STREAM]
[STREAM]
index=1
codec_name=vorbis
codec_type=audio
[/STREAM]
[STREAM]
index=2
codec_name=vorbis
codec_type=audio
[/STREAM]
[STREAM]
index=3
codec_name=vorbis
codec_type=audio
[/STREAM]
[STREAM]
index=4
codec_name=ass
codec_type=subtitle
[/STREAM]
Verwenden der Informationen aus einem der obigen Befehle:
ffmpeg -i input.mkv \
-map 0:v -c copy video.mkv \
-map 0:a:0 -c copy audio0.oga \
-map 0:a:1 -c copy audio1.oga \
-map 0:a:2 -c copy audio2.oga \
-map 0:s -c copy subtitles.ass
In diesem Fall ist das obige Beispiel dasselbe wie:
ffmpeg -i input.mkv \
-map 0:0 -c copy video.mkv \
-map 0:1 -c copy audio0.oga \
-map 0:2 -c copy audio1.oga \
-map 0:3 -c copy audio2.oga \
-map 0:4 -c copy subtitles.ass
Ich bevorzuge das erste Beispiel, weil der input file index:stream specifier:stream index
flexibler und effizienter ist. Es ist auch weniger anfällig für falsche Zuordnung.
In der Dokumentation zu Stream-Spezifizierern und der -map
-Option können Sie die Syntax vollständig verstehen. Weitere Informationen finden Sie in der Antwort auf FFmpeg-Multiplexer-Video und -Audio (von einem anderen Video) - Zuordnungsproblem .
Diese Beispiele werden Stream Copy (Re-Mux), so dass keine Neucodierung stattfindet.
Zuerst würden Sie alle Audioströme auflisten:
ffmpeg -i VIDEO.mkv
und dann basierend auf der Ausgabe können Sie den Befehl kompilieren, um die Audiospuren einzeln zu extrahieren.
Wenn Sie ein Shell-Skript verwenden, können Sie dies möglicherweise in einer Skriptdatei automatisieren, sodass Sie es generisch für jede mkv-Datei tun können.
Untertitel sind ziemlich gleich. Die Untertitel werden in den Informationen gedruckt und können dann wie folgt extrahiert werden:
ffmpeg -threads 4 -i VIDEO.mkv -vn -an -codec:s:0.2 srt myLangSubtitle.srt
0.2 ist die Kennung, die Sie aus der Info lesen müssen.
Das folgende Skript extrahiert alle Audio-Streams aus Dateien im aktuellen Verzeichnis
ls |parallel "ffmpeg -i {} 2>&1 |\
sed -n 's/.*Stream \#\(.\+\)\:\(.\+\)\: Audio\: \([a-zA-Z0-9]\+\).*$/-map \1:\2 -c copy \"{.}.\1\2.\3\"/p' |\
xargs -n5 ffmpeg -i {} "
Ich habe es so gelöst:
ffprobe -show_entries stream=index,codec_type:stream_tags=language -of compact $video1 2>&1 | { while read line; do if $(echo "$line" | grep -q -i "stream #"); then echo "$line"; fi; done; while read -d $'\x0D' line; do if $(echo "$line" | grep -q "time="); then echo "$line" | awk '{ printf "%s\r", $8 }'; fi; done; }
Ausgabe:
Stellen Sie $ video1 var nur vor dem Befehl ein.
Geniesse es!.