ffmpeg命令行map参数的使用

介绍

理解-map参数的最好办法就是想像一下怎么去告诉ffmpeg你要从源文件中选择/拷贝哪个流到输出文件。输出文件的stream顺序取决于在命令行中-map的参数顺序。

下面有一些例子。

默认

默认操作(没有指定map参数),比如:

ffmpeg -i INPUT OUTPUT

本质上,是从所有输入中发现“最高质量”(单个)视频输入流和“最高质量”(单个)音频输入流,并“发送”到OUTPUT。所有其他输入流实质上都被丢弃了。

如果我们想用map命令“显示”与上面命令相同的操作,它会是这样的:

ffmpeg -i INPUT -map single_highest_quality_video_stream_from_all_inputs -map single_highest_quality_audio_stream_from_all_inputs OUTPUT

此处输出将有两个流,一个音频,一个视频。

当你想要控制哪些流被包含,或者在输出中包含不止一个流时,你需要/想要手动指定“-map”命令,并修改这些参数。

输入文件

在下面的所有示例中,我们将使用一个类似下面的示例输入文件:

# fmpeg -i input.mkv
 
ffmpeg version ... Copyright (c) 2000-2012 the FFmpeg developers
...
Input #0, matroska,webm, from 'input.mkv':
  Duration: 01:39:44.02, start: 0.000000, bitrate: 5793 kb/s
    Stream #0:0(eng): Video: h264 (High), yuv420p, 1920x800, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
    Stream #0:1(ger): Audio: dts (DTS), 48000 Hz, 5.1(side), s16, 1536 kb/s (default)
    Stream #0:2(eng): Audio: dts (DTS), 48000 Hz, 5.1(side), s16, 1536 kb/s
    Stream #0:3(ger): Subtitle: text (default)
At least one output file must be specified
 
#

本文福利,免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部↓↓

 

例子1

那么现在,我们说我们想要:

  • 将视频流复制
  • 将德语音频流编码为MP3(128kbps)和AAC(96kbps)(在输出中创建两个音频流)
  • 将英语音频流删除
  • 将字幕流复制

这可以用以下的ffmpeg命令来完成:

ffmpeg -i input.mkv \
    -map 0:0 -map 0:1 -map 0:1 -map 0:3 \
    -c:v copy \
    -c:a:0 libmp3lame -b:a:0 128k \
    -c:a:1 libfaac -b:a:1 96k \
    -c:s copy \
    output.mkv

注意一下参数里没有“-map 0:2”,并且“-map 0:1”被写了两次。

使用“-map 0:0 -map 0:1 -map 0:1 -map 0:3”,我们告诉ffmpeg选择/映射指定的输入流按相应顺序输出。

因此,我们的输出将具有以下流:

Output #0, matroska, to 'output.mkv':
    Stream #0:0(eng): Video ...
    Stream #0:1(ger): Audio ...
    Stream #0:2(ger): Audio ...
    Stream #0:3(ger): Subtitle ...

在我们选择好在输出中包含哪些流之后,使用“-map”选项,我们为输出中的每个流指定相应的编解码器。

视频和字幕流已经被复制,德语的音频流被编码成了两个新的音频流,MP3和AAC。

我们使用“-c:a:0”来指定输出的第一路音频流编解码器(codec),且用“-c:a:1”来指定输出的第二路音频流编解码器(codec)。

注意,“a:0”指的是输出的第一路音频流(本例中为0:1),“a:1”指的是输出的第二路音频流(也映射到输入流0:1),等。

结果将会是:

Output #0, matroska, to 'output.mkv':
    Stream #0:0(eng): Video ...
    Stream #0:1(ger): Audio ...
    Stream #0:2(ger): Audio ...
    Stream #0:3(ger): Subtitle ...
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (dca -> libmp3lame)
  Stream #0:2 -> #0:2 (dca -> libfaac)
  Stream #0:3 -> #0:3 (copy)

例子2

如果说我们想要倒序排列输入流,比如类似这样的输出:

    Stream #0:0(ger): Subtitle: text (default)
    Stream #0:1(eng): Audio: dts (DTS), 48000 Hz, 5.1(side), s16, 1536 kb/s
    Stream #0:2(ger): Audio: dts (DTS), 48000 Hz, 5.1(side), s16, 1536 kb/s (default)
    Stream #0:3(eng): Video: h264 (High), yuv420p, 1920x800, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)

这可以简单地使用下面的命令行来完成:

ffmpeg -i input.mkv -map 0:3 -map 0:2 -map 0:1 -map 0:0 -c copy output.mkv

注意,我们指定了所有的输入流,输出中的流顺序也会按照输入流的顺序生成。

选项“-c copy”告诉ffmpeg在所有流上使用“复制”操作。

例子3

如果我们想从同一个输入文件中仅提取音频流,那么我们可以这样做:

ffmpeg -i input.mkv -map 0:1 -map 0:2 -c copy output.mkv

例子4

如果我们想重新编码视频流,但复制所有其他流(如音频、字幕、附件等),我们可能会使用这样的东西:

ffmpeg -i input.mkv -map 0 -c copy -c:v mpeg2video output.mkv

这将会告诉ffmpeg:

  • 读取输入文件“'input.mkv'”
  • 选择要处理的所有输入流(第一个input=0)(使用“-map 0”)
  • 标记所有流被复制到输出(使用“-c copy”)
  • 标记要重新编码的视频流(使用“-c:v mpeg2video”)
  • 写入输出文件到“output.mkv”

例子5

你可以使用"-map"命令来创建多路文件输出,比如:

ffmpeg -i input.mkv -map 0:1 -map 0:2 audios_only.mkv -map 0:0 video_only.mkv

默认是将“最高质量视频”和“最高质量音频”映射到每个输出文件(基本上为每个输出重复使用)

例子6

你可以使用一个滤镜(filtergraph)做为map参数来控制输出:

ffmpeg -i INPUT -filter_complex "[0] scale=100x100[smaller_sized]"  -map "[smaller_sized]" out.mp4

这(在我们的示例中)与更精确地指定流是相同的,并且完全一样。

ffmpeg -i INPUT -filter_complex "[0:0] scale=100x100[smaller_sized]"  -map "[smaller_sized]" out.mp4

例子7

还有一些流选择快捷方式,比如你也可以使用“0:v”:

ffmpeg -i input -map 0:v -map 0:a output.mkv # chooses video and audio from input 0

例子8

MPEG流的选择:

最棘手的部分是从MPEG TS流选择时它可能会有多个流/通道,如果你正在接收“实时数据”(live data),仅仅指定索引可能是不行的,因为索引可以在运行时有所变化,所以:

ffmpeg -i INPUT -map 0:6 OUTPUT # 每次运行产生的结果可能都不一样,请不要这样使用!

假设您的文件是MPEG,您可以运行“ffmpeg -i INPUT”(不指定输出)来查看它包含的程序ID和流ID,比如这个示例(对其进行分析,以帮助“确保”它接收到其中的所有流,可能并不总是需要的)。

$ ffmpeg -probesize 50M -analyzeduration 50M -i INPUT
...
Input #0, mpegts, from 'INPUT':
  Duration: N/A, start: 22159.226833, bitrate: N/A
  Program 1344
    Metadata:
      service_name    : 7 Digital
      service_provider: Seven Network
    Stream #0:0[0x401]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], max. 14950 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x402](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 256 kb/s
  Program 1346
    Metadata:
      service_name    : 7TWO
      service_provider: Seven Network
    Stream #0:3[0x406]: Unknown: none ([5][0][0][0] / 0x0005)
    Stream #0:6[0x421]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], max. 14950 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:7[0x422](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 192 kb/s
    Stream #0:8[0x424](eng): Subtitle: dvb_teletext ([6][0][0][0] / 0x0006), 492x250
    Stream #0:4[0x499]: Unknown: none ([11][0][0][0] / 0x000B)

你可以通过程序ID指定所需的流:

ffmpeg -i INPUT -map 0:p:1344 OUTPUT # 从程序1344中输入两个输入,在本例子中是通道“7 digital”

或指定子流:

ffmpeg -i INPUT -map i:0x401 OUTPUT # 从找到的任何地方用PID(MPEG Packet ID [stream identifier])0x401拉入单个输入流,在本例中,它是“7 digital”中的视频流

其他类似的,请参阅其说明符示例。注意,如果你有“未知”的流在那里,你可能需要添加-ignore_unknown标志。

还请注意,如果输入流包含多个程序ID,则可以使用相同的ffmpeg实例和这里描述的map命令同时来记录它们。

例子9

包括“全部”输入到输出。默认行为是只复制一个音频和一个视频通道。如果你想复制“所有”频道,请使用“-map”:

ffmpeg -i input -map 0 output.mp4 # 从一个输入重新编码所有视频和音频通道 
ffmpeg -i input -map 0 -c copy output.mp4 # 将所有视频和音频通道从一个输入复制到输出,而不是仅一个视频

原文链接:ffmpeg命令行map参数的使用 - 资料 - 我爱音视频网 - 构建全国最权威的音视频技术交流分享论坛 

本文福利,免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部↓↓ 

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/125642026
今日推荐