Практическое руководство по FFmpeg: Часть 3

3-я часть описания пакета FFmpeg и практических примеров его использования.
Это третья часть статьи, первая находится здесь.

Командная строка FFmpeg

Я буду описывать только подмножество синтаксиса командной строки. Впрочем, его хватит для практически любых ситуаций. Общий вид командной строки:

ffmpeg общие_параметры входные_файлы описание_фильтров выходные_файлы
  • общие_параметры — общие параметры программы, разделенные пробелами. В документации им соответствует раздел «5.2 Generic options». Здесь в основном указывается, какая информация о работе программы выводится в консольное окно. Я сам, например, всегда добавляю опцию -hide_banner (не показывать информацию об авторских правах и конфигурации утилиты).
  • входные_файлы — список описаний входных файлов, разделенных пробелами. Каждое описание входного файла имеет вид
  • параметры_файла -i имя_файла
  • выходные_файлы — список описаний выходных файлов, построенный примерно по тем же принципам, что и входных и примерно с теми же опциями, с той разницей, что -i не включается:
  • параметры_файла имя_файла
  • параметры_файла — параметры файла, разделенные пробелами. Каждый из них относится только к тому входному или выходному файлу, который непосредственно следует после группы параметров.
  • описание_фильтров — см. подразделы «Простое описание фильтров» и «Сложное описание фильтров» ниже.

Пример

C:\Bin\ffmpeg -hide_banner -ss 6:52 -i "a.avi" -vf loop=start=0:size=1:loop=-1 -t 5 "b.mkv"
  1. Берем входной файл (опция -i "a.avi").
  2. Вырезаем из него часть, которая начинается с 6-й минуты 52-й секунды (опция -ss 6:52).
  3. Применяем к ее видео потоку (опция -vf) фильтр loop с аргументами start=0:size=1:loop=-1. То есть берем один (опция size=1) самый первый кадр (опция start=0) и повторяем его бесконечное количество раз (опция loop=-1). Аудио поток остается неизменным.
  4. Из видео после фильтра и исходного аудио потоков вырезаем первые 5 секунд (опция -t 5).
  5. Записываем результат в файл (опция "b.mkv").

Простое описание фильтров

Описание фильтров может быть простым или сложным. Простое описание фильтров состоит из описаний фильтров видео (-vf) и/или аудио (-af) потоков, разделенных пробелами:
-vf цепочка_фильтров
-af цепочка_фильтров
  • цепочка_фильтров — описания индивидуальных фильтров, разделенные запятыми. Каждый из фильтров выполняет какое-то преобразование входного потока и передает результаты на вход следующему фильтру. Каждое описание состоит из имени фильтра и, возможно, его аргументов:
  • имя_фильтра
    имя_фильтра=аргументы_фильтра
  • аргументы_фильтра — описания индивидуальных аргументов, разделенные двоеточиями. Аргумент может быть позиционным или именованным. Если аргумент позиционный, то он включат только значение, а имя аргумента определяется его позицией в списке, которую вы можете узнать из документации по конкретному фильтру. Если аргумент именованный, то его описание включает имя аргумента и его значение. Если какому-то аргументу не задано значение, то берется значение по умолчанию.
  • значение_аргумента
    имя_аргумента=значение_аргумента

Примеры простого описания фильтров

Самый первый пример приведен в подразделе «Пример» выше, в нем используется именно простое (опция -vf) описание фильтров. Далее я буду демонстрировать, как может быть изменена часть -vf loop=start=0:size=1:loop=-1 командной строки.
  1. Использование позиционных аргументов. В описании аргументов фильтра мы использовали именованные аргументы start=0, size=1 и loop=-1. Идем в документацию по фильтру «39.117 loop». В нем аргументы перечислены в следующем порядке: 1. loop, 2. size и 3. start. Это означает, что мы может описать те же самые аргументы в виде:
  2. -vf loop=-1:1:0
  3. Добавление еще одного фильтра (затухание изображения продолжительностью 3 секунды) в цепочку.
  4. -vf loop=-1:1:0,fade=type=out:d=3
  5. Добавление описания фильтра для другого потока (нормализация уровня громкости). Фильтр в примере используется без аргументов.
  6. -vf loop=-1:1:0,fade=type=out:d=3 -af loudnorm

Сложное описание фильтров

Сложное описание фильтров имеет вид:
-filter_complex граф_фильтров маппинг_выходных_потоков
  • граф_фильтров — описания веток графа, разделенные точками с запятыми. Каждая ветка имеет вид (символом центральной точки · мы обозначаем отсутствие пробела):
  • список_входов·цепочка_фильтров·список_выходов
  • цепочка_фильтров — в том же формате, что и для простого описания фильтров, см. выше.
  • список_входов — список входных потоков и/или меток (без пробелов).
  • [описание_входного_потока]
    [имя_метки]
  • список_выходов — список меток (без пробелов).
  • [имя_метки]
  • маппинг_выходных_потоков — описания потоков выходного файла, разделенные пробелами. В выходном файле потоки будут включены именно в том порядке, в котором идут опции -map и только те, которые перечислены. Обратите внимание, что описание_входного_потока приводится без квадратных скобок.
  • -map описание_входного_потока
    -map [имя_метки]
  • описание_входного_потока — описание входного потока в одном из форматов:
  • индекс_входного_файла
    индекс_входного_файла:тип_потока
    индекс_входного_файла:тип_потока:индекс_потока_данного_типа_в_файле
    индекс_входного_файла:индекс_потока_в_файле
  • тип_потока — v, a или s для соответственно видео изображения, аудио и субтитров.
  • имя_метки — имя может включать буквы, цифры и символ подчеркивания. Каждая метка обязана появляться ровно один раз как входная и ровно один раз как выходная, иначе будет ошибка. Если имеется необходимость, то существуют специальные фильтры для дублирования меток.

Примеры сложного описания фильтров

Я опять буду демонстрировать, как может быть изменена часть -vf loop=start=0:size=1:loop=-1 командной строки из подраздела «Пример» выше.
  1. Пример, как можно поменять простое описание фильтров на сложное с полным сохранением функциональности. Используется описание из примера #3 подраздела «Примеры простого описания фильтров» выше.
  2. -vf loop=-1:1:0,fade=type=out:d=3 -af loudnorm
    -filter_complex [0:v]loop=-1:1:0,fade=type=out:d=3[v0];[0:a]loudnorm[a0] -map [v0] -map [a0]
  3. Немного более простое описание фильтров (пример #2 того же подраздела), где мы исключили loudnorm. Обратите внимание, что если мы не укажем -map 0:a в сложном описании фильтров, то в выходном файле совсем не будет звука.
  4. -vf loop=-1:1:0,fade=type=out:d=3
    -filter_complex [0:v]loop=-1:1:0,fade=type=out:d=3[v0] -map [v0] -map 0:a
  5. Более сложный пример, который невозможно реализовать с помощью простого описания фильтров.
    См., что означает символ ^ …

    Чтобы не вытягивать текст описания в одну длинную строчку, я буду использовать символ ^ командных файлов Windows переноса на следующую строку. То есть так, как этот текст может использоваться в командном файле. Если вы желаете использовать этот текст в командной строке, то удалите все символы ^ и переводы строк, следующих за ними.

    -filter_complex ^
    [0:v]trim=end=3[v0];^
    [0:a]atrim=end=3[a0];^
    [0:v]trim=start=3,setpts=PTS-STARTPTS,loop=-1:1:0,fade=type=out:d=2[v1];^
    [0:a]atrim=start=3,asetpts=PTS-STARTPTS,afade=type=out:d=2[a1];^
    [v0][a0][v1][a1]concat=n=2:v=1:a=1[vv][aa] ^
    -map [vv] -map [aa]
    Он помещает в выходной файл 5-секундное видео, где первые 3 секунды копируют входной поток, а оставшиеся 2 секунды заполнены затухающими звуком и изображением с остановившимся кадром. Пример почти совершенно практический, больша́я часть моих YouTube клипов создана похожим кодом. Например, вот этот:

Применение кавычек и символа \

Их необходимость связана с различной интерпретацией отдельных символов в различных частях командной строки. Например, см. описание выше: «входные_файлы — список описаний входных файлов, разделенных пробелами». Однако пробел также может являться частью имени файла.

Символами, интерпретируемыми специальным образом, могут быть пробелы, точки с запятой, запятые, двоеточия, квадратные скобки. Также одиночные и двойные кавычки, символ \ и другие.

Применение кавычек и символа \ описывается в разделе документации «7.1 Quoting and escaping». К сожалению, вы не можете им воспользоваться в качестве полного окончательного описания. Особенностью FFmpeg является то, что различные части командной строки интерпретируются по-разному. Практически:
Это и достоинство и недостаток. С одной стороны, вы не можете выучить один общий набор правил и применять его во всех ситуациях. С другой, в подавляющем большинстве ситуаций вы можете не заботиться о специальной интерпретации отдельных символов и их использование скорее всего будет соответствовать вашим интуитивным представлениям. Кроме того, командная строка будет проще и ее содержание будет проще восприниматься.
  • Если в аргументе имеется шанс появления пробелов, как в имени файла, то лучше поместить его в двойные кавычки.
  • Перед специальными символами (кроме тех, которые являются частью имени файла) помещайте символ \.

Не-ascii символы в командной строке

Время от времени вы будете сталкиваться с тем, что FFmpeg не будет понимать какой-то Unicode символ командной строки. Типичный пример — тире (то есть не короткий ascii дефис ‘-’, а длинное тире ‘‒’) в имени файла.

В обсуждениях в FFmpeg блогах утверждается, что это проблема не самого FFmpeg, а его окружения (в нашем случае Far Manager и командных файлов Windows). В тот момент, когда вы копируете строку и затем ее переносите в командную строку, отдельные символы могут преобразовываться в другой Unicode код.

В практике, если, например, ваш файл с подобным именем не распознается FFmpeg, просто переименуйте его.

Marple Mashu Marces AnimationОпубликовано 28 сентября 2020 г.
Последние изменения 20 ноября 2020 г.