FFmpeg не копирует все аудиопотоки

У меня проблемы с получением ffmpeg для копирования всех аудиопотоков из файла .mp4. Похоже, что после нескольких часов поиска в сети это должно скопировать все потоки (как показано в примере 4 здесь):

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

in.mp4 содержит 3 потока:

  • видео
  • Аудио трек 1
  • Аудио дорожка 2

out.mp4 (который должен быть идентичен in.mp4) содержит только 2 потока:

  • видео
  • Аудио трек 1

FFmpeg, кажется, правильно идентифицирует все 3 потока, но не копирует все из них. Выход из FFmpeg:

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

Изменить: Вывод из 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

Редактировать 2 (решено): мне удалось найти правильный синтаксис из этого билета. Для любых других заинтересованных сторон правильный синтаксис:

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

Это скопирует все потоки.

Ответ 1

Очевидно, это популярный вопрос, поэтому я публикую свое решение в качестве ответа (ранее был комментарием), чтобы другие могли видеть.

Мне удалось найти правильный синтаксис из этого билета. Правильный синтаксис:

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

Это скопирует все 3 потока.

Ответ 2

У FFmpeg есть возможность отобразить все потоки на выход, вы должны использовать опцию -map 0 чтобы отобразить все потоки от входа до выхода.

В полной строке это может выглядеть так:

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

Для получения дополнительной информации см. Документацию по выбору потока и -map.

Ответ 3

ОК, я прочитал довольно глубоко в man-странице ffmpeg и нашел это, что должно быть полезно:

Обратите внимание, что в настоящее время каждый выходной поток может содержать только каналы из один входной поток; вы не можете, например, использовать "-map_channel" для выбор нескольких входных аудиоканалов, содержащихся в разных потоках (из тех же или разных файлов) и объединить их в один вывод поток. Поэтому в настоящее время невозможно, например, два отдельных монопотока в один стереопоток. Однако разделение стереопотока на два одноканальных монопотока возможно.

Если вам нужна эта функция, возможно, обходное решение - использовать amerge фильтр. Например, если вам нужно объединить носитель (здесь input.mkv) с двумя монопольными аудиопотоками в один звуковой поток стереоканала (и сохраните видеопоток), вы можете использовать следующую команду:

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

Вы можете прочитать и поэкспериментировать с инструкциями справочной страницы на man ffmpeg-filters, чтобы понять, на какой уровень сложности вы входите, чтобы именовать каналы и ожидаемый результат.

[Edit: Как заметил Мульвия, это отвечает на вопрос, но это был не совсем оригинальный вопрос с плакатом.]

Ответ 4

Сначала я попробовал этот более широкий ответ здесь: fooobar.com/info/2338428/...

Но у меня были проблемы с неподдерживаемой дорожкой субтитров, поэтому я прекратил использовать эту команду:

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

Я понимаю, что после того, как я попросил скопировать, он в основном копировал только то, что я отобразил (и он, конечно, отобразил все аудио), так как мне все равно, какие субтитры будут вставлены вообще. Если вы хотите отобразить субтитры, просто добавьте это -map 0:s.