wiki:

Map

Introduction

The best way to understand -map option is to think of it like a way to tell FFmpeg which streams do you want to select/copy from input to an output.

The order of -map options, specified on cmd line, will create the same order of streams in the output file.

Here are several examples.

Default

The default behavior (when map is not specified), ex:

  ffmpeg -i INPUT OUTPUT

is to, in essence, discover the "highest quality" (single) video input stream and "highest quality" (single) audio input stream from all input(s), and "send" that to the OUTPUT. All other input streams are in essence discarded.

The "map" command basically means "include this stream into the immediately following OUTPUT file."

If we wanted to "show" the same behavior using the map command, it would look like this:

  ffmpeg -i INPUT -map single_highest_quality_video_stream_from_all_inputs -map single_highest_quality_audio_stream_from_all_inputs OUTPUT

and OUTPUT will end up with 2 streams, one audio, one video.

When you want to control which streams are included, or include more than one stream in the output, then you will need/want to specify the "-map" command manually, and change these parameters.

Input file

In all following examples, we will use an example input file like this one:

# 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

#

Example 1

Now, let's say we want to:

  • copy video stream
  • encode german audio stream to mp3 (128kbps) and aac (96kbps) (creating 2 audio streams in the output)
  • drop english audio stream
  • copy subtitle stream

This can be done using the following FFmpeg command line:

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

Note there is no "-map 0:2" and that "-map 0:1" has been specified twice.

Using "-map 0:0 -map 0:1 -map 0:1 -map 0:3" we told FFmpeg to select/map specified input streams to output in that order.

So, our output will now have the following streams:

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 ...

After we selected which streams we would like in our output, using "-map" option, we specified codecs for each stream in our output.

Video and subtitle stream have just been copied and german audio stream has been encoded to 2 new audio streams, mp3 and aac.

We used "-c:a:0" to specify codec for the output's first AUDIO stream and "-c:a:1" to specify codec for the output's second AUDIO stream.

Note that "a:0" refers to the output's first AUDIO stream (#0:1 in our case), "a:1" refers to the output's 2nd AUDIO stream (#0:2 in our case), etc.

The result will be:

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)

Example 2

Let's say that we want to reorder input streams backwards, so that we have output like this:

    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)

This can simply be done using the following command line:

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

Note that we specified all the input streams, but in the reverse order, which causes that order to be respected in the output.

The option "-c copy" tells FFmpeg to use "copy" on all streams.

Example 3

If we want to extract only audio streams, from the same input file, then we can do it like this:

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

Example 4

If we want to re-encode just the video streams, but copy all the other streams (like audio, subtitles, attachments, etc), we might use something like this:

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

It will tell ffmpeg to:

  • read the input file 'input.mkv'
  • select all the input streams (first input = 0) to be processed (using "-map 0")
  • mark all the streams to be just copied to the output (using "-c copy")
  • mark just the video streams to be re-encoded (using "-c:v mpeg2video")
  • write the output file 'output.mkv'

Example 5

You can use the "-map" command in creating multiple output files, ex:

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

The default is to map the "highest quality video" and "highest quality audio" to each output file (basically reuses it for each output), see also Creating multiple outputs.

Example 6

You can use the named output of a filtergraph as a mapping parameter, ex:

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

which (in our example) is the same as specifying the stream more precisely, and equivalent to this

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

Example 7

There are stream selection shortcuts you can also use like "0:v"

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

See stream specifiers for details.

Example 8

MPEG stream selection:

The tricky part with selecting from MPEG TS is it may contain multiple streams/channels, and if you are receiving "live data" just specifying an index might not work because it can change from run to run, so

ffmpeg -i INPUT -map 0:6 OUTPUT # might not work the same every run, DO NOT USE THIS WAY!

Assuming your file is MPEG, you can run "ffmpeg -i INPUT" (not specify an output) to see what program id's and stream id's it contains, like this example (probesize and analyzeduration specified to help "make sure" it picks up all the streams in it, may not be always needed)

$ 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)

you could specify desired streams by program id:

ffmpeg -i INPUT -map 0:p:1344 OUTPUT # pulls in both inputs from program 1344, channel "7 Digital" in this case

or specify a child stream:

ffmpeg -i INPUT -map i:0x401 OUTPUT # pulls in the single input stream with PID (MPEG Packet ID [stream identifier]) 0x401 from wherever it is found, in this case its a video stream in "7 Digital"

or similar, see other specifier examples. Note if you have "unknown" streams in there you may need to add the -ignore_unknown flag as well.

Also note that if your input stream contains multiple program id's, you can record simultaneously from various of them, using the same FFmpeg instance and the map commands described here.

Example 9

Include "all" inputs to the output. The default behavior is to copy only one audio and one video channel. If you want to copy 'all' channels, use "-map"

ffmpeg -i input -map 0 output.mp4 # re encodes all video and audio channels from input one 
ffmpeg -i input -map 0 -c copy output.mp4 # copies all video and audio channels from input one to output, not just one video
Last modified 5 months ago Last modified on Nov 19, 2016, 1:54:37 AM