FFmpeg | Выбор потоков (map)
от aNNiMON
Выбор потоков может потребоваться для создания копии файла с нужными потоками или для случаев, когда нужно скопировать видео- или аудиодорожку из одного файла в другой.
Форматы
-map индекс — выбирает все потоки указанного файла (-map 1)
-map индекс:тип_потока — выбирает все потоки заданного типа (-map 1:v)
-map индекс:номер_потока — выбирает конкретный поток по номеру (-map 1:0)
-map индекс:тип_потока:номер_потока — выбирает конкретный поток по номеру и с указанным типом (-map 1:v:0)
В качестве индекса может быть число или название потока, которое мы задаём в -vf / -filter_complex.
Если указать отрицательный индекс, поток будет исключён (-map -0:v)
Тип потока может быть:
- v (video) — видео (включая обложки, статичные изображения)
- V (video) — видео (только видео, не изображения)
- a (audio) — аудио
- s (subtitles) — субтитры
- d (data) — данные
- t (attachment) — вложения
Есть видео без звука и отдельная звуковая дорожка в mp3. Объединить эти два потока в видео со звуком:
Если звуковая дорожка окажется длиннее, чем видео, то по окончанию видео будет чёрный экран, а звук продолжится. Чтобы ограничить результат по длинне самого короткого потока, используется ключ -shortest
Даны два mp4 видео, заменить звук во втором видео звуком из первого видео без перекодирования:
Дано видео со звуком и отдельный mp3 файл. Добавить звуковую дорожку в видео второй дорожкой так, чтобы было два аудиопотока.
Есть mkv-файл в котором одна видеодорожка, две аудиодорожки с разными озвучками и один поток субтитров.
Нужно вшить субтитры и сформировать два mp4-видео с разными озвучками.
Решение:
1. Вытаскиваем файл субтитров из контейнера в отдельный файл
2. Применяем фильтр ass, раздваиваем видеопоток (по одному на каждый файл результата) и выбираем нужный поток аудио с копированием
Раздваивать потоки обязательно, иначе видео с хардсабом пойдёт только в первый файл.
Перед началом обработки ffmpeg выдаст информацию о назначении потоков
Это поможет убедиться, что всё настроено правильно.
Если, к примеру, забыть указать -c:a copy перед вторым результирующим файлом, то ffmpeg выдаст:
Последняя строка говорит о том, что для второго файла (индекс 1) происходит перекодирование из aac в aac, а это явно не то, чего мы желали.
Следующая статья →Форматы
-map индекс — выбирает все потоки указанного файла (-map 1)
-map индекс:тип_потока — выбирает все потоки заданного типа (-map 1:v)
-map индекс:номер_потока — выбирает конкретный поток по номеру (-map 1:0)
-map индекс:тип_потока:номер_потока — выбирает конкретный поток по номеру и с указанным типом (-map 1:v:0)
В качестве индекса может быть число или название потока, которое мы задаём в -vf / -filter_complex.
Если указать отрицательный индекс, поток будет исключён (-map -0:v)
Тип потока может быть:
- v (video) — видео (включая обложки, статичные изображения)
- V (video) — видео (только видео, не изображения)
- a (audio) — аудио
- s (subtitles) — субтитры
- d (data) — данные
- t (attachment) — вложения
Есть видео без звука и отдельная звуковая дорожка в mp3. Объединить эти два потока в видео со звуком:
- ffmpeg -i input.mp4 -i audio.mp3 -c:v copy -map 1:a result.mp4
Если звуковая дорожка окажется длиннее, чем видео, то по окончанию видео будет чёрный экран, а звук продолжится. Чтобы ограничить результат по длинне самого короткого потока, используется ключ -shortest
Даны два mp4 видео, заменить звук во втором видео звуком из первого видео без перекодирования:
- ffmpeg -i a.mp4 -i b.mp4 -map 0:a -map 1:v -c copy -shortest b_result.mp4
Дано видео со звуком и отдельный mp3 файл. Добавить звуковую дорожку в видео второй дорожкой так, чтобы было два аудиопотока.
- ffmpeg -i input.mp4 -i audio.mp3 -map 0 -map 1:a -c:v copy result.mp4
Есть mkv-файл в котором одна видеодорожка, две аудиодорожки с разными озвучками и один поток субтитров.
- ffmpeg -i input.mkv
- Duration: 00:50:28.07, start: 0.000000, bitrate: 2104 kb/s
- Stream #0:0: Video: h264 (High), yuv420p(progressive), 1280x720, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
- Stream #0:1(rus): Audio: aac (LC), 48000 Hz, stereo, fltp (default)
- Stream #0:2: Audio: aac (LC), 48000 Hz, stereo, fltp
- Stream #0:3: Subtitle: ass (default)
Решение:
1. Вытаскиваем файл субтитров из контейнера в отдельный файл
- ffmpeg -i input.mkv 1.ass
- ffmpeg -i input.mkv ^
- -filter_complex ass=1.ass,split[v1][v2] ^
- -map "[v1]" -map 0:a:0 -c:a copy v1.mp4 ^
- -map "[v2]" -map 0:a:1 -c:a copy v2.mp4
Перед началом обработки ffmpeg выдаст информацию о назначении потоков
- Stream mapping:
- Stream #0:0 (h264) -> ass
- split:output0 -> Stream #0:0 (libx264)
- Stream #0:1 -> #0:1 (copy)
- split:output1 -> Stream #1:0 (libx264)
- Stream #0:2 -> #1:1 (copy)
Если, к примеру, забыть указать -c:a copy перед вторым результирующим файлом, то ffmpeg выдаст:
- Stream mapping:
- Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
- Stream #0:1 -> #0:1 (copy)
- Stream #0:0 -> #1:0 (h264 (native) -> h264 (libx264))
- Stream #0:2 -> #1:1 (aac (native) -> aac (native))
ffplay