使用ffmpeg从视频中提取每个音频和字幕

Wha*_*hen 14 audio video cmd ffmpeg mkv

我有多个音轨和字幕可以在一个.mkv文件中提取.我是ffmpeg命令的新手,这是我尝试过的(音频):

ffmpeg -i VIDEO.mkv -vn -acodec copy AUDIO.aac

它只提取1个音频.我想要的是告诉ffmpeg将每个音频文件和字幕文件提取到目的地,并保留每个文件和扩展名的原始名称.(因为我不知道音频文件是哪个扩展名,有时可能是.flac.aac).

我不确定我在网上找到的解决方案,因为它非常复杂,我需要解释才知道它是如何工作的,这样我才能在将来操作命令.顺便说一句,我计划从Windows CMD运行代码.

谢谢.

llo*_*gan 31

现在还没有选择ffmpeg将所有流自动提取到适当的容器中,但是当然可以手动完成.默认流选择仅为每种流类型选择一个流,因此您必须手动映射每个流.

1.获取输入信息

使用ffmpeg或者ffprobe您可以获取每个流中的信息,并且有多种格式(xml,json,cvs等)可满足您的需求.

ffmpeg

ffmpeg -i input.mkv
Run Code Online (Sandbox Code Playgroud)

结果输出(我删除了一些额外的东西,流数和格式信息是重要的):

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)
Run Code Online (Sandbox Code Playgroud)

ffprobe

ffprobe -v error -show_entries stream=index,codec_name,codec_type input.mkv
Run Code Online (Sandbox Code Playgroud)

结果输出:

[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]
Run Code Online (Sandbox Code Playgroud)

2.提取流

使用上述命令之一的信息:

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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,上面的示例与以下示例相同:

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
Run Code Online (Sandbox Code Playgroud)

  • @themihai 这些值代表“输入 ID:流说明符:流 ID”。例如,`2:a:5` 将是来自第三个输入的第 6 个 *a*audio 流(`ffmpeg` 从 0 开始计数)。它比简单地声明像 `2:5` 这样的东西更灵活,因为 *stream index* 值可能并不总是代表所需的流。通过让您从第二个输入中选择第 8 个视频流:`1:v:8`,它可以让您变得更加懒惰。有关更多信息,请参阅 [`-map` 文档](http://ffmpeg.org/ffmpeg.html#Advanced-options) 和 [此答案](http://stackoverflow.com/a/12943003/1109017)。 (5认同)
  • 值得注意的是,在libavformat版本57.82.100之前,无法使用此命令以*.sup格式提取Bluray字幕(hdmv_pgs_subtitle),因此如果您需要这样做,请确保使用最新版本的ffmpeg可执行文件. (3认同)

小智 5

我是这样解决的:

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; }
Run Code Online (Sandbox Code Playgroud)

输出:

结果-ffprobre-列表-流

仅在命令之前设置 $video1 var。

好好享受!。