
Я пытаюсь скопировать видео/аудио из контейнера 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"
В этом случае вы должны получить второй видеопоток и седьмой аудиопоток.
надеюсь, это поможет