6

I'm trying to copy video/audio from an mkv container to mp4. When I run ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4 I'm given no video with polish audio. There's only one video stream, stream #0:0. Stream #0:1 is polish audio, #0:2 english, and #0:3 - #0:5 are subtitles.

I read this https://trac.ffmpeg.org/wiki/How%20to%20use%20-map%20option but don't understand it really. Why is -map 0:1 written twice in example 1? What does -c:s do? What would a command to copy #0:0 to video and #0:2 to audio look like?

8

-map <inputNo>:<streamNo> tells ffmpeg to take stream streamNo from the input inputNo and to add it to the output, where <inputNo> starts with 0.

Sometimes, you may want to take the same input stream twice (such as -map 0:1 -map 0:1 in the example) because you can encode each with different codecs/parameters. In the example, the output contains the same audio stream twice, one in MP3 and the other in AAC.

By default (i.e. with no -map command at all), one video, one audio, and one subtitle stream from the inputs are taken. If you want to map all the streams from one input, use -map <inputNo>.

That you don't get video with your command can only mean one thing : your video track is encoded with a codec that can be muxed in MKV, but not in MP4. So it is discarded automatically. Can you post a log of ffmpeg -i input.mkv so that we can check which codecs the tracks are encoded with ?

Finally, -c:s is used for subtitle codec (while -c:a is for audio and -c:v for video)

|improve this answer|||||
  • 2
    "By default (i.e. with no -map command at all), all the streams from all the inputs are taken once." — this is not true. ffmpeg will only take one audio, video, and subtitle stream. If you want all the streams mapped, you need -map 0. – slhck Jul 18 '15 at 8:20
2

This was the example that allowed me to understand. Imagine the following command:

ffmpeg -i tears_of_steel.mkv -map 0:0 -map 0:2 -map 0:1 -map 0:4 -map 0:3 -c copy tears_of_steel-v2.mkv 

And here is how ffmpeg does the mapping:

Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:2 -> #0:1 (copy)
Stream #0:1 -> #0:2 (copy)
Stream #0:4 -> #0:3 (copy)
Stream #0:3 -> #0:4 (copy)

What happened?

In the command, we have only one input: tears_of_steel.mkv. That's why all our maps start with #0:...

Then we write a first map option: -map 0:0, which refers to the first stream of our input (tears_of_steel.mkv), which might be a video stream, but that doesn't matter.

Because it's the first map option, it will be mapped to the first stream in our output file (tears_of_steel-v2.mkv).

Then we write a second map option: -map 0:2, which refers to the third stream of our input. Because it's the second map option, it is mapped to the second stream in our output.

And so on...

I wrote that on my github: https://github.com/lingtalfi/ffmpeg-notes/blob/master/ffmpeg-map.md

|improve this answer|||||
0

This should work, can't test on this machine:

ffmpeg -i input.mkv
-map 0:0 -map 0:2 \
-c:v copy \
-c:a aac \
-b:a 128k \
output.mp4

or

ffmpeg -i input.mkv -map 0:0 -map 0:2 -c:v copy -c:a aac -b:a 128k output.mp4

Explanations

c:s is an alias for -scodec codec, which specifies the subtitle codec.

-map 0:1 is there twice because the example has an aac and an mp3 output.

|improve this answer|||||
  • Won't work because -c:a aac needs -strict experimental too. – slhck Jul 18 '15 at 8:22
0

This is a simple answer for people like me, who like simple working explanations. This is a solution when you copy mkv to mp4 and want to choose audio streams:

You have to write -map 0:numberofstreamminusone in front of -c:a copy

Let's say the video has 3 streams (you can see that in mediainfo). The first stream is video, the second is default audio, and the third is non-default audio in the language you want. So you have to write -map 0:2 NOT -map 0:3

Also, you have to write -map 0:0 in front of -c:v copy because if you don't, ffmpeg will not copy the video stream and you get only the audio stream (If the video has two video streams and you want to copy the second one, you have to write -map 0:1)

So the final command line looks like this:

ffmpeg -i "inputpath\input.mkv" -map 0:0 -c:v copy -map 0:2 -c:a copy "outputpath\output.mp4"

In this case, you wil get the first video stream and the third audio stream

Another example:

ffmpeg -i "inputpath\input.mkv" -map 0:1 -c:v copy -map 0:6 -c:a copy "outputpath\output.mp4"

In this case you should get the second video stream and the seventh audio stream

I hope this helps

|improve this answer|||||
  • The examples seem inaccurate, or the wording is confusing. As I understand it, “0:2” refers to the third stream, regardless of its type, so most likely the second audio stream (if there is only one video stream and the streams are placed in “logical” order in the input); likewise, in the second example, “0:6” would be the sixth audio stream if stream 0 in input is a video stream and 1-6 are audio streams. – GabrielB Nov 25 '18 at 13:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.