Понимаем FFmpeg

author

FFmpeg — это набор библиотек для обработки видео и аудио файлов. FFmpeg сконвертирует mov в mp4, наложит водяной знак, склеит несколько видео файлов в один, поменяет разрешение, перекодирует потоковое видео, создаст поток сам. FFmpeg полезен для тех, кто профессионально работает с видео, разрабатывает медиа приложения или просто обрабатывает домашние записи.

FFmpeg не имеет графического интерфейса и управляется командами из консоли. Многие пользователи работают с ним, копируя нужные команды из интернета, не понимая, что значит тот или иной флаг. Научимся осознанно работать с FFmpeg на примере нескольких полезных команд.

Сегодня мы пройдем путь от получения информации о файле до применения нескольких фильтров одновременно, решая задачи, с которыми часто сталкиваешься при работе с видео. Установим ffmpeg и вперед!

Получаем информацию о файле

ffmpeg -i file.mp4

Тут все просто, вводим путь к файлу, получаем информацию о нем: кодеки, количество дорожек, разрешение, битрейт и фреймрейт. Мы указываем пути к файлам флагом -i (input):

-i file1.mp4 -i file2.mp4.

Конвертируем в mp4

Допустим у нас есть сайт, на котором видео проигрывалось через Flash плеер. Мы хотим поменять его на HTML5 Video. Для этого конвертируем видео файлы на сервере из flv формата в mp4.

ffmpeg -i flashvideo.flv -vcodec libx264 -acodec libvo_aacenc output.mp4

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

  • output.mp4 — путь к сконвертированному файлу.
  • -vcodec libx264 — указываем какой видео кодек хотим получить. В нашем случае это H264, который поддерживается большинством браузеров.
  • -acodec libvo_aacenc — аудио кодек AAC.

Список поддерживаемых вашим ffmpeg кодеков можно получить через ffmpeg -codecs.

Вместо -vcodec встречается запись -codec:v и -c:v. Если не указать кодеки для конвертации ffmpeg -i flashvideo.flv output.mp4, то ffmpeg установит дефолтные кодеки для формата файла на выходе.

При конвертации задают не только кодеки. Увеличим число настроек:

ffmpeg -i flashvideo.flv -b:v 700k -r 25 -pix_fmt yuv420p -vcodec libx264 \
-b:a 128k -ar 44100 -acodec libvo_aacenc -y output.mp4

Мы установили битрейт для видео -b:v и аудио -b:a в 700 и 128 кб/c. Битрейт можно обозначить другими флагами: -vb и -b для видео или -ab для аудио.

Оставшиеся три параметра — это фреймрейт -r 25 в кадрах в секунду, цветовая модель YUV равная обычному значению yuv420p и частота дискретизации звука 44100 Гц. Флаг -y нужен для перезаписи файла, если он уже существует.

Вырезаем фрагмент видео

ffmpeg -ss 10 -t 20 -i source_video.mp4 -vcodec copy -acodec copy result.mp4

Флагом -ss указываем с какого момента исходного видео обрезаем, -t — продолжительность. На выходе мы получим двадцати секундное видео, которое начнется с десятой секунды исходного. Запись -ss 00:00:10.250 -t 00:00:20.120 пригодится для указания более точного промежутка времени. До версии 2.1 FFmpeg в обоих случаях обрезал видео по ближайшему ключевому кадру. В новых версиях итоговое видео максимально близко к указанному интервалу.

Мы добавили -vcodec copy -acodec copy, чтобы сохранить кодеки исходного видео. Иначе ffmpeg перекодировал бы их в кодеки по умолчанию. Сейчас видео не перекодируется и команда выполнится быстро. Дальше упростим эту запись флагом -c copy.

Если расположить флаги -ss и -t после входящего видео, то итоговое видео будет таким же, но команда будет выполняться дольше. Флаги будут относиться к итоговому видео и FFmpeg будет декодировать фрагмент видео до -ss. В первом случае эта часть будет проигнорирована.

Флаг -t можно заменить на -to, указав вместо продолжительности конечную точку. Этот флаг нельзя применить к входящему видео:

ffmpeg -ss 10 -i source_video.mp4 -to 30 -c copy result.mp4

Команда дала нам другой результат: тридцати секундное видео с десятой секунды исходного. Это произошло, потому что -to использовал временную шкалу result.mp4, тридцатая секунда на котором равна сороковой секунде source_video.mp4. Чтобы использовать исходную шкалу добавим флаг -copyts. Так мы получим такое же видео, как от первой команды:

ffmpeg -ss 10 -i source_video.mp4 -to 30 -copyts -c copy result.mp4

Фильтры. Меняем разрешение

Один из самых мощных инструментов ffmpeg — фильтры. Они могут добавлять эффекты, накладывать разные видео друг на друга, сшивать несколько файлов в один. Увидеть список установленных фильтров мы можем по команде ffmpeg -filters. Изменим с их помощью разрешение видео:

ffmpeg -i source_video.avi -vf scale=640:480 source_preview.avi

Мы использовали флаг -vf, указав фильтр scale и разрешение 640:480. Этот фильтр может сохранять пропорции и вычислять разрешение динамически.

Объединение фильтров. Ускоряем воспроизведение

ffmpeg -i source_video.mp4 \
-filter_complex "[0:v]setpts=0.5*PTS;[0:a]atempo=2.0" accelerated.mp4

Мы объединили несколько фильтров в один флагом filter_complex и получили ускоренный в два раза файл. Чтобы разобраться применим фильтры по одиночке.

ffmpeg -i source_video.mp4 -vf setpts=0.5*PTS accelerated_video.mp4

Мы ускорили воспроизведение видео дорожки фильтром setpts. Однако аудиодорожка не изменилась, и файл получится той же продолжительности что и был: видео проиграется в 2 раза быстрее, а последний кадр будет висеть всю вторую половину файла. Если убрать аудио дорожку флагом -an, то длительность итогового файла будет определяться по видео дорожке и будет в два раза меньше исходной.

Наоборот, если нужна только ускоренное аудио без видео, воспользуемся фильтром atempo, а флагом vn уберем видео дорожку.

ffmpeg -i source_video.mp4 -af atempo=2.0 -vn accelerated_audio.mp3

Добавив filter_complex и применив оба фильтра, мы ускорили файл целиком.

Граф фильтров применяет последовательность из нескольких фильтров к исходному файлу. Мы указали ускорение setpts для видео дорожки [0:v] и atempo для аудио [0:a]. С помощью комбинаций фильтров мы можем решить большинство задач по редактированию видео.

Склеиваем файлы в один

ffmpeg -i input1.mp4 -i input2.mp4  \
-filter_complex  "[0:0] [0:1] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" -y output.mp4

Мы видим новый флаг map. Он указывает ffmpeg какие дорожки хотим получить в итоговом файле. Если в наших исходных видео файлах гарантировано одна видео и аудио дорожка, и столько же мы хотим получить на выходе, то флаг map не нужен. Другие примеры использования Map можно посмотреть на сайте ffmpeg.

Выполним ту же операцию другим методом:

ffmpeg -f concat -i list.txt -c copy output.mp4

В FFmpeg есть элементы, которые читают или записывают медиа в определенных форматах. Они называются демультиплексор и мультиплексор. -f concat — это демультиплексор, который принимает текстовый файл, со списком медиа файлов и склеивает их в один. Посмотреть другие элементы можно командой ffmpeg -formats.

Содержимое list.txt:

file 'input1.mp4'
file 'input2.mp4'

Такой метод удобен, если у нас много файлов и надо склеить их друг за другом. Он не перекодирует видео и работает быстрее первого метода.

Но первый метод применяется чаще. Во-первых, он может принять на вход видео с разными кодеками. Во-вторых, дает большую гибкость. Например, если нужна только часть первого видео, мы можем воспользоваться флагами -ss и -t. Обратите внимание, эти флаги действуют только на первый файл input1.mp4.

ffmpeg -ss 5 -t 2 -i input1.mp4  -i input2.mp4 \
-filter_complex  "[0:0] [0:1] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" -y result.mp4

Водяной знак

Последний пример, который мы рассмотрим — это наложение водяного знака. Фильтр overlay принимает на вход координаты расположения водяного знака на итоговом видео.

Расположим водяной знак по центру. Зная размер исходного видео и png картинки, можно вычислить координаты самим. Например при видео 1280×720 и водяном знаке 200×200, положение по горизонтали x = (1280 - 200) / 2 = 540 и по вертикали y = (720 - 200) / 2 = 260. Соответственно значение фильтра "overlay=540:260". Однако удобнее написать универсальную команду, чтобы ffmpeg посчитал все за нас. Размер видео получим из параметров main_w и main_h, а водяного знака из overlay_w и overlay_h. Далее ту формулу, по которой мы вычисляли координаты запишем в значение фильтра "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2". Готово, мы получили команду для наложения водяного знака по центру:

ffmpeg -i source_video.mp4 -i watermark.png \
-filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" \
-codec:a copy video_protected.mp4

FFmpeg — мощный инструмент для работы с видео. Решение других задач с его помощью можно посмотреть в статье 19 команд ffmpeg для всех нужд.

Плюсануть
Отправить
Поделиться