Понимаем FFmpeg
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 для всех нужд.