Dotl
Dotl

Reputation: 1498

FFmpeg not copying all audio streams

I'm having trouble getting ffmpeg to copy all audio streams from a .mp4 file. After hours of searching online, it appears this should copy all streams (as shown in example 4 here):

ffmpeg -i in.mp4 -map 0 -c copy out.mp4

in.mp4 contains 3 streams:

out.mp4 (which should be identical to in.mp4) contains only 2 streams:

FFmpeg does appear to correctly identify all 3 streams, but doesn't copy all of them over. Output from FFmpeg:

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

Edit: Output from ffmpeg -v 9 -loglevel 99 -i in.mp4:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from in.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.36.100
  Duration: 00:00:06.03, start: 0.000000, bitrate: 5582 kb/s
    Stream #0:0(und), 1, 1/15360: Video: h264 (Main), 1 reference frame (avc1 /
0x31637661), yuv420p(tv, bt470bg/unknown/unknown, left), 1920x1080 (0x0) [SAR 1:
1 DAR 16:9], 0/1, 5317 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz,
 stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
    Stream #0:2(und), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz,
 stereo, fltp, 128 kb/s
    Metadata:
      handler_name    : SoundHandler
Successfully opened the file.
At least one output file must be specified
[AVIOContext @ 0000000001c2b9e0] Statistics: 153350 bytes read, 2 seeks

Edit 2 (solved): I managed to find the correct syntax from this ticket. For any others that are interested, the correct syntax is:

ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0 out.mp4

This will copy all streams.

Upvotes: 49

Views: 61558

Answers (6)

udippel
udippel

Reputation: 145

@Aquarius Power: [I couldn't comment, alas] Your answer is the only one that worked for me. Thanks a bunch!

My basic command is, to extract the first 40 seconds of a file with ffmpeg -i infile -t 00:00:40 -c copy outfile, including all audio streams.

Just -c copy and -vcodec copy -acodec copy produce the first audio stream only.

-c copy map 0 results in

[mpegts @ 0x55a014287e00] Timestamps are unset in a packet for stream 8. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly [mpegts @ 0x55a014287e00] Stream 8, codec epg, is muxed as a private data stream and may not be recognized upon reading. And worse, it doesn't respect the end time, but produces a complete file, at a speed below 1.

-vcodec copy -c:a copy -map 0

and

-vcodec copy -c:a copy -map 0:0 -map 0:1 -map 0:2

both fail with

Automatic encoder selection failed for output stream #0:0. Default encoder for format mpegts (codec none) is probably disabled. Please choose an encoder manually. Error selecting an encoder for stream 0:0

-c copy -map 0:a -map 0:v

Does exactly what the OP requested. Unfortunately, I can't vote your answer up, either. But I hope that anyone with the same question finds this!

Upvotes: 0

Arunas Bart
Arunas Bart

Reputation: 2718

It seems that specific ffmpeg versions ignore -c copy option and skip audio stream copy, thus resulting in final file with no audio, e.g. does not copy audio tracks and produce video with no sound.

The ffmpeg affected is for example used on Synology Disk Station devices:

ffmpeg version 2.7.7 Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 4.9.3 (crosstool-NG 1.20.0) 20150311 (prerelease)

To resolve that, without analyzing file structure and manually mapping all audio streams with -map 0:1 -map 0:2 etc, I found very simple command to process it automatically:

ffmpeg -i INFILE -map 0 -c copy -c:a copy OUTFILE

This is different from -c:v -c:a as preserves chapters and subtitles together with video and all audio tracks with different languages, like english, spanish, french, russian or chineese.

Also in case you have more hardly broken file, which simple copy does not fix, please try this command, which potentially fix more errors, which could crash video player, or stuck video or audio:

ffmpeg -err_detect ignore_err -i INFILE -map 0 -c copy -c:a copy OUTFILE

Upvotes: 0

PRIHLOP
PRIHLOP

Reputation: 1619

FFmpeg have option to map all streams to output, you have to use option -map 0 to map all streams from input to output.

In full line it might look like:

ffmpeg -i in.mp4 -c copy -map 0 out.mp4

For more info see the documentation on stream selection and the -map option.

Upvotes: 62

Aquarius Power
Aquarius Power

Reputation: 3985

First I tried this broader answer here: https://stackoverflow.com/a/54616353/1422630

But I had trouble with a not supported subtitle track so I ended having to use this command:

avconv -i INFILE -c copy -map 0:a -map 0:v OUTFILE

I understand that, after I asked to copy, it basically copied only what I mapped (and it mapped all audio of course), as I don't care for the subtitles being embedded at all. If you want to map the subtitles, just add this -map 0:s.

Upvotes: 1

Dotl
Dotl

Reputation: 1498

Apparently this is a popular question, so I'm posting my solution as an answer (was previously a comment reply) so that others can see.

I managed to find the correct syntax from this ticket. The correct syntax is:

ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0:0 -map 0:1 -map 0:2 out.mp4

This will copy all 3 streams.

Upvotes: 24

user2832874
user2832874

Reputation:

OK, I read pretty deep into the ffmpeg man page and found this which should be useful:

Note that currently each output stream can only contain channels from a single input stream; you can't for example use "-map_channel" to pick multiple input audio channels contained in different streams (from the same or different files) and merge them into a single output stream. It is therefore not currently possible, for example, to turn two separate mono streams into a single stereo stream. However splitting a stereo stream into two single channel mono streams is possible.

If you need this feature, a possible workaround is to use the amerge filter. For example, if you need to merge a media (here input.mkv) with 2 mono audio streams into one single stereo channel audio stream (and keep the video stream), you can use the following command:

ffmpeg -i input.mkv -filter_complex "[0:1] [0:2] amerge" -c:a pcm_s16le -c:v copy output.mkv

You may want to read through and experiment with the man page instructions on man ffmpeg-filters to understand just what level of complexity you're getting into for naming channels and expected output.

[Edit: As Mulvya noted, this answers a question, but it was not quite the original poster's question.]

Upvotes: 2

Related Questions