Задача, и почему это сложнее, чем кажется?

«Дайте мне один кадр в секунду из этого клипа» — одна из самых распространенных видеоработ. Тестировщику QA нужны скриншоты, расположенные на равном расстоянии друг от друга, чтобы прикрепить их к отчету об ошибке. Исследователю нужна выборочная последовательность изображений для использования в инструменте аннотаций. Социальному редактору нужно двадцать кадров-кандидатов из двухминутной версии, не перебирая хронологию вручную.

Сама задача проста. Что делает его неудобным, так это то, что «один кадр в секунду» становится двусмысленным, если присмотреться. Вы имеете в виду один кадр на каждую секунду времени воспроизведения или на каждую? Нет-й кадр закодированного потока? Это разные вещи: клип со скоростью 24 кадра в секунду и клип со скоростью 60 кадров в секунду дают одинаковый результат при первом чтении и совершенно разные значения при втором. Выберите неправильный, и вы либо получите папку с почти дубликатами, либо последовательность слишком разреженная, чтобы быть полезной.

Оба подхода ниже создают идентичные пиксели. Они отличаются тем, как вы выражаете то, что хотите, и тем, как быстро вы обнаруживаете, что выразили это неправильно.

Метод 1: FFmpeg, параметр за параметром

Каноническая команда короткая:

ffmpeg -i input.mp4 -vf fps=1 -q:v 2 frame_%04d.jpg

Каждая деталь имеет значение:

  • -i input.mp4 — исходный файл. FFmpeg читает его один раз, от начала до конца; он не ищет каждую временную метку индивидуально.
  • -vf fps=1 — видеофильтр, который выполняет фактическую работу. fps=1 означает один выходной кадр в секунду во время воспроизведения, независимо от частоты кадров источника. Использование fps=1/5 для одного кадра каждые пять секунд или fps=2 для двух в секунду. Это показания времени воспроизведения.
  • -q:v 2 — качество JPEG в инвертированной шкале, где 2 — почти без потерь, а 31 — сильное сжатие. Опустите его, и вы получите значение по умолчанию FFmpeg, которое заметно мягче, чем ожидает большинство людей. Если вам нужен вывод без потерь, напишите frame_%04d.png вместо этого и полностью отбросьте этот флаг.
  • frame_%04d.jpg  — шаблон вывода. %04d дополняет счетчик нулями до четырех цифр: frame_0001.jpg, frame_0002.jpg. Набивка не является косметической; см. проблему нумерации ниже.

Если вам нужно другое чтение — каждый Нет-й закодированный кадр, а не каждый Нет секунды — фильтр меняется:

ffmpeg -i input.mp4 -vf "select=not(mod(n\,10))" -vsync vfr frame_%04d.png

Это сохраняет кадры, в которых индекс кадра n делится на 10 и -vsync vfr не позволяет FFmpeg дублировать кадры, чтобы обеспечить постоянную скорость вывода. Оставьте этот флаг выключенным, и вы получите гораздо больше файлов, чем запрашивали, что является частым и запутанным первым результатом.

Чтобы ограничить работу сегментом, добавьте -ss до -i поэтому FFmpeg выполняет поиск перед декодированием, а не декодированием и удалением:

ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -vf fps=1 frame_%04d.png

Метод 2: то же задание в браузере

Frame Extractor на этом сайте сопоставляется с одними и теми же двумя показаниями, причем двусмысленность явно выражена в интерфейсе, а не скрыта в строке фильтра.

  1. Закиньте файл. Он считывается прямо с диска в память браузера — загрузка отсутствует, поэтому источник размером 3 ГБ начинает обрабатываться сразу, а не после передачи.
  2. Выберите метод извлечения. «Интервал времени» эквивалентен fps=1/N — вы вводите промежуток в секундах. «Частота кадров (FPS)» эквивалентна select/mod фильтр — вы вводите Нет чтобы сохранить каждый Нет-й кадр.
  3. Прочитайте подсказку о количестве кадров перед извлечением. Это та часть, которая экономит больше всего времени. Интерфейс показывает, сколько изображений создадут ваши текущие настройки. до все работает, поэтому ошибка в 4000 файлов становится числом, которое вы видите, а не папкой, которую вы обнаруживаете.
  4. Установить формат и качество. PNG для без потерь, JPG или WebP с ползунком 10–100 %, когда размер имеет значение. Положение ползунка соответствует тому, что -q:v элементы управления выражали то, как об этом думает большинство людей.
  5. При необходимости обрежьте диапазон. Ползунок с двумя ручками — это -ss/-to эквивалент, с метками времени, отображаемыми при перетаскивании.
  6. Экспорт. Кадры отображаются в сетке предварительного просмотра; щелкните один, чтобы сохранить его отдельно, или возьмите весь набор как один ZIP.

Правило Удобный выбор интервала: для говорящей головы или записи экрана, захватывается 1 кадр каждые 2–5 секунд каждое значимое изменение состояния. Для спорта или чего-либо с быстрым движением — 2–5 кадров в секунду. Зарезервируйте «каждый кадр» для подлинного анализа с точностью до кадра: минута со скоростью 60 кадров в секунду — это 3600 изображений и несколько гигабайт PNG.

Три проблемы, которые на самом деле стоят людям времени

1. На выходе — тысячи почти идентичных кадров.

Почти всегда путаница единиц: вы имели в виду "каждый 10-й кадр" и написали fps=10, что означает десять кадров в секунду — на источнике с частотой 30 кадров в секунду, что дает в 3 раза больше изображений, чем наивное ожидание, а не в 3 раза меньше.

Прежде чем что-либо запускать, сделайте арифметику. Режим времени воспроизведения: duration ÷ interval. Индексный режим кадра: duration × source_fps ÷ N. 10-минутный клип со скоростью 30 кадров в секунду на «каждом 10-м кадре» — это 600 × 30 ÷ 10 = 1800 изображений. Если это число вас удивляет, скорректируйте его до начала, а не после. В браузере та же цифра автоматически появляется под полем интервала.

2. В середине длинного видео эвакуация останавливается.

Разные причины с каждой стороны, поэтому и способы устранения тоже различаются.

При использовании FFmpeg зависание обычно связано с диском — тысячи PNG приземляются в одном каталоге, и узким местом становится файловая система, а не декодер. Запишите в новый пустой каталог, выберите JPG, если вам не нужен формат без потерь, и разбейте очень длинные источники на сегменты с -ss/-to.

В браузере ограничение составляет ОЗУ: каждый извлеченный кадр хранится в памяти до тех пор, пока вы не загрузите ZIP. Несколько сотен 4K PNG — это несколько гигабайт и за это можно убить вкладку. Надежный шаблон — работать порциями: используйте ползунок временного диапазона, чтобы выбрать 0:00–2:00, загрузите ZIP, а затем переместите диапазон на 2:00–4:00. Закрытие других вкладок перед выполнением большого задания действительно помогает, а JPG с качеством 85–90 % снижает нагрузку на память в несколько раз без видимой разницы для большинства применений.

3. Нумерация кадров нарушает порядок импорта.

Этот фрагмент после экспорта выглядит нормально. Инструменты, которые сортируют имена файлов в виде текста — и большинство из них — упорядочивают frame_10.png до frame_2.png, поскольку "1" сортируется перед "2" посимвольно. Ваша последовательность воспроизводится в зашифрованном виде, и непонятно почему.

Исправление — это заполнение нулями, достаточно широкое для максимального количества, которое вы когда-либо видели. производить. Вот что %04d предназначено для; use %05d если вы можете превысить 9999 кадров. Инструмент браузера автоматически дополняет данные, что является основной причиной того, что его выходные данные имеют тенденцию передаваться прямо в импортер последовательности изображений без переименования.

Когда FFmpeg по-прежнему является правильным выбором

Множество время. Это не тот случай, когда браузер выигрывает по всем показателям:

  • Все, что запланировано или запланировано. Задание cron, этап CI, серверный конвейер — браузер вообще не может участвовать в них.
  • Пакеты по многим файлам. Цикл оболочки более 200 клипов тривиален в FFmpeg и утомителен где-либо еще.
  • Кодеки, которые браузер не декодирует. ProRes, DNxHD, необработанные форматы камеры, необычные контейнеры. Если браузер не может воспроизвести его, он не сможет извлечь из него данные. FFmpeg обрабатывает практически все.
  • Фильтрация во время экстракции. Деинтерлейсинг, масштабирование, преобразование цветового пространства, обрезка, обнаружение смены сцены — все это доступно в виде фильтров за один проход.
  • Воспроизводимость. Команда в README точна. «Установить ползунок примерно здесь» — нет.

Инструмент браузера лучше подходит для разовых задач, для всех, кто не хочет устанавливать и поддерживать набор инструментов для случайных задач, когда источник достаточно конфиденциальен, и важна только локальная обработка, и когда вы хотите просмотреть кадры перед экспортом. Это действительно разные ситуации, а не рейтинг.

Краткая справка

Что вы хотите FFmpeg Браузерный инструмент
Один кадр в секунду -vf fps=1 Time Interval = 1
Один кадр каждые 5 секунд -vf fps=1/5 Time Интервал = 5
Каждый 10-й закодированный кадр -vf "select=not(mod(n\,10))" -vsync vfr Режим частоты кадров, N = 10
Только от 1:30 до 2:15 -ss 00:01:30 -to 00:02:15 Ползунок временного диапазона
Вывод без потерь .png шаблон вывода Формат = PNG
Файлы меньшего размера -q:v 5 with .jpg JPG + ползунок качества
Просмотрите счетчик перед запуском Рассчитать вручную Отображается под полем интервала
Предварительный просмотр перед сохранением Откройте папку вывода Встроенная сетка предварительного просмотра
Автоматизация / пакетная обработка Цикл оболочки, cron, CI Нет возможно
ProRes, DNxHD, raw Поддерживается Только то, что декодирует браузер

Какой бы маршрут вы ни выбрали, на первом месте принимается решение об интервале, а на втором — инструмент. Определите, сколько кадров вам действительно нужно, подтвердите подсчет перед началом, а все остальное - механическое дело.