Возникли проблемы с пониманием команды ffmpeg -map

Возникли проблемы с пониманием команды ffmpeg -map

Я пытаюсь скопировать видео/аудио из контейнера mkv в mp4. При запуске ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4я не получаю видео с польским звуком. Есть только один видеопоток, поток #0:0. Поток #0:1 - это польское аудио, #0:2 - английский, а #0:3 - #0:5 - это субтитры.

Я читаюFFmpeg Wiki: Картано не понимаю его на самом деле. Почему -map 0:1написано дважды в примере 1? Что делает -c:s? Как будет выглядеть команда для копирования #0:0 в видео и #0:2 в аудио?

решение1

-map <inputNo>:<streamNo>говорит ffmpeg принять потокпотокНетот входавводНети добавить его к выводу, где <inputNo>начинается с 0.

Иногда вам может понадобиться взять один и тот же входной поток дважды (как -map 0:1 -map 0:1в примере), поскольку вы можете закодировать каждый с разными кодеками/параметрами. В примере выход содержит один и тот же аудиопоток дважды, один в MP3, а другой в AAC.

По умолчанию (т.е. без -mapкакой-либо команды) из входов берется один видео, один аудио и один поток субтитров. Если вы хотите сопоставить все потоки из одного входа, используйте -map <inputNo>.

То, что вы не получаете видео с помощью вашей команды, может означать только одно: ваша видеодорожка закодирована кодеком, который может быть мультиплексирован в MKV, но не в MP4. Поэтому он автоматически отбрасывается. Можете ли вы опубликовать лог, ffmpeg -i input.mkvчтобы мы могли проверить, какими кодеками закодированы дорожки?

Наконец, -c:sиспользуется для кодека субтитров (в то время как -c:aдля аудио и -c:vвидео)

решение2

Это был пример, который позволил мне понять. Представьте себе следующую команду:

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 

А вот как ffmpeg выполняет сопоставление:

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)

Что случилось?

В команде у нас только один ввод: tear_of_steel.mkv. Вот почему все наши карты начинаются с #0:...

Затем мы пишем первую опцию карты: -map 0:0, которая ссылается на первый поток наших входных данных (tears_of_steel.mkv), который может быть видеопотоком, но это не имеет значения.

Поскольку это первый вариант карты, он будет сопоставлен с первым потоком в нашем выходном файле (tears_of_steel-v2.mkv).

Затем мы пишем вторую опцию карты: -map 0:2, которая ссылается на третий поток нашего ввода. Поскольку это вторая опция карты, она сопоставляется со вторым потоком в нашем выводе.

И так далее...

Я написал это на своем github:https://github.com/lingtalfi/ffmpeg-notes/blob/master/ffmpeg-map.md

решение3

Вот как работают опции -c(выбор кодеков) и -map(выбор потоков):

-c:a -> select first or best supported audio (transcoded)
-c:a copy -> best supported audio (copied)
-map 0:a -> all audio from 1st input file (transcoded)
-map 1:a:0 -> 1st audio stream from 2nd input file (transcoded)
-map 1:a:1 -c:a copy -> 2nd audio stream from 2nd input file (copied)

Чтобы скопировать все потоки субтитров из первого входного файла без перекодирования:

-map 0:s -c:s copy 

Ваш выходной файл — mp4, а входной файл — mkv, и вы выбрали вывод видео без перекодирования ( -c:v copy) в совместимый с mp4 формат, поэтому в итоге вы получаете файл mp4 без (воспроизводимого) видео.

Либо укажите видеокодер, совместимый с mp4, например, -c:v libx264вместо -c:v copyили оставьте это поле пустым (т.е. не упоминайте кодер и ffmpeg)выбранные кодировщики будут зарегистрированы по умолчанию для каждого выходного формата)

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

ffmpeg -i input.mkv -map 0:0 -c:v libx264 -map 0:2 -c:a copy output.mp4

решение4

Это простой ответ для таких людей, как я, которые любят простые рабочие объяснения. Это решение, когда вы копируете mkv в mp4 и хотитевыбрать аудиопотоки:

Тебе нужно написать-map 0:числопотоковминусодинперед -c:a копия

Допустим, у видео 3 потока (это можно увидеть в mediainfo). Первый поток — видео, второй — аудио по умолчанию, а третий — нестандартное аудио на нужном вам языке. Поэтому вам нужно написать -map 0:2, а НЕ -map 0:3

Также вам нужно написать-map 0:0 перед -c:v копироватьпотому что если вы этого не сделаете, ffmpeg не будет копировать видеопоток, и вы получите только аудиопоток (если видео имеет два видеопотока и вы хотите скопировать второй, вам нужно написать -map 0:1)

Итакфинальная командная строкавыглядит так:

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

В этом случае вы получите первый видеопоток и третий аудиопоток.

Другой пример:

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

В этом случае вы должны получить второй видеопоток и седьмой аудиопоток.

надеюсь, это поможет

Связанный контент